PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.12.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.12.0
2.12.0 2.11.0 2.10.0 2.9.0 2.8.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 All 53 releases
← All changes | includes/integrations/class-google-search-console-client.php +11 -81 1.26.0 → 2.12.0 View file →
@@ -61,10 +61,16 @@
61 61 'message' => 'Google Search Console API connection successful',
62 62 'sites_count' => count($result['siteEntry'] ?? [])
63 63 ];
64 64 } catch (\Exception $e) {
65 + // `message` as well as `error`: the success branch above reports
66 + // its outcome as `message`, and every consumer reads that key, so
67 + // a failure that only set `error` was reported to the admin as an
68 + // error with no reason at all (#852). `error` is kept for any
69 + // caller that already reads it.
65 70 return [
66 71 'success' => false,
72 + 'message' => $e->getMessage(),
67 73 'error' => $e->getMessage()
68 74 ];
69 75 }
70 76 }
@@ -133,9 +139,9 @@
133 139 $days = (int) str_replace('d', '', $date_range);
134 140 $end_date = gmdate('Y-m-d', strtotime('-2 days'));
135 141 $start_date = gmdate('Y-m-d', strtotime('-' . ($days - 1) . ' days', strtotime($end_date)));
136 142
137 - $endpoint = '/sites/' . urlencode($site_url) . '/searchAnalytics/query';
143 + $endpoint = '/sites/' . rawurlencode($site_url) . '/searchAnalytics/query';
138 144
139 145 $request_body = [
140 146 'startDate' => $start_date,
141 147 'endDate' => $end_date,
@@ -161,9 +167,9 @@
161 167 $days = (int) str_replace('d', '', $date_range);
162 168 $end_date = gmdate('Y-m-d', strtotime('-2 days'));
163 169 $start_date = gmdate('Y-m-d', strtotime('-' . ($days - 1) . ' days', strtotime($end_date)));
164 170
165 - $endpoint = '/sites/' . urlencode($site_url) . '/searchAnalytics/query';
171 + $endpoint = '/sites/' . rawurlencode($site_url) . '/searchAnalytics/query';
166 172
167 173 // diverse from get_search_performance: no dimensions, just totals
168 174 $request_body = [
169 175 'startDate' => $start_date,
@@ -209,9 +215,9 @@
209 215 * @return array Aggregated totals
210 216 * @throws \Exception If API request fails
211 217 */
212 218 public function get_search_totals_by_dates(string $site_url, string $start_date, string $end_date): array {
213 - $endpoint = '/sites/' . urlencode($site_url) . '/searchAnalytics/query';
219 + $endpoint = '/sites/' . rawurlencode($site_url) . '/searchAnalytics/query';
214 220
215 221 $request_body = [
216 222 'startDate' => $start_date,
217 223 'endDate' => $end_date,
@@ -246,9 +252,9 @@
246 252 * @return array Raw rows from GSC API
247 253 * @throws \Exception If API request fails
248 254 */
249 255 public function get_search_performance_by_dates(string $site_url, string $start_date, string $end_date, int $row_limit = 500, array $dimensions = ['query']): array {
250 - $endpoint = '/sites/' . urlencode($site_url) . '/searchAnalytics/query';
256 + $endpoint = '/sites/' . rawurlencode($site_url) . '/searchAnalytics/query';
251 257
252 258 $request_body = [
253 259 'startDate' => $start_date,
254 260 'endDate' => $end_date,
@@ -308,41 +314,8 @@
308 314 }
309 315 }
310 316
311 317 /**
312 - * Get page performance data for SEO analytics
313 - *
314 - * @param string $site_url Site URL to get data for
315 - * @param string $date_range Date range for data
316 - * @param int $limit Number of pages to retrieve
317 - * @return array Page performance data
318 - * @throws \Exception If API request fails
319 - */
320 - public function get_page_performance(string $site_url, string $date_range = '30d', int $limit = 25): array {
321 - $result = $this->get_search_performance($site_url, $date_range, ['page'], $limit);
322 -
323 - $pages = [];
324 - $rows = $result['rows'] ?? [];
325 -
326 - foreach ($rows as $row) {
327 - $pages[] = [
328 - 'page' => $row['keys'][0] ?? '',
329 - 'clicks' => $row['clicks'] ?? 0,
330 - 'impressions' => $row['impressions'] ?? 0,
331 - 'ctr' => round(($row['ctr'] ?? 0) * 100, 2), // Convert to percentage
332 - 'position' => round($row['position'] ?? 0, 1)
333 - ];
334 - }
335 -
336 - return [
337 - 'pages' => $pages,
338 - 'site_url' => $site_url,
339 - 'date_range' => $date_range,
340 - 'total_pages' => count($pages)
341 - ];
342 - }
343 -
344 - /**
345 318 * Get device performance breakdown for mobile SEO insights
346 319 *
347 320 * @param string $site_url Site URL to get data for
348 321 * @param string $date_range Date range for data
@@ -403,51 +376,8 @@
403 376 ];
404 377 }
405 378
406 379 /**
407 - * Get site indexing status and coverage data
408 - *
409 - * @param string $site_url Site URL to check
410 - * @return array Indexing status and coverage data
411 - * @throws \Exception If API request fails
412 - */
413 - public function get_indexing_status(string $site_url): array {
414 - try {
415 - // Get overall search performance to estimate indexed pages
416 - $performance = $this->get_search_performance($site_url, '30d', ['page'], 1000);
417 - $indexed_pages = count($performance['rows'] ?? []);
418 -
419 - // Get basic site info
420 - $sites = $this->list_sites();
421 - $site_info = null;
422 -
423 - foreach ($sites['siteEntry'] ?? [] as $site) {
424 - if ($site['siteUrl'] === $site_url) {
425 - $site_info = $site;
426 - break;
427 - }
428 - }
429 -
430 - return [
431 - 'site_url' => $site_url,
432 - 'is_verified' => !is_null($site_info),
433 - 'indexed_pages_estimate' => $indexed_pages,
434 - 'permission_level' => $site_info['permissionLevel'] ?? 'none',
435 - 'last_updated' => gmdate('Y-m-d H:i:s')
436 - ];
437 - } catch (\Exception $e) {
438 - return [
439 - 'site_url' => $site_url,
440 - 'is_verified' => false,
441 - 'indexed_pages_estimate' => 0,
442 - 'permission_level' => 'none',
443 - 'error' => $e->getMessage(),
444 - 'last_updated' => gmdate('Y-m-d H:i:s')
445 - ];
446 - }
447 - }
448 -
449 - /**
450 380 * Get keyword opportunities for SEO insights
451 381 * Identifies queries with high impressions but low CTR or position
452 382 *
453 383 * @param string $site_url Site URL to analyze
@@ -597,9 +527,9 @@
597 527 * @param string[] $brand_terms Brand keywords to match (substring, case-insensitive)
598 528 * @return array { branded: {...}, non_branded: {...}, total_clicks: int }
599 529 */
600 530 private function gsc_split_by_brand(string $site_url, string $start, string $end, array $brand_terms): array {
601 - $url = self::API_BASE_URL . '/sites/' . urlencode($site_url) . '/searchAnalytics/query';
531 + $url = self::API_BASE_URL . '/sites/' . rawurlencode($site_url) . '/searchAnalytics/query';
602 532
603 533 $page_size = 25000;
604 534 $start_row = 0;
605 535 $total_clicks = 0;