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 / classes / Tracking / BaseTracking.php

BaseTracking.php in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF 2.3.1, at classes/Tracking/BaseTracking.php

145 lines 3.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 declare(strict_types=1);
3
4 namespace Imagify\Tracking;
5
6 use Imagify\Dependencies\WPMedia\Mixpanel\Optin;
7 use Imagify\Dependencies\WPMedia\Mixpanel\TrackingPlugin;
8
9 /**
10 * Abstract base class for Imagify tracking.
11 *
12 * @since 2.3.0
13 */
14 abstract class BaseTracking {
15
16 /**
17 * The Mixpanel opt-in service.
18 *
19 * @var Optin
20 */
21 protected $optin;
22
23 /**
24 * The Mixpanel tracking plugin service.
25 *
26 * @var TrackingPlugin
27 */
28 protected $mixpanel;
29
30 /**
31 * Whether the Mixpanel user has already been identified during this request.
32 *
33 * @var bool
34 */
35 private $identified = false;
36
37 /**
38 * Constructor.
39 *
40 * @param Optin $optin The Mixpanel opt-in service.
41 * @param TrackingPlugin $mixpanel The Mixpanel tracking plugin service.
42 */
43 public function __construct( Optin $optin, TrackingPlugin $mixpanel ) {
44 $this->optin = $optin;
45 $this->mixpanel = $mixpanel;
46 }
47
48 /**
49 * Check if tracking is allowed.
50 *
51 * @return bool True if tracking is allowed, false otherwise.
52 */
53 public function can_track(): bool {
54 return $this->optin->can_track();
55 }
56
57 /**
58 * Returns the default event properties shared by every tracked event.
59 *
60 * IMPORTANT: do NOT add `domain`, `wp_version`, `php_version`, `plugin`,
61 * `brand`, or `application` here. `TrackingPlugin::track_direct()` injects
62 * those automatically and any value set here is silently overwritten.
63 *
64 * @return array<string, mixed>
65 */
66 protected function get_default_event_properties(): array {
67 $email = $this->get_license_owner_email();
68 $license_owner = '' !== $email ? hash( 'sha256', $email ) : '';
69
70 $this->identify_user( $email );
71
72 return [
73 'context' => 'wp_plugin',
74 'license_owner' => $license_owner,
75 'user_id' => (int) get_current_user_id(),
76 ];
77 }
78
79 /**
80 * Registers a stable `distinct_id` super property on the Mixpanel instance.
81 *
82 * Mixpanel needs `distinct_id` on every event to compute user-level metrics
83 * (MAU/DAU, retention, cohorts, funnels). `TrackingPlugin::identify()` hashes
84 * the identifier with sha224 before it is registered, so no raw email or
85 * domain ever leaves the site.
86 *
87 * The identifier is the Imagify license owner email — the same strategy as
88 * WP Rocket, so one license maps to one Mixpanel user across all its sites.
89 * When no license email is available (unlicensed or unreachable API), the
90 * site host is used instead so events are still attributed to a stable,
91 * anonymized identity rather than none at all.
92 *
93 * Called from `get_default_event_properties()` — the single choke point every
94 * tracked event goes through — so the license user is fetched only once and
95 * never on plugin bootstrap. Runs at most once per instance per request; the
96 * underlying Mixpanel instance is shared, so the property applies to every
97 * subsequent event.
98 *
99 * @param string $email The license owner email, or an empty string when unknown.
100 *
101 * @return void
102 */
103 protected function identify_user( string $email ): void {
104 if ( $this->identified ) {
105 return;
106 }
107
108 $identifier = '' !== $email ? $email : $this->get_site_identifier();
109
110 if ( '' === $identifier ) {
111 return;
112 }
113
114 $this->mixpanel->identify( $identifier );
115
116 $this->identified = true;
117 }
118
119 /**
120 * Returns the Imagify license owner email.
121 *
122 * @return string The email, or an empty string when the account is unknown.
123 */
124 private function get_license_owner_email(): string {
125 $user = get_imagify_user();
126
127 if ( is_wp_error( $user ) || empty( $user->email ) ) {
128 return '';
129 }
130
131 return (string) $user->email;
132 }
133
134 /**
135 * Returns the site host, used as a fallback identifier when no license email exists.
136 *
137 * @return string The host, or an empty string when it cannot be resolved.
138 */
139 private function get_site_identifier(): string {
140 $host = wp_parse_url( get_home_url(), PHP_URL_HOST );
141
142 return is_string( $host ) ? $host : '';
143 }
144 }
145