PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 2.3.1
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v2.3.1
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.9 2.2.8 trunk 1.10 1.3.3 1.3.4 1.3.5 1.3.5.1 1.3.5.2 1.3.6 1.3.6.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.5 All 103 releases
imagify / docs / api / tracking.md

tracking.md in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF 2.3.1, at docs/api/tracking.md

137 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 # Tracking Module
2
3 The `Imagify\Tracking` module wires the `wp-media/wp-mixpanel` Composer package into Imagify's DI layer and fires analytics events to Mixpanel when media optimization completes.
4
5 ---
6
7 ## Architecture
8
9 | Class | Role |
10 |---|---|
11 | `Imagify\Tracking\BaseTracking` | Abstract base: `can_track()`, `get_default_event_properties()`, `identify_user()` |
12 | `Imagify\Tracking\Tracking` | Concrete: `track_media_optimized()`, `track_settings_saved()` |
13 | `Imagify\Tracking\Subscriber` | Subscribes to WordPress hooks and delegates to `Tracking` |
14 | `Imagify\Tracking\ServiceProvider` | Registers all module services into the DI container |
15
16 The module depends on two Strauss-prefixed vendor classes:
17
18 - `Imagify\Dependencies\WPMedia\Mixpanel\Optin` — manages opt-in state
19 - `Imagify\Dependencies\WPMedia\Mixpanel\TrackingPlugin` — sends events to Mixpanel
20
21 ---
22
23 ## User identification (`distinct_id`)
24
25 Mixpanel needs a `distinct_id` on every event to compute user-level metrics — MAU/DAU, retention, cohorts, funnels, unique users by feature. Without it, events are only aggregatable in bulk.
26
27 `BaseTracking::identify_user()` registers it by calling `TrackingPlugin::identify()`, which hashes the identifier with **sha224** and registers it as a Mixpanel *super property* on the shared Mixpanel instance — so it lands on every event sent afterwards, including MCP events. No raw email or domain ever leaves the site.
28
29 | Priority | Identifier | Rationale |
30 |---|---|---|
31 | 1 | `get_imagify_user()->email` | Same strategy as WP Rocket: one license = one Mixpanel user across all of its sites |
32 | 2 | Host of `get_home_url()` | Fallback for unlicensed sites or an unreachable API, so events still get a stable anonymized identity |
33 | 3 | *(none)* | If neither resolves, `identify()` is not called and the event carries no `distinct_id` |
34
35 It is called from `get_default_event_properties()` — the single choke point every tracked event goes through. That placement is deliberate:
36
37 - It reuses the `get_imagify_user()` result already needed for `license_owner` (transient-cached for 5 minutes), so no extra API call.
38 - It never runs on plugin bootstrap, unlike identifying in the constructor.
39
40 A per-instance `identified` flag keeps it to one call per instance per request.
41
42 > `distinct_id` is a Mixpanel super property, not an event property — it will not appear in `get_default_event_properties()` return values or in the `track_direct()` `$properties` argument.
43
44 ---
45
46 ## Option key
47
48 | Option | Default | Description |
49 |---|---|---|
50 | `imagify_mixpanel_optin` | `false` | Tracks whether the user has opted in to analytics. Set to `1` to enable tracking (e.g., `wp option update imagify_mixpanel_optin 1`). The opt-in toggle UI ships in a follow-up issue. |
51
52 ---
53
54 ## Hooks subscribed
55
56 | Hook | Method | Priority | Args |
57 |---|---|---|---|
58 | `imagify_after_optimize` | `Subscriber::track_media_optimized` | 10 | 2 (`$process`, `$item`) |
59 | `update_option_imagify_settings` | `Subscriber::track_settings_saved` | 10 | 2 (`$old_value`, `$new_value`) |
60 | `update_site_option_imagify_settings` | `Subscriber::track_settings_saved` | 10 | 2 (`$option`, `$new_value`) |
61
62 `imagify_after_optimize` fires inside ActionScheduler (see `classes/Job/MediaOptimization.php`). Because bulk/cron runs execute without a logged-in user, the module uses `Optin::can_track()` (option-only check) and `TrackingPlugin::track_direct()` (bypasses `current_user_can`).
63
64 `update_option_imagify_settings` fires on single-site when the option value changes. `update_site_option_imagify_settings` fires on multisite. Note the argument ordering differs between them: on multisite the first argument is the option name string, not the old value — the delegating method casts both args to array to satisfy the strict-typed `Tracking` signature, and the old value is unused downstream.
65
66 ---
67
68 ## Event: Media Optimized
69
70 Fired after a successful full-size optimization. Guards (all must pass):
71
72 1. `can_track()` returns `true` (opt-in enabled).
73 2. `'full'` is present in `$item['sizes_done']`.
74 3. `get_size_data('full')['success'] === true`.
75
76 ### Event properties
77
78 | Property | Source | Notes |
79 |---|---|---|
80 | `context` | `'wp_plugin'` | Always `wp_plugin` |
81 | `license_owner` | SHA-256 hash of `get_imagify_user()->email` | Empty string if not connected |
82 | `user_id` | `get_current_user_id()` | `0` during cron/bulk runs |
83 | `optimization_level` | `DataInterface::get_optimization_level()` | 0=normal, 1=aggressive, 2=ultra |
84 | `media_type` | `MediaInterface::get_mime_type()` | e.g. `image/jpeg` |
85 | `original_size` | `get_size_data('full', 'original_size')` | Bytes |
86 | `optimized_size` | `get_size_data('full', 'optimized_size')` | Bytes |
87 | `savings_percent` | Computed | `0` when `original_size` is `0` |
88 | `next_gen_format` | AVIF checked first, then WebP | `'avif'`, `'webp'`, or `null` |
89 | `trigger` | Resolved from context | `'auto'`, `'bulk'`, or `'manual'` |
90
91 `TrackingPlugin::track_direct()` automatically merges `domain`, `wp_version`, `php_version`, `plugin`, `brand`, and `application` — do NOT include these in `get_default_event_properties()`.
92
93 ### Trigger resolution
94
95 1. `auto``$item['data']['is_new_upload']` is truthy.
96 2. `bulk` — transient `imagify_wp_optimize_running` or `imagify_custom-folders_optimize_running` is set.
97 3. `manual` — fallback.
98
99 When `auto` and bulk transients are both true, `auto` wins.
100
101 ---
102
103 ## Event: Settings Saved
104
105 Fired each time the Imagify settings option is actually updated (WordPress only fires `update_option_*` when the value changes). Guards:
106
107 1. `can_track()` returns `true` (opt-in enabled).
108
109 ### Event properties
110
111 | Property | Source option key | Notes |
112 |---|---|---|
113 | `context` | | Always `'wp_plugin'` (from `get_default_event_properties()`) |
114 | `license_owner` | | SHA-256 hash of `get_imagify_user()->email`; empty string if not connected |
115 | `user_id` | | `get_current_user_id()` |
116 | `optimization_level` | `optimization_level` | Cast to `int`; `null` if key absent |
117 | `auto_optimize_on_upload` | `auto_optimize` | `bool` via `! empty()` |
118 | `resize_larger_images` | `resize_larger` | `bool` via `! empty()` |
119 | `next_gen_images_webp` | `convert_to_webp` | `bool` via `! empty()` |
120 | `next_gen_images_avif` | `convert_to_avif` | `bool` via `! empty()` |
121 | `backup_original` | `backup` | `bool` via `! empty()` |
122
123 `TrackingPlugin::track_direct()` automatically merges `domain`, `wp_version`, `php_version`, `plugin`, `brand`, and `application` — these are not set manually.
124
125 ---
126
127 ## ServiceProvider bindings
128
129 Registered in `config/providers.php` as `Imagify\Tracking\ServiceProvider`.
130
131 | Binding | Arguments |
132 |---|---|
133 | `Imagify\Dependencies\WPMedia\Mixpanel\Optin` | `'imagify'`, `'manage_options'` |
134 | `Imagify\Dependencies\WPMedia\Mixpanel\TrackingPlugin` | token, `'imagify <VERSION>'`, `'wp media'`, `'imagify'` |
135 | `Imagify\Tracking\Tracking` | `Optin`, `TrackingPlugin` |
136 | `Imagify\Tracking\Subscriber` | `Tracking` |
137