PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.7.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.7.0
2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.32.0 1.31.0 1.30.0 1.29.0 1.28.0 1.27.0 1.26.0 1.25.0 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.10.0 All 48 releases
← All changes | includes/api/class-integrations-endpoint.php +1 -140 2.1.12.7.0 View file →
@@ -121,55 +121,8 @@
121 121 ]
122 122 ]
123 123 );
124 124
125 - // Verify GA4 tracking
126 - register_rest_route(
127 - $this->namespace,
128 - '/' . $this->rest_base . '/verify-ga4-tracking',
129 - [
130 - [
131 - 'methods' => 'POST',
132 - 'callback' => [$this, 'verify_ga4_tracking'],
133 - 'permission_callback' => [$this, 'check_manage_permissions'],
134 - 'args' => [
135 - 'measurement_id' => [
136 - // Optional, and an empty string is meaningful:
137 - // verify_tracking() then discovers the ID from the
138 - // live homepage. A `required` + `pattern` arg
139 - // rejected that at the REST layer before the
140 - // handler ran, which is why verification was
141 - // unreachable on sites with no stored ID (#250).
142 - 'required' => false,
143 - 'type' => 'string',
144 - 'default' => '',
145 - // No regex delimiters — WP's REST validator wraps the
146 - // pattern in its own (#...#u), so a leading/trailing
147 - // slash would require literal slashes in the value.
148 - // The empty alternative keeps discovery reachable
149 - // while still rejecting a malformed ID.
150 - 'pattern' => '^(G-[A-Z0-9]{10})?$',
151 - 'sanitize_callback' => 'sanitize_text_field',
152 - 'description' => 'GA4 Measurement ID in format G-XXXXXXXXXX. Omit or leave empty to auto-detect the ID from the site homepage.'
153 - ]
154 - ]
155 - ]
156 - ]
157 - );
158 -
159 - // Detect GA4 conflicts
160 - register_rest_route(
161 - $this->namespace,
162 - '/' . $this->rest_base . '/detect-ga4-conflicts',
163 - [
164 - [
165 - 'methods' => 'GET',
166 - 'callback' => [$this, 'detect_ga4_conflicts'],
167 - 'permission_callback' => [$this, 'check_read_permissions']
168 - ]
169 - ]
170 - );
171 -
172 125 // Get Search Console Sites
173 126 register_rest_route(
174 127 $this->namespace,
175 128 '/' . $this->rest_base . '/search-console/sites',
@@ -338,16 +291,8 @@
338 291 $settings['google_analytics_api_key'] = $this->settings->get('google_analytics_api_key');
339 292 $settings['google_search_console_api_key'] = $this->settings->get('google_search_console_api_key');
340 293 $settings['google_pagespeed_api_key'] = $this->settings->get('google_pagespeed_api_key');
341 294
342 - // Get GA4 tracking settings (let Settings class handle defaults)
343 - $settings['ga4_measurement_id'] = $this->settings->get('ga4_measurement_id');
344 - $settings['ga4_auto_inject'] = $this->settings->get('ga4_auto_inject');
345 - $settings['ga4_anonymize_ip'] = $this->settings->get('ga4_anonymize_ip');
346 - $settings['ga4_exclude_admin'] = $this->settings->get('ga4_exclude_admin');
347 - $settings['ga4_tracking_verified'] = $this->settings->get('ga4_tracking_verified');
348 - $settings['ga4_last_verification'] = $this->settings->get('ga4_last_verification');
349 -
350 295 // Get other integration settings (let Settings class handle defaults)
351 296 $settings['api_timeout'] = $this->settings->get('api_timeout');
352 297 $settings['enable_rate_limiting'] = $this->settings->get('enable_rate_limiting');
353 298 $settings['cache_duration'] = $this->settings->get('cache_duration');
@@ -416,21 +361,9 @@
416 361 $sanitized[$key] = absint($settings[$key]);
417 362 }
418 363 }
419 364
420 - $text = ['ga4_measurement_id', 'ga4_last_verification'];
421 -
422 - foreach ($text as $key) {
423 - if (array_key_exists($key, $settings)) {
424 - $sanitized[$key] = sanitize_text_field($settings[$key]);
425 - }
426 - }
427 -
428 365 $booleans = [
429 - 'ga4_auto_inject',
430 - 'ga4_anonymize_ip',
431 - 'ga4_exclude_admin',
432 - 'ga4_tracking_verified',
433 366 'enable_rate_limiting',
434 367 'auto_test_connections',
435 368 'retry_failed_requests',
436 369 ];
@@ -917,9 +850,9 @@
917 850 * Writing provider API keys, disconnecting Google (a server-side token
918 851 * revoke) and running live connection tests manage the site's third-party
919 852 * credentials, so they require an administrator — `thinkrank_settings` is
920 853 * delegatable to non-admin roles through the Role Manager. Mirrors the
921 - * pattern used by the brand-visibility and AI-insights key writes.
854 + * pattern used by the AI-insights settings writes.
922 855 *
923 856 * @since 1.29.0
924 857 * @return bool Permission status
925 858 */
@@ -926,80 +859,8 @@
926 859 public function check_credential_permissions(): bool {
927 860 return current_user_can('manage_options');
928 861 }
929 862
930 - /**
931 - * Verify GA4 tracking
932 - * Following ThinkRank API response patterns
933 - *
934 - * @since 1.0.0
935 - * @param WP_REST_Request $request Request object
936 - * @return WP_REST_Response|WP_Error Response object
937 - */
938 - public function verify_ga4_tracking(WP_REST_Request $request) {
939 - try {
940 - // Empty is allowed and meaningful: verify_tracking() then reads the
941 - // homepage and discovers whichever GA4 ID is actually serving. The
942 - // old 400 made verification impossible on OAuth-connected sites
943 - // that never typed an ID in — precisely the reported case (#250).
944 - $measurement_id = (string) ( $request->get_param('measurement_id') ?? '' );
945 -
946 - // Load tracking manager
947 - if (!class_exists('ThinkRank\\Frontend\\Google_Analytics_Tracking_Manager')) {
948 - require_once THINKRANK_PLUGIN_DIR . 'includes/frontend/class-google-analytics-tracking-manager.php';
949 - }
950 -
951 - $tracking_manager = new \ThinkRank\Frontend\Google_Analytics_Tracking_Manager();
952 - $verification_result = $tracking_manager->verify_tracking($measurement_id);
953 -
954 - return new WP_REST_Response([
955 - 'success' => true,
956 - 'data' => $verification_result,
957 - 'message' => 'Tracking verification completed'
958 - ], 200);
959 - } catch (\Exception $e) {
960 - return new WP_Error(
961 - 'verification_failed',
962 - 'Tracking verification failed: ' . $e->getMessage(),
963 - ['status' => 500]
964 - );
965 - }
966 - }
967 -
968 - /**
969 - * Detect GA4 conflicts
970 - * Following ThinkRank API response patterns
971 - *
972 - * @since 1.0.0
973 - * @param WP_REST_Request $request Request object
974 - * @return WP_REST_Response|WP_Error Response object
975 - */
976 - public function detect_ga4_conflicts(WP_REST_Request $request) {
977 - try {
978 - // Load tracking manager
979 - if (!class_exists('ThinkRank\\Frontend\\Google_Analytics_Tracking_Manager')) {
980 - require_once THINKRANK_PLUGIN_DIR . 'includes/frontend/class-google-analytics-tracking-manager.php';
981 - }
982 -
983 - $tracking_manager = new \ThinkRank\Frontend\Google_Analytics_Tracking_Manager();
984 - $conflicts = $tracking_manager->detect_existing_tracking();
985 -
986 - return new WP_REST_Response([
987 - 'success' => true,
988 - 'data' => [
989 - 'conflicts' => $conflicts,
990 - 'has_conflicts' => !empty($conflicts)
991 - ],
992 - 'message' => 'Conflict detection completed'
993 - ], 200);
994 - } catch (\Exception $e) {
995 - return new WP_Error(
996 - 'conflict_detection_failed',
997 - 'Conflict detection failed: ' . $e->getMessage(),
998 - ['status' => 500]
999 - );
1000 - }
1001 - }
1002 863 /**
1003 864 * Fingerprint the currently connected Google account.
1004 865 *
1005 866 * Prefers the refresh token: it is issued once per authorization grant and