PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.4.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.4.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 / seo / email-report-sections / class-position-summary-section.php

class-position-summary-section.php in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO 2.4.0, at includes/seo/email-report-sections/class-position-summary-section.php

81 lines 2.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Position Summary Section
4 *
5 * Buckets tracked keywords into Top 3 / 4–10 / 11–50 / 51–100 brackets.
6 * Source: GSC `position_distribution` already computed by Analytics_Manager.
7 *
8 * @package ThinkRank
9 * @subpackage SEO\Email_Report_Sections
10 * @since 1.9.0
11 */
12
13 declare(strict_types=1);
14
15 namespace ThinkRank\SEO\Email_Report_Sections;
16
17 if (!defined('ABSPATH')) {
18 exit;
19 }
20
21 final class Position_Summary_Section implements Email_Report_Section_Interface {
22
23 public function key(): string {
24 return 'position_summary';
25 }
26
27 public function label(): string {
28 return __('Position Summary', 'thinkrank');
29 }
30
31 public function default_enabled(): bool {
32 return true;
33 }
34
35 public function requires_capability(): ?string {
36 return null;
37 }
38
39 public function collect(array $context): array {
40 $shared = $context['shared'] ?? [];
41 if (empty($shared['available'])) {
42 return [];
43 }
44 $dist = $shared['current']['search_performance']['position_distribution'] ?? [];
45 if (!is_array($dist) || empty($dist)) {
46 return [];
47 }
48 return [
49 'top_3' => (int) ($dist['top_3'] ?? 0),
50 '4_10' => (int) ($dist['4_10'] ?? 0),
51 '11_50' => (int) ($dist['10_50'] ?? 0), // GSC's `10_50` bucket starts at 11
52 '51_100' => (int) ($dist['51_100'] ?? 0),
53 ];
54 }
55
56 public function render(array $payload): string {
57 $rows = [
58 __('Top 3', 'thinkrank') => $payload['top_3'],
59 __('Position 4–10', 'thinkrank') => $payload['4_10'],
60 __('Position 11–50', 'thinkrank') => $payload['11_50'],
61 __('Position 51–100', 'thinkrank') => $payload['51_100'],
62 ];
63
64 $html = '<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="border-collapse:collapse;">';
65 foreach ($rows as $label => $count) {
66 $html .= '<tr>'
67 . '<td style="padding:10px 12px;border-bottom:1px solid #e5e7eb;color:#374151;font:500 14px/1.4 -apple-system,Segoe UI,Roboto,sans-serif;">' . esc_html($label) . '</td>'
68 . '<td style="padding:10px 12px;border-bottom:1px solid #e5e7eb;text-align:right;color:#111827;font:700 14px/1.4 -apple-system,Segoe UI,Roboto,sans-serif;">' . esc_html(number_format_i18n((int) $count)) . '</td>'
69 . '</tr>';
70 }
71 $html .= '</table>';
72 return $html;
73 }
74
75 public function fallback_html(): string {
76 return '<p style="color:#6b7280;font-style:italic;">'
77 . esc_html__('Search Console data unavailable. Connect Search Console to see position distribution.', 'thinkrank')
78 . '</p>';
79 }
80 }
81