PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.14.2
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.14.2
2.14.3 2.14.2 2.14.1 2.14.0 2.13.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 All 58 releases
← All changes | includes/seo/email-report-sections/class-top-winning-keywords-section.php +30 -14 2.7.0 → 2.14.2 View file →
@@ -1,11 +1,12 @@
1 1 <?php
2 2 /**
3 - * Top Winning Keywords Section
3 + * Top Winning Keywords Section — "Top growing queries".
4 4 *
5 - * Keywords with the largest click gain vs the previous period, computed
6 - * from the shared current-vs-previous comparison the Data Provider builds
7 - * from Search Console.
5 + * Queries with the largest click gain vs the previous period, computed from
6 + * the shared current-vs-previous comparison the Data Provider builds from
7 + * Search Console (query dimension). Ranking is on the click delta; average
8 + * position rides along as context.
8 9 *
9 10 * @package ThinkRank
10 11 * @subpackage SEO\Email_Report_Sections
11 12 * @since 1.9.0
@@ -27,9 +28,9 @@
27 28 return 'top_winning_keywords';
28 29 }
29 30
30 31 public function label(): string {
31 - return __('Top Winning Keywords', 'thinkrank');
32 + return __('Top growing queries', 'thinkrank');
32 33 }
33 34
34 35 public function default_enabled(): bool {
35 36 return true;
@@ -38,8 +39,12 @@
38 39 public function requires_capability(): ?string {
39 40 return null;
40 41 }
41 42
43 + public function renders_own_heading(): bool {
44 + return true;
45 + }
46 +
42 47 public function collect(array $context): array {
43 48 $shared = $context['shared'] ?? [];
44 49 $comparison = $shared['comparison'] ?? [];
45 50 if (empty($comparison['available']) || empty($comparison['queries'])) {
@@ -53,16 +58,16 @@
53 58 if ($delta <= 0) {
54 59 continue;
55 60 }
56 61 $rows[] = [
57 - 'query' => $entry['query'] ?? '',
58 - 'position' => isset($entry['cur_pos']) ? (float) $entry['cur_pos'] : null,
59 - 'clicks' => (int) $entry['cur_clicks'],
60 - 'change' => $delta,
62 + 'query' => $entry['query'] ?? '',
63 + 'position' => isset($entry['cur_pos']) ? (float) $entry['cur_pos'] : null,
64 + 'prev_position' => isset($entry['prev_pos']) ? (float) $entry['prev_pos'] : null,
65 + 'clicks' => (int) $entry['cur_clicks'],
66 + 'change' => $delta,
61 67 ];
62 68 }
63 69
64 - // Biggest click gain first.
65 70 usort($rows, static fn($a, $b) => $b['change'] <=> $a['change']);
66 71
67 72 return [
68 73 'rows' => array_slice($rows, 0, self::MAX_ROWS),
@@ -68,14 +73,25 @@
68 73 'rows' => array_slice($rows, 0, self::MAX_ROWS),
69 74 ];
70 75 }
71 76
77 + public function has_data(array $payload): bool {
78 + return !empty($payload['rows']);
79 + }
80 +
72 81 public function render(array $payload): string {
73 - return Top_Posts_Renderer::render_keywords($payload['rows'] ?? [], 'gain');
82 + $rows = Top_Posts_Renderer::keyword_rows($payload['rows'] ?? []);
83 + if ($rows === []) {
84 + return '';
85 + }
86 + return Email_Report_Html::heading(
87 + $this->label(),
88 + __('Search terms that sent more clicks than last period', 'thinkrank')
89 + )
90 + . Email_Report_Html::list_rows($rows, 'up')
91 + . Email_Report_Html::link(__('See all queries', 'thinkrank'), Email_Report_Html::admin_link('analytics', 'keywords'));
74 92 }
75 93
76 94 public function fallback_html(): string {
77 - return '<p style="color:#6b7280;font-style:italic;">'
78 - . esc_html__('Search Console data unavailable. Connect Search Console to see top winning keywords.', 'thinkrank')
79 - . '</p>';
95 + return '';
80 96 }
81 97 }