# thinkrank/1.0.0/includes/api/class-integrations-endpoint.php

ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console &amp; Local SEO, version 1.0.0. 553 lines.

- Page: https://pluginprobe.com/plugins/thinkrank/1.0.0/code/includes/api/class-integrations-endpoint.php
- Raw: https://pluginprobe.com/plugins/thinkrank/1.0.0/raw/includes/api/class-integrations-endpoint.php
- Modified: 2025-08-10T07:57:44+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/thinkrank/1.0.0/code/includes/api/class-integrations-endpoint.php#L10-L20`.

```php
<?php
/**
 * Integrations API Endpoints Class
 *
 * Provides REST API endpoints for Google API integrations management
 * following the same pattern as Site Identity and Social Media endpoints.
 *
 * @package ThinkRank\API
 * @since 1.0.0
 */

declare(strict_types=1);

namespace ThinkRank\API;

use WP_REST_Controller;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;
use ThinkRank\Core\Settings;

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Integrations API Endpoints Class
 *
 * Handles Google API keys and integration settings management
 * following ThinkRank patterns from working endpoints.
 *
 * @since 1.0.0
 */
class Integrations_Endpoint extends WP_REST_Controller {

    /**
     * API namespace
     *
     * @since 1.0.0
     * @var string
     */
    protected $namespace = 'thinkrank/v1';

    /**
     * REST base
     *
     * @since 1.0.0
     * @var string
     */
    protected $rest_base = 'integrations';

    /**
     * Settings instance
     *
     * @since 1.0.0
     * @var Settings
     */
    private Settings $settings;

    /**
     * Constructor
     *
     * @since 1.0.0
     */
    public function __construct() {
        $this->settings = new Settings();
    }

    /**
     * Register API routes
     *
     * @since 1.0.0
     */
    public function register_routes(): void {
        // Integrations settings management
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/settings',
            [
                [
                    'methods' => 'GET',
                    'callback' => [$this, 'get_settings'],
                    'permission_callback' => [$this, 'check_read_permissions']
                ],
                [
                    'methods' => 'POST',
                    'callback' => [$this, 'update_settings'],
                    'permission_callback' => [$this, 'check_manage_permissions'],
                    'args' => $this->get_settings_args()
                ]
            ]
        );

        // Test Google API connections
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/test-connections',
            [
                [
                    'methods' => 'POST',
                    'callback' => [$this, 'test_connections'],
                    'permission_callback' => [$this, 'check_manage_permissions']
                ]
            ]
        );

        // Verify GA4 tracking
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/verify-ga4-tracking',
            [
                [
                    'methods' => 'POST',
                    'callback' => [$this, 'verify_ga4_tracking'],
                    'permission_callback' => [$this, 'check_manage_permissions'],
                    'args' => [
                        'measurement_id' => [
                            'required' => true,
                            'type' => 'string',
                            'pattern' => '/^G-[A-Z0-9]{10}$/',
                            'sanitize_callback' => 'sanitize_text_field',
                            'description' => 'GA4 Measurement ID in format G-XXXXXXXXXX'
                        ]
                    ]
                ]
            ]
        );

        // Detect GA4 conflicts
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/detect-ga4-conflicts',
            [
                [
                    'methods' => 'GET',
                    'callback' => [$this, 'detect_ga4_conflicts'],
                    'permission_callback' => [$this, 'check_read_permissions']
                ]
            ]
        );
    }

    /**
     * Get integrations settings
     *
     * @since 1.0.0
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response Response object
     */
    public function get_settings(WP_REST_Request $request): WP_REST_Response {
        try {
            $settings = $this->get_integrations_settings();

            return new WP_REST_Response([
                'success' => true,
                'data' => [
                    'settings' => $settings
                ],
                'message' => 'Integrations settings retrieved successfully'
            ], 200);

        } catch (\Exception $e) {
            return new WP_REST_Response([
                'success' => false,
                'message' => 'Failed to retrieve integrations settings: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Update integrations settings
     *
     * @since 1.0.0
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response Response object
     */
    public function update_settings(WP_REST_Request $request): WP_REST_Response {
        try {
            $settings = $request->get_param('settings');

            if (empty($settings) || !is_array($settings)) {
                return new WP_REST_Response([
                    'success' => false,
                    'message' => 'Invalid settings data provided'
                ], 400);
            }

            // Sanitize and save settings
            $sanitized_settings = $this->sanitize_settings($settings);
            $success = $this->save_integrations_settings($sanitized_settings);

            if ($success) {
                return new WP_REST_Response([
                    'success' => true,
                    'data' => [
                        'settings' => $this->get_integrations_settings()
                    ],
                    'message' => 'Integrations settings saved successfully'
                ], 200);
            } else {
                return new WP_REST_Response([
                    'success' => false,
                    'message' => 'Failed to save integrations settings'
                ], 500);
            }

        } catch (\Exception $e) {
            return new WP_REST_Response([
                'success' => false,
                'message' => 'Failed to update integrations settings: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Test Google API connections
     *
     * @since 1.0.0
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response Response object
     */
    public function test_connections(WP_REST_Request $request): WP_REST_Response {
        try {
            // Get raw, unmasked API keys directly from Settings class for testing
            $analytics_key = $this->settings->get('google_analytics_api_key');
            $search_console_key = $this->settings->get('google_search_console_api_key');
            $pagespeed_key = $this->settings->get('google_pagespeed_api_key');

            $results = [];

            // Test Google Analytics API
            if (!empty($analytics_key)) {
                $results['google_analytics'] = $this->test_google_analytics($analytics_key);
            } else {
                $results['google_analytics'] = ['status' => 'not_configured', 'message' => 'API key not configured'];
            }

            // Test Search Console API
            if (!empty($search_console_key)) {
                $results['search_console'] = $this->test_search_console($search_console_key);
            } else {
                $results['search_console'] = ['status' => 'not_configured', 'message' => 'API key not configured'];
            }

            // Test PageSpeed API
            if (!empty($pagespeed_key)) {
                $results['pagespeed'] = $this->test_pagespeed($pagespeed_key);
            } else {
                $results['pagespeed'] = ['status' => 'not_configured', 'message' => 'API key not configured'];
            }

            return new WP_REST_Response([
                'success' => true,
                'data' => $results,
                'message' => 'Connection tests completed'
            ], 200);

        } catch (\Exception $e) {
            return new WP_REST_Response([
                'success' => false,
                'message' => 'Connection test failed: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get integrations settings from Settings class (with encryption)
     *
     * @since 1.0.0
     * @return array Settings array
     */
    private function get_integrations_settings(): array {
        $settings = [];

        // Get encrypted API keys
        $settings['google_analytics_api_key'] = $this->settings->get('google_analytics_api_key');
        $settings['google_search_console_api_key'] = $this->settings->get('google_search_console_api_key');
        $settings['google_pagespeed_api_key'] = $this->settings->get('google_pagespeed_api_key');

        // Get GA4 tracking settings (let Settings class handle defaults)
        $settings['ga4_measurement_id'] = $this->settings->get('ga4_measurement_id');
        $settings['ga4_auto_inject'] = $this->settings->get('ga4_auto_inject');
        $settings['ga4_anonymize_ip'] = $this->settings->get('ga4_anonymize_ip');
        $settings['ga4_exclude_admin'] = $this->settings->get('ga4_exclude_admin');
        $settings['ga4_tracking_verified'] = $this->settings->get('ga4_tracking_verified');
        $settings['ga4_last_verification'] = $this->settings->get('ga4_last_verification');

        // Get other integration settings (let Settings class handle defaults)
        $settings['api_timeout'] = $this->settings->get('api_timeout');
        $settings['enable_rate_limiting'] = $this->settings->get('enable_rate_limiting');
        $settings['cache_duration'] = $this->settings->get('cache_duration');
        $settings['auto_test_connections'] = $this->settings->get('auto_test_connections');
        $settings['retry_failed_requests'] = $this->settings->get('retry_failed_requests');

        // Mask API keys for security (like OpenAI/Claude keys)
        $settings['google_analytics_api_key'] = $this->mask_api_key($settings['google_analytics_api_key']);
        $settings['google_search_console_api_key'] = $this->mask_api_key($settings['google_search_console_api_key']);
        $settings['google_pagespeed_api_key'] = $this->mask_api_key($settings['google_pagespeed_api_key']);

        return $settings;
    }

    /**
     * Save integrations settings using Settings class (with encryption)
     *
     * @since 1.0.0
     * @param array $settings Settings to save
     * @return bool Success status
     */
    private function save_integrations_settings(array $settings): bool {
        $success = true;

        // Save each setting individually using the Settings class
        // This ensures proper encryption for API keys
        foreach ($settings as $key => $value) {
            if (!$this->settings->set($key, $value)) {
                $success = false;
                // Setting save failed - error details available through settings manager
            }
        }

        return $success;
    }

    /**
     * Sanitize settings data
     *
     * @since 1.0.0
     * @param array $settings Raw settings
     * @return array Sanitized settings
     */
    private function sanitize_settings(array $settings): array {
        $sanitized = [];

        // Sanitize API keys (only if not empty - don't overwrite with empty values)
        if (!empty($settings['google_analytics_api_key'])) {
            $sanitized['google_analytics_api_key'] = sanitize_text_field($settings['google_analytics_api_key']);
        }
        if (!empty($settings['google_search_console_api_key'])) {
            $sanitized['google_search_console_api_key'] = sanitize_text_field($settings['google_search_console_api_key']);
        }
        if (!empty($settings['google_pagespeed_api_key'])) {
            $sanitized['google_pagespeed_api_key'] = sanitize_text_field($settings['google_pagespeed_api_key']);
        }

        // Sanitize numeric settings
        $sanitized['api_timeout'] = absint($settings['api_timeout'] ?? 30);
        $sanitized['cache_duration'] = absint($settings['cache_duration'] ?? 3600);

        // Sanitize GA4 tracking settings
        $sanitized['ga4_measurement_id'] = sanitize_text_field($settings['ga4_measurement_id'] ?? '');
        $sanitized['ga4_auto_inject'] = isset($settings['ga4_auto_inject']) ? (bool) $settings['ga4_auto_inject'] : false;
        $sanitized['ga4_anonymize_ip'] = isset($settings['ga4_anonymize_ip']) ? (bool) $settings['ga4_anonymize_ip'] : false;
        $sanitized['ga4_exclude_admin'] = isset($settings['ga4_exclude_admin']) ? (bool) $settings['ga4_exclude_admin'] : false;
        $sanitized['ga4_tracking_verified'] = isset($settings['ga4_tracking_verified']) ? (bool) $settings['ga4_tracking_verified'] : false;
        $sanitized['ga4_last_verification'] = sanitize_text_field($settings['ga4_last_verification'] ?? '');

        // Sanitize boolean settings
        $sanitized['enable_rate_limiting'] = isset($settings['enable_rate_limiting']) ? (bool) $settings['enable_rate_limiting'] : true;
        $sanitized['auto_test_connections'] = isset($settings['auto_test_connections']) ? (bool) $settings['auto_test_connections'] : true;
        $sanitized['retry_failed_requests'] = isset($settings['retry_failed_requests']) ? (bool) $settings['retry_failed_requests'] : true;

        return $sanitized;
    }

    /**
     * Mask API key for security display (XXX pattern)
     *
     * @since 1.0.0
     * @param string $api_key API key to mask
     * @return string Masked API key or empty string
     */
    private function mask_api_key(string $api_key): string {
        if (empty($api_key)) {
            return '';
        }

        // Show first 6 characters + XXXX suffix (consistent with placeholders)
        if (strlen($api_key) > 10) {
            return substr($api_key, 0, 6) . 'XXXX';
        }

        return 'XXXX';
    }

    /**
     * Test Google Analytics API connection
     *
     * @since 1.0.0
     * @param string $api_key API key to test
     * @return array Test result
     */
    private function test_google_analytics(string $api_key): array {
        // Simple validation test - in production this would make actual API call
        if (strlen($api_key) < 30 || !str_starts_with($api_key, 'AIza')) {
            return ['status' => 'error', 'message' => 'Invalid Google Analytics API key format'];
        }

        return ['status' => 'configured', 'message' => 'Google Analytics API key is configured and format is valid'];
    }

    /**
     * Test Google Search Console API connection
     *
     * @since 1.0.0
     * @param string $api_key API key to test
     * @return array Test result
     */
    private function test_search_console(string $api_key): array {
        // Simple validation test - in production this would make actual API call
        if (strlen($api_key) < 30 || !str_starts_with($api_key, 'AIza')) {
            return ['status' => 'error', 'message' => 'Invalid Search Console API key format'];
        }

        return ['status' => 'configured', 'message' => 'Search Console API key is configured and format is valid'];
    }

    /**
     * Test Google PageSpeed API connection
     *
     * @since 1.0.0
     * @param string $api_key API key to test
     * @return array Test result
     */
    private function test_pagespeed(string $api_key): array {
        // Simple validation test - in production this would make actual API call
        if (strlen($api_key) < 30 || !str_starts_with($api_key, 'AIza')) {
            return ['status' => 'error', 'message' => 'Invalid PageSpeed Insights API key format'];
        }

        return ['status' => 'configured', 'message' => 'PageSpeed Insights API key is configured and format is valid'];
    }

    /**
     * Get settings arguments for REST API
     *
     * @since 1.0.0
     * @return array Settings arguments
     */
    private function get_settings_args(): array {
        return [
            'settings' => [
                'required' => true,
                'type' => 'object',
                'description' => 'Integrations settings object'
            ]
        ];
    }

    /**
     * Check read permissions
     *
     * @since 1.0.0
     * @return bool Permission status
     */
    public function check_read_permissions(): bool {
        return current_user_can('manage_options');
    }

    /**
     * Check manage permissions
     *
     * @since 1.0.0
     * @return bool Permission status
     */
    public function check_manage_permissions(): bool {
        return current_user_can('manage_options');
    }

    /**
     * Verify GA4 tracking
     * Following ThinkRank API response patterns
     *
     * @since 1.0.0
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error Response object
     */
    public function verify_ga4_tracking(WP_REST_Request $request): WP_REST_Response|WP_Error {
        try {
            $measurement_id = $request->get_param('measurement_id');

            if (empty($measurement_id)) {
                return new WP_Error(
                    'missing_measurement_id',
                    'Measurement ID is required',
                    ['status' => 400]
                );
            }

            // Load tracking manager
            if (!class_exists('ThinkRank\\Frontend\\Google_Analytics_Tracking_Manager')) {
                require_once THINKRANK_PLUGIN_DIR . 'includes/frontend/class-google-analytics-tracking-manager.php';
            }

            $tracking_manager = new \ThinkRank\Frontend\Google_Analytics_Tracking_Manager();
            $verification_result = $tracking_manager->verify_tracking($measurement_id);

            return new WP_REST_Response([
                'success' => true,
                'data' => $verification_result,
                'message' => 'Tracking verification completed'
            ], 200);

        } catch (\Exception $e) {
            return new WP_Error(
                'verification_failed',
                'Tracking verification failed: ' . $e->getMessage(),
                ['status' => 500]
            );
        }
    }

    /**
     * Detect GA4 conflicts
     * Following ThinkRank API response patterns
     *
     * @since 1.0.0
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error Response object
     */
    public function detect_ga4_conflicts(WP_REST_Request $request): WP_REST_Response|WP_Error {
        try {
            // Load tracking manager
            if (!class_exists('ThinkRank\\Frontend\\Google_Analytics_Tracking_Manager')) {
                require_once THINKRANK_PLUGIN_DIR . 'includes/frontend/class-google-analytics-tracking-manager.php';
            }

            $tracking_manager = new \ThinkRank\Frontend\Google_Analytics_Tracking_Manager();
            $conflicts = $tracking_manager->detect_existing_tracking();

            return new WP_REST_Response([
                'success' => true,
                'data' => [
                    'conflicts' => $conflicts,
                    'has_conflicts' => !empty($conflicts)
                ],
                'message' => 'Conflict detection completed'
            ], 200);

        } catch (\Exception $e) {
            return new WP_Error(
                'conflict_detection_failed',
                'Conflict detection failed: ' . $e->getMessage(),
                ['status' => 500]
            );
        }
    }
}

```
