age_tracking'] ) ? sanitize_text_field( wp_unslash( $_POST['usage_tracking'] ) ) : 'off'; if ( $usage_tracking === 'on' ) { $this->optin->enable(); return; } $this->optin->disable(); } /** * Check if usage tracking is enabled (opt-in). * * @return bool */ public function is_opted_in(): bool { return $this->optin->is_enabled(); } /** * Track a WordPress Abilities API execution event. * * MCP and direct calls share the same event name; the context property * differentiates them ('wp_plugin' vs 'wp_plugin_mcp'). * * @param string $event_name Mixpanel event name (e.g. 'SEO Audit Run'). * @param array $properties Additional event properties (e.g. score, test_id). * @param string $event_capability WordPress capability required to execute the ability. */ public function track_ability_executed( string $event_name, array $properties = [], string $event_capability = '' ): void { if ( ! $this->is_opted_in() ) { return; } $context = ! empty( $_SERVER['HTTP_MCP_SESSION_ID'] ) ? 'wp_plugin_mcp' : 'wp_plugin'; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput $this->track_event( $event_name, array_merge( [ 'context' => $context ], $properties ), $event_capability ); } /** * Track a custom event for Rank Math. * * Always enforces the usage-tracking opt-in — no-ops when the site * hasn't consented, regardless of caller. * * @param string $event Event name. * @param array $properties Additional properties to merge. * @param string $event_capability The capability required to track the event. */ public function track_event( string $event, array $properties = [], string $event_capability = '' ): void { if ( ! $this->is_opted_in() ) { return; } $defaults = [ 'context' => 'wp_plugin', 'language' => $this->user_language, ]; $this->identify_user(); $this->mixpanel->track( $event, array_merge( $defaults, $properties ), $event_capability ); } /** * Get the current request path with query string, suitable for tracking. * Handles AJAX and REST requests by using referer when available. * * @return string */ public function get_current_path_with_query(): string { // For AJAX/REST requests, use referer to get the originating page. $referer = wp_get_referer(); $current_url = $referer ? $referer : Helper::get_current_page_url(); $path = wp_parse_url( $current_url, PHP_URL_PATH ) . '?' . wp_parse_url( $current_url, PHP_URL_QUERY ); return $path; } /** * Identify the current user in Mixpanel. * Safe to call multiple times; no-ops when opt-out. */ public function identify_user(): void { $this->mixpanel->identify( $this->user_email ); } /** * Get the current plugin label (with version) used in tracking payloads. * * @return string */ public function get_plugin_label(): string { return $this->plugin; } /** * Initialize user data. */ private function init_user_data() { if ( ! $this->user_email ) { $this->user_email = $this->get_user_email(); } if ( ! $this->user_language ) { $this->user_language = get_user_locale(); } } /** * Get user email for identification. * * @return string */ private function get_user_email(): string { $account = Admin_Helper::get_registration_data(); if ( ! empty( $account['email'] ) ) { return $account['email']; } $user = wp_get_current_user(); return isset( $user->user_email ) ? (string) $user->user_email : ''; } /** * Get the capability required for tracking based on the current Rank Math page. * * @param string $page The `page` query arg, e.g., 'rank-math-options-general'. * * @return string Capability name or empty for default behavior. */ private function get_event_capability_for_page( string $page ): string { // Map known Rank Math admin pages to their capabilities. $map = [ 'rank-math-options-general' => 'rank_math_general', 'rank-math-options-titles' => 'rank_math_titles', 'rank-math-options-sitemap' => 'rank_math_sitemap', 'rank-math-options-instant-indexing' => 'rank_math_general', 'rank-math-404-monitor' => 'rank_math_404_monitor', 'rank-math-redirections' => 'rank_math_redirections', 'rank-math-role-manager' => 'rank_math_role_manager', 'rank-math-analytics' => 'rank_math_analytics', 'rank-math-seo-analysis' => 'rank_math_site_analysis', 'rank-math-content-ai-page' => 'rank_math_content_ai', 'rank-math-links-page' => 'rank_math_general', ]; return isset( $map[ $page ] ) ? $map[ $page ] : ''; } }