PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 1.32.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v1.32.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
thinkrank / includes / integrations / class-google-search-analytics-client.php

class-google-search-analytics-client.php in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO 1.32.0, at includes/integrations/class-google-search-analytics-client.php

138 lines 4.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Google Search Analytics Client
5 *
6 * Client library for interacting with Google Search Console Search Analytics API.
7 * Extends the specific Google API Base Client for standardized request handling.
8 *
9 * @package ThinkRank
10 * @subpackage Integrations
11 * @since 1.0.0
12 */
13
14 declare(strict_types=1);
15
16 namespace ThinkRank\Integrations;
17
18 // Prevent direct access
19 if (!defined('ABSPATH')) {
20 exit;
21 }
22
23 /**
24 * Google Search Analytics Client Class
25 *
26 * specific client for fetching search analytics data from Google Search Console.
27 *
28 * @since 1.0.0
29 */
30 class Google_Search_Analytics_Client extends Google_API_Base_Client {
31
32 /**
33 * API Base URL
34 *
35 * @var string
36 */
37 protected const API_BASE_URL = 'https://www.googleapis.com/webmasters/v3';
38
39 /**
40 * Get search analytics data
41 *
42 * @param string $site_url The URL of the property in search console.
43 * @param string $start_date Start date in YYYY-MM-DD format.
44 * @param string $end_date End date in YYYY-MM-DD format.
45 * @param array $dimensions Dimensions to group by (e.g., 'query', 'page', 'country', 'device').
46 * @param int $row_limit Maximum number of rows to return.
47 * @return array Analytical data including rows and totals.
48 * @throws \Exception If the API request fails.
49 */
50 public function get_search_analytics_data(string $site_url, string $start_date, string $end_date, array $dimensions = [], int $row_limit = 1000): array {
51 $endpoint = '/sites/' . rawurlencode($site_url) . '/searchAnalytics/query';
52
53 $request_body = [
54 'startDate' => $start_date,
55 'endDate' => $end_date,
56 'dimensions' => $dimensions,
57 'rowLimit' => $row_limit,
58 // Include fresh (still-processing) data so the most recent days
59 // aren't missing — matches the GSC web UI default.
60 'dataState' => 'all',
61 ];
62
63 // Construct full URL. The API key is sent by make_request() in the
64 // x-goog-api-key header, not the query string (which proxies/logs capture).
65 $full_url = self::API_BASE_URL . $endpoint;
66
67 $response = $this->make_request($full_url, $request_body, 'POST');
68
69
70 return [
71 'rows' => $response['rows'] ?? [],
72 'responseAggregationType' => $response['responseAggregationType'] ?? null,
73 ];
74 }
75
76 /**
77 * Test the connection to the API
78 *
79 * @return array Connection test result
80 *
81 * @throws \Exception On failure.
82 */
83 public function test_connection(): array {
84 try {
85 // We can't easily test without a site URL, but we can check if credentials are present
86 if (empty($this->api_key) && empty($this->access_token)) {
87 throw new \Exception('No API key or Access Token provided.');
88 }
89
90 return [
91 'success' => true,
92 'message' => 'Client initialized with credentials.',
93 ];
94 } catch (\Exception $e) {
95 return [
96 'success' => false,
97 'message' => $e->getMessage(),
98 ];
99 }
100 }
101
102 /**
103 * Get rate limits for this API
104 *
105 * @return array Rate limit configuration
106 */
107 protected function get_rate_limits(): array {
108 return [
109 // Shares Google Search Console's 2000 requests/day quota — this client
110 // hits the same GSC endpoint as Google_Search_Console_Client, so it must
111 // count against the same budget instead of running effectively unlimited.
112 'max_requests_per_day' => 2000,
113 'reset_time' => get_transient($this->get_rate_limit_key() . '_reset') ?: strtotime('tomorrow'),
114 ];
115 }
116
117 /**
118 * Get the rate limit key for creating unique transients
119 *
120 * Uses the same plugin-prefixed key as Google_Search_Console_Client so both
121 * clients share (and jointly respect) the single GSC daily quota.
122 *
123 * @return string Rate limit key
124 */
125 protected function get_rate_limit_key(): string {
126 return 'thinkrank_gsc_rate_limit';
127 }
128
129 /**
130 * Get the error message to display when rate limit is exceeded
131 *
132 * @return string Error message
133 */
134 protected function get_rate_limit_error_message(): string {
135 return 'Google Search Console API rate limit exceeded. Please try again later.';
136 }
137 }
138