PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.2.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.2.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-key-metrics-section.php

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

91 lines 3.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Key Metrics Section
4 *
5 * Renders traffic, impressions, average position, and total tracked keywords
6 * for the period. PRD §3, Sections-to-Include item 1.
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 Key_Metrics_Section implements Email_Report_Section_Interface {
22
23 public function key(): string {
24 return 'key_metrics';
25 }
26
27 public function label(): string {
28 return __('Key Metrics', '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 $current = $shared['current'] ?? [];
45 $traffic = $current['traffic'] ?? [];
46 $search = $current['search_performance'] ?? [];
47 $totals = $search['totals'] ?? [];
48
49 return [
50 'sessions' => (int) ($traffic['sessions'] ?? 0),
51 'users' => (int) ($traffic['users'] ?? 0),
52 'impressions' => (int) ($totals['impressions'] ?? 0),
53 'clicks' => (int) ($totals['clicks'] ?? 0),
54 'avg_position' => (float) ($totals['position'] ?? 0.0),
55 'total_keywords' => (int) (count($search['rows'] ?? [])),
56 ];
57 }
58
59 public function render(array $payload): string {
60 $cells = [
61 __('Sessions', 'thinkrank') => number_format_i18n((int) $payload['sessions']),
62 __('Users', 'thinkrank') => number_format_i18n((int) $payload['users']),
63 __('Impressions', 'thinkrank') => number_format_i18n((int) $payload['impressions']),
64 __('Clicks', 'thinkrank') => number_format_i18n((int) $payload['clicks']),
65 __('Avg. Position', 'thinkrank') => number_format_i18n((float) $payload['avg_position'], 1),
66 __('Tracked Keywords', 'thinkrank') => number_format_i18n((int) $payload['total_keywords']),
67 ];
68
69 $html = '<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="border-collapse:collapse;">';
70 $i = 0;
71 foreach ($cells as $label => $value) {
72 if ($i % 3 === 0) {
73 $html .= ($i === 0 ? '<tr>' : '</tr><tr>');
74 }
75 $html .= '<td style="width:33%;padding:10px;border:1px solid #e5e7eb;background:#f9fafb;text-align:center;">'
76 . '<div style="font:500 12px/1.2 -apple-system,Segoe UI,Roboto,sans-serif;color:#6b7280;text-transform:uppercase;letter-spacing:.04em;">' . esc_html($label) . '</div>'
77 . '<div style="font:700 20px/1.2 -apple-system,Segoe UI,Roboto,sans-serif;color:#111827;margin-top:4px;">' . esc_html($value) . '</div>'
78 . '</td>';
79 $i++;
80 }
81 $html .= '</tr></table>';
82 return $html;
83 }
84
85 public function fallback_html(): string {
86 return '<p style="color:#6b7280;font-style:italic;">'
87 . esc_html__('Data temporarily unavailable. Please check your connected integrations.', 'thinkrank')
88 . '</p>';
89 }
90 }
91