Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/seo-by-rank-math/includes/class-tracking.php
Keine Baseline-Datei – Diff nur gegen leer.
1
-
1
+
<?php
2
+
/**
3
+
* Code related to the Mixpanel Tracking.
4
+
*
5
+
* @since 1.0.x
6
+
* @package RankMath
7
+
* @subpackage RankMath\Core
8
+
* @author Rank Math <support@rankmath.com>
9
+
*/
10
+
11
+
declare(strict_types=1);
12
+
13
+
namespace RankMath;
14
+
15
+
use RankMath\Traits\Hooker;
16
+
use RankMath\Helper;
17
+
use RankMath\Helpers\Param;
18
+
use RankMath\Helpers\Str;
19
+
use RankMath\Helpers\Editor;
20
+
use RankMath\Admin\Admin_Helper;
21
+
use WPMedia\Mixpanel\Optin;
22
+
use WPMedia\Mixpanel\TrackingPlugin;
23
+
24
+
/**
25
+
* Tracking class.
26
+
*/
27
+
class Tracking {
28
+
use Hooker;
29
+
30
+
/**
31
+
* Opt-in instance.
32
+
*
33
+
* @var Optin
34
+
*/
35
+
private $optin;
36
+
37
+
/**
38
+
* Mixpanel instance.
39
+
*
40
+
* @var TrackingPlugin
41
+
*/
42
+
private $mixpanel;
43
+
44
+
/**
45
+
* User email for identification.
46
+
*
47
+
* @var string
48
+
*/
49
+
private $user_email = '';
50
+
51
+
/**
52
+
* User language.
53
+
*
54
+
* @var string
55
+
*/
56
+
private $user_language = '';
57
+
58
+
/**
59
+
* Plugin name.
60
+
*
61
+
* @var string
62
+
*/
63
+
private $plugin = '';
64
+
65
+
/**
66
+
* Constructor.
67
+
*/
68
+
public function __construct() {
69
+
$this->plugin = defined( 'RANK_MATH_PRO_VERSION' ) ? 'Rank Math Pro ' . RANK_MATH_PRO_VERSION : 'Rank Math Free ' . rank_math()->version;
70
+
$this->optin = new Optin( 'rank_math', 'manage_options' );
71
+
$this->mixpanel = new TrackingPlugin( '517e881edc2636e99a2ecf013d8134d3', $this->plugin, 'RankMath', 'RankMath' );
72
+
73
+
$this->action( 'init', 'hooks' );
74
+
}
75
+
76
+
/**
77
+
* Initialize the tracking class hooks.
78
+
*/
79
+
public function hooks(): void {
80
+
$this->init_user_data();
81
+
$this->action( 'rank_math_mixpanel_optin_changed', 'track_optin_change' );
82
+
$this->action( 'rank_math/module_changed', 'track_module_option_change', 10, 2 );
83
+
$this->action( 'rank_math/setup_wizard/enable_tracking', 'enable_usage_tracking' );
84
+
$this->action( 'rank_math/setup_wizard/step_viewed', 'track_setup_wizard_step_view' );
85
+
$this->action( 'rank_math/admin/enqueue_scripts', 'enqueue_mixpanel' );
86
+
$this->action( 'admin_init', 'track_admin_page_view' );
87
+
$this->action( 'rank_math/admin/options/general_data', 'set_usage_tracking_option', 99 );
88
+
$this->action( 'rank_math/settings/before_save', 'update_mixpanel_optin', 10, 2 );
89
+
$this->filter( 'rank_math/settings/saved_data', 'add_mixpanel_data', 10, 2 );
90
+
$this->action( 'cmb2_save_options-page_fields_rank-math-options-general_options', 'update_mixpanel_optin_cmb2' );
91
+
}
92
+
93
+
/**
94
+
* Track the opt-in status change.
95
+
*
96
+
* @param bool $status The new opt-in status.
97
+
*/
98
+
public function track_optin_change( $status ): void {
99
+
$this->identify_user();
100
+
$this->mixpanel->track_optin( $status );
101
+
}
102
+
103
+
/**
104
+
* Track module option changes.
105
+
*
106
+
* @param string $module_id The module ID.
107
+
* @param string $state The new state (on/off).
108
+
*/
109
+
public function track_module_option_change( $module_id, $state ): void {
110
+
if ( ! $this->is_opted_in() ) {
111
+
return;
112
+
}
113
+
114
+
$enable_module = $state === 'on';
115
+
$properties = [
116
+
'context' => 'wp_plugin',
117
+
'option_name' => 'module ' . $module_id,
118
+
'previous_value' => ! $enable_module ? 1 : 0,
119
+
'new_value' => $enable_module ? 1 : 0,
120
+
'language' => $this->user_language,
121
+
];
122
+
123
+
$this->track_event( 'Option Changed', $properties );
124
+
}
125
+
126
+
/**
127
+
* Enable or disable usage tracking.
128
+
*
129
+
* @param bool $enable True to enable, false to disable.
130
+
*/
131
+
public function enable_usage_tracking( $enable ): void {
132
+
if ( $enable ) {
133
+
$this->optin->enable();
134
+
return;
135
+
}
136
+
137
+
$this->optin->disable();
138
+
}
139
+
140
+
/**
141
+
* Track setup wizard step views.
142
+
*/
143
+
public function track_setup_wizard_step_view() {
144
+
if ( ! $this->is_opted_in() ) {
145
+
return;
146
+
}
147
+
148
+
// Get the actual admin page URL from the request referer.
149
+
$referer = wp_get_referer();
150
+
$current_url = $referer ? $referer : Helper::get_current_page_url();
151
+
$path = $this->get_current_path_with_query();
152
+
153
+
// Parse the referer URL to get the current step being viewed.
154
+
$url_parts = wp_parse_url( $referer );
155
+
parse_str( $url_parts['query'] ?? '', $query_params );
156
+
$current_step_being_viewed = $query_params['step'] ?? 'compatibility';
157
+
158
+
// Use static variable to prevent duplicate tracking in the same request.
159
+
static $tracked_steps = [];
160
+
if ( in_array( $current_step_being_viewed, $tracked_steps, true ) ) {
161
+
return;
162
+
}
163
+
$tracked_steps[] = $current_step_being_viewed;
164
+
165
+
$properties = [
166
+
'current_url' => $current_url,
167
+
'path' => $path,
168
+
'context' => 'wp_plugin',
169
+
'language' => $this->user_language,
170
+
];
171
+
172
+
$this->track_event( 'Page Viewed', $properties );
173
+
}
174
+
175
+
/**
176
+
* Enqueue Mixpanel script on Block Editor pages.
177
+
*/
178
+
public function enqueue_mixpanel(): void {
179
+
if ( ! $this->optin->can_track() ) {
180
+
return;
181
+
}
182
+
183
+
if ( ! Helper::is_block_editor() || ! Editor::can_add_editor() ) {
184
+
return;
185
+
}
186
+
187
+
$this->mixpanel->add_script();
188
+
Helper::add_json(
189
+
'tracking',
190
+
[
191
+
'plugin' => $this->plugin,
192
+
'path' => isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '',
193
+
'email' => $this->user_email,
194
+
'language' => $this->user_language,
195
+
],
196
+
);
197
+
}
198
+
199
+
/**
200
+
* Track admin page views.
201
+
*/
202
+
public function track_admin_page_view() {
203
+
if ( ! $this->optin->can_track() ) {
204
+
return;
205
+
}
206
+
207
+
// Only track Rank Math admin/configuration pages.
208
+
if ( ! Str::starts_with( 'rank-math', Param::get( 'page' ) ) ) {
209
+
return;
210
+
}
211
+
212
+
// Check if we've already tracked this user in the last 7 days.
213
+
$transient_key = 'rank_math_admin_tracking_' . md5( $this->user_email );
214
+
if ( get_transient( $transient_key ) ) {
215
+
return;
216
+
}
217
+
218
+
// Set transient for 7 days to prevent duplicate tracking.
219
+
set_transient( $transient_key, true, WEEK_IN_SECONDS );
220
+
221
+
// Get the current admin page URL.
222
+
$current_url = Helper::get_current_page_url();
223
+
$path = $this->get_current_path_with_query();
224
+
225
+
$properties = [
226
+
'current_url' => $current_url,
227
+
'path' => $path,
228
+
'context' => 'wp_plugin',
229
+
'language' => $this->user_language,
230
+
];
231
+
232
+
// Determine capability based on current Rank Math page and pass it to Mixpanel.
233
+
$page = (string) Param::get( 'page' );
234
+
$event_capability = $this->get_event_capability_for_page( $page );
235
+
$this->track_event( 'Page Viewed', $properties, $event_capability );
236
+
}
237
+
238
+
/**
239
+
* Add usage_tracking option to the general settings.
240
+
*
241
+
* @param array $json Localized data.
242
+
*/
243
+
public function set_usage_tracking_option( $json ) {
244
+
// Early bail if the current page is not general settings.
245
+
if ( ! isset( $json['optionPage'] ) || $json['optionPage'] !== 'general' || ! isset( $json['data'] ) ) {
246
+
return $json;
247
+
}
248
+
249
+
$json['canAddUsageTracking'] = current_user_can( 'manage_options' );
250
+
$json['data']['usage_tracking'] = $this->optin->can_track();
251
+
252
+
return $json;
253
+
}
254
+
255
+
/**
256
+
* Update opt-in value.
257
+
*
258
+
* @param string $type Settings type.
259
+
* @param array $settings Settings data.
260
+
*/
261
+
public function update_mixpanel_optin( $type, $settings ) {
262
+
if ( $type !== 'general' || ! isset( $settings['usage_tracking'] ) ) {
263
+
return;
264
+
}
265
+
266
+
if ( ! empty( $settings['usage_tracking'] ) ) {
267
+
$this->optin->enable();
268
+
return;
269
+
}
270
+
271
+
$this->optin->disable();
272
+
}
273
+
274
+
/**
275
+
* Add usage tracking data to the saved settings.
276
+
*
277
+
* @param array $data Settings data.
278
+
* @param string $type Settings type.
279
+
* @return array
280
+
*/
281
+
public function add_mixpanel_data( $data, $type ) {
282
+
if ( $type !== 'general' ) {
283
+
return $data;
284
+
}
285
+
286
+
$data['usage_tracking'] = $this->optin->can_track();
287
+
return $data;
288
+
}
289
+
290
+
/**
291
+
* Update Mixpanel optin option when general settings are saved. Used
292
+
*/
293
+
public function update_mixpanel_optin_cmb2() {
294
+
// Get the value from the form submission.
295
+
$usage_tracking = isset( $_POST['usage_tracking'] ) ? sanitize_text_field( wp_unslash( $_POST['usage_tracking'] ) ) : 'off';
296
+
if ( $usage_tracking === 'on' ) {
297
+
$this->optin->enable();
298
+
return;
299
+
}
300
+
301
+
$this->optin->disable();
302
+
}
303
+
304
+
/**
305
+
* Check if usage tracking is enabled (opt-in).
306
+
*
307
+
* @return bool
308
+
*/
309
+
public function is_opted_in(): bool {
310
+
return $this->optin->is_enabled();
311
+
}
312
+
313
+
/**
314
+
* Track a custom event for Rank Math.
315
+
*
316
+
* @param string $event Event name.
317
+
* @param array $properties Additional properties to merge.
318
+
* @param string $event_capability The capability required to track the event.
319
+
*/
320
+
public function track_event( string $event, array $properties = [], string $event_capability = '' ): void {
321
+
$defaults = [
322
+
'context' => 'wp_plugin',
323
+
'language' => $this->user_language,
324
+
];
325
+
326
+
$this->identify_user();
327
+
$this->mixpanel->track( $event, array_merge( $properties, $defaults ), $event_capability );
328
+
}
329
+
330
+
/**
331
+
* Get the current request path with query string, suitable for tracking.
332
+
* Handles AJAX and REST requests by using referer when available.
333
+
*
334
+
* @return string
335
+
*/
336
+
public function get_current_path_with_query(): string {
337
+
// For AJAX/REST requests, use referer to get the originating page.
338
+
$referer = wp_get_referer();
339
+
$current_url = $referer ? $referer : Helper::get_current_page_url();
340
+
$path = wp_parse_url( $current_url, PHP_URL_PATH ) . '?' . wp_parse_url( $current_url, PHP_URL_QUERY );
341
+
342
+
return $path;
343
+
}
344
+
345
+
/**
346
+
* Identify the current user in Mixpanel.
347
+
* Safe to call multiple times; no-ops when opt-out.
348
+
*/
349
+
public function identify_user(): void {
350
+
$this->mixpanel->identify( $this->user_email );
351
+
}
352
+
353
+
/**
354
+
* Get the current plugin label (with version) used in tracking payloads.
355
+
*
356
+
* @return string
357
+
*/
358
+
public function get_plugin_label(): string {
359
+
return $this->plugin;
360
+
}
361
+
362
+
/**
363
+
* Initialize user data.
364
+
*/
365
+
private function init_user_data() {
366
+
if ( ! $this->user_email ) {
367
+
$this->user_email = $this->get_user_email();
368
+
}
369
+
370
+
if ( ! $this->user_language ) {
371
+
$this->user_language = get_user_locale();
372
+
}
373
+
}
374
+
375
+
/**
376
+
* Get user email for identification.
377
+
*
378
+
* @return string
379
+
*/
380
+
private function get_user_email(): string {
381
+
$account = Admin_Helper::get_registration_data();
382
+
if ( ! empty( $account['email'] ) ) {
383
+
return $account['email'];
384
+
}
385
+
386
+
$user = wp_get_current_user();
387
+
return isset( $user->user_email ) ? (string) $user->user_email : '';
388
+
}
389
+
390
+
/**
391
+
* Get the capability required for tracking based on the current Rank Math page.
392
+
*
393
+
* @param string $page The `page` query arg, e.g., 'rank-math-options-general'.
394
+
*
395
+
* @return string Capability name or empty for default behavior.
396
+
*/
397
+
private function get_event_capability_for_page( string $page ): string {
398
+
// Map known Rank Math admin pages to their capabilities.
399
+
$map = [
400
+
'rank-math-options-general' => 'rank_math_general',
401
+
'rank-math-options-titles' => 'rank_math_titles',
402
+
'rank-math-options-sitemap' => 'rank_math_sitemap',
403
+
'rank-math-options-instant-indexing' => 'rank_math_general',
404
+
'rank-math-404-monitor' => 'rank_math_404_monitor',
405
+
'rank-math-redirections' => 'rank_math_redirections',
406
+
'rank-math-role-manager' => 'rank_math_role_manager',
407
+
'rank-math-analytics' => 'rank_math_analytics',
408
+
'rank-math-seo-analysis' => 'rank_math_site_analysis',
409
+
'rank-math-content-ai-page' => 'rank_math_content_ai',
410
+
];
411
+
412
+
return isset( $map[ $page ] ) ? $map[ $page ] : '';
413
+
}
414
+
}
415
+