gsc-cli 2.0.2 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/AUTH.md +205 -0
- data/FUNDING.md +120 -0
- data/README.md +463 -299
- data/bin/gsc +29158 -4921
- data/dist/gsc +29158 -4921
- data/lib/gsc/aio_hunter.rb +343 -0
- data/lib/gsc/answer_synthesizer.rb +157 -0
- data/lib/gsc/api.rb +53 -1
- data/lib/gsc/auth.rb +26 -0
- data/lib/gsc/backlinks_manager.rb +96 -0
- data/lib/gsc/brand_segmenter.rb +140 -0
- data/lib/gsc/cache_manager.rb +806 -0
- data/lib/gsc/cannibalization_analyzer.rb +141 -0
- data/lib/gsc/canonical_chains.rb +367 -0
- data/lib/gsc/citation_simulator.rb +339 -0
- data/lib/gsc/cli/aio_hunter.rb +154 -0
- data/lib/gsc/cli/analytics.rb +788 -0
- data/lib/gsc/cli/audit.rb +1976 -0
- data/lib/gsc/cli/base.rb +384 -0
- data/lib/gsc/cli/cache.rb +266 -0
- data/lib/gsc/cli/canonical.rb +223 -0
- data/lib/gsc/cli/citation_simulator.rb +152 -0
- data/lib/gsc/cli/dashboard.rb +354 -0
- data/lib/gsc/cli/doctor.rb +129 -0
- data/lib/gsc/cli/eeat.rb +125 -0
- data/lib/gsc/cli/ga4.rb +852 -0
- data/lib/gsc/cli/growth.rb +650 -0
- data/lib/gsc/cli/hreflang.rb +164 -0
- data/lib/gsc/cli/image_seo.rb +162 -0
- data/lib/gsc/cli/indexing.rb +458 -0
- data/lib/gsc/cli/intent_shift.rb +125 -0
- data/lib/gsc/cli/keyword_value.rb +134 -0
- data/lib/gsc/cli/keywords.rb +795 -0
- data/lib/gsc/cli/landing_roi.rb +308 -0
- data/lib/gsc/cli/low_ctr.rb +213 -0
- data/lib/gsc/cli/mobile_parity.rb +150 -0
- data/lib/gsc/cli/report.rb +100 -0
- data/lib/gsc/cli/rich_results.rb +172 -0
- data/lib/gsc/cli/schema_generate.rb +149 -0
- data/lib/gsc/cli/seasonal.rb +232 -0
- data/lib/gsc/cli/security.rb +153 -0
- data/lib/gsc/cli/setup.rb +1291 -0
- data/lib/gsc/cli/sitemap_tree.rb +143 -0
- data/lib/gsc/cli/skill_pack.rb +62 -0
- data/lib/gsc/cli/soft_404.rb +199 -0
- data/lib/gsc/cli/sparkline.rb +227 -0
- data/lib/gsc/cli/watchdog.rb +150 -0
- data/lib/gsc/cli/zombie_purger.rb +208 -0
- data/lib/gsc/cli.rb +706 -5111
- data/lib/gsc/cli_advanced.rb +1513 -0
- data/lib/gsc/client.rb +17 -2
- data/lib/gsc/color.rb +16 -1
- data/lib/gsc/command_registry.rb +47 -9
- data/lib/gsc/config.rb +11 -2
- data/lib/gsc/content_gap.rb +112 -0
- data/lib/gsc/ctr_curve.rb +115 -0
- data/lib/gsc/decay_predictor.rb +322 -0
- data/lib/gsc/doctor.rb +434 -0
- data/lib/gsc/eeat_auditor.rb +428 -0
- data/lib/gsc/entity_auditor.rb +229 -0
- data/lib/gsc/firewall_scanner.rb +733 -0
- data/lib/gsc/geo_auditor.rb +368 -0
- data/lib/gsc/google_suggest.rb +109 -0
- data/lib/gsc/google_trends.rb +8 -1
- data/lib/gsc/heading_validator.rb +283 -0
- data/lib/gsc/hreflang_validator.rb +412 -0
- data/lib/gsc/image_seo.rb +286 -0
- data/lib/gsc/indexing_queue.rb +179 -0
- data/lib/gsc/indexnow.rb +93 -0
- data/lib/gsc/intent_shift.rb +188 -0
- data/lib/gsc/internal_links.rb +249 -0
- data/lib/gsc/keyword_value.rb +191 -0
- data/lib/gsc/landing_roi.rb +195 -0
- data/lib/gsc/llms_generator.rb +425 -0
- data/lib/gsc/low_ctr_rewriter.rb +408 -0
- data/lib/gsc/mobile_parity.rb +222 -0
- data/lib/gsc/network_tracer.rb +93 -0
- data/lib/gsc/open_page_rank.rb +72 -0
- data/lib/gsc/page_analyzer.rb +47 -7
- data/lib/gsc/page_comparator.rb +108 -0
- data/lib/gsc/page_speed.rb +110 -0
- data/lib/gsc/prompts.rb +38 -29
- data/lib/gsc/questions_harvester.rb +178 -0
- data/lib/gsc/report_generator.rb +461 -0
- data/lib/gsc/rich_results.rb +388 -0
- data/lib/gsc/robots_checker.rb +114 -0
- data/lib/gsc/schema_generator.rb +788 -0
- data/lib/gsc/schema_validator.rb +120 -0
- data/lib/gsc/seasonal_predictor.rb +381 -0
- data/lib/gsc/security_scanner.rb +496 -0
- data/lib/gsc/serp_feature_detector.rb +359 -0
- data/lib/gsc/serp_preview.rb +152 -0
- data/lib/gsc/site_crawler.rb +113 -21
- data/lib/gsc/sitemap_loader.rb +15 -4
- data/lib/gsc/sitemap_tree.rb +301 -0
- data/lib/gsc/skill_pack.rb +195 -0
- data/lib/gsc/soft_404_analyzer.rb +385 -0
- data/lib/gsc/sparkline.rb +171 -0
- data/lib/gsc/speed_correlator.rb +416 -0
- data/lib/gsc/striking_playbook.rb +190 -0
- data/lib/gsc/title_optimizer.rb +420 -0
- data/lib/gsc/vault.rb +260 -0
- data/lib/gsc/version.rb +1 -1
- data/lib/gsc/watchdog.rb +235 -0
- data/lib/gsc/zombie_purger.rb +366 -0
- data/lib/gsc.rb +144 -0
- metadata +91 -2
data/lib/gsc/prompts.rb
CHANGED
|
@@ -11,7 +11,7 @@ module GSC
|
|
|
11
11
|
title: 'The 360° Multi-Horizon Master SEO & Universal Keyword Audit',
|
|
12
12
|
impact: 'Maximum Impact (Exhaustive 30d, 90d, 180d audit & action plan)',
|
|
13
13
|
cli_command: 'gsc performance --days 180 --json',
|
|
14
|
-
template: "
|
|
14
|
+
template: "Perform an exhaustive 360° SEO, Universal Keyword, and Crawl Health Audit for {{domain}} across 30d, 90d, and 180d horizons.\n\nExecute the following commands with --json and save the final report to docs/seo/master_audit_report.md (and as an agent artifact if your environment supports artifacts):\n\n1. Macro Multi-Horizon Performance & Trends:\n - `gsc performance --days 30 --json`\n - `gsc performance --days 90 --json`\n - `gsc performance --days 180 --json`\n - `gsc decay --compare 28 --json`\n\n2. Universal Keyword Intelligence (Saved & Unsaved):\n - Check all saved snapshots: `gsc saved check 1 --json`\n - Unsaved live search queries: `gsc top-queries --days 180 --limit 500 -s imp --json`\n - Page 2 striking distance: `gsc opportunities --min-imp 5 --limit 100 --json`\n - CTR underperformers: `gsc underperformers --limit 50 --json`\n - Keyword cannibalization conflicts: `gsc cannibalization --json`\n\n3. Google Trends & Autocomplete Velocity:\n - `gsc trends \"{{seed}}\" --time 12m --json`\n - `gsc planner \"{{seed}}\" --json`\n\n4. Landing Pages, Post-Click GA4 Behavior & Crawl Budget:\n - Top traffic landing pages: `gsc top-pages --days 90 --limit 100 --json`\n - Organic bounce & engagement: `gsc ga4 --organic --days 30 --limit 100 --json`\n - SERP vs Bounce correlation: `gsc correlation --organic --json`\n - Sitemap crawl waste: `gsc zombies public/sitemap.xml --json`\n\nGenerate a Master Executive Report containing:\n1. Executive Growth Scorecard (Macro comparison: 30d vs 90d vs 180d clicks, impressions, CTR, pos).\n2. The Universal Keyword Opportunity Matrix (Ranking, Striking Distance, Untargeted Saved Keywords).\n3. Google Trends Seasonal Velocity & Rising Breakouts (+5000% queries).\n4. CTR Optimization Matrix (Title & meta rewrites for low-CTR pages).\n5. Post-Click Leak Audit (High organic impressions with high GA4 bounce).\n6. Technical & Zombie Crawl Waste cleanup plan.\n7. Prioritized 30-Day Sprint (P0, P1, P2 with exact file paths and code edits)."
|
|
15
15
|
},
|
|
16
16
|
|
|
17
17
|
# Category: Growth & Striking Distance Opportunities
|
|
@@ -22,7 +22,7 @@ module GSC
|
|
|
22
22
|
title: 'The Page 2 Striking Distance Leap',
|
|
23
23
|
impact: 'High Impact (Push Page 2 keywords to Top 3)',
|
|
24
24
|
cli_command: 'gsc opportunities --min-imp 20 --json',
|
|
25
|
-
template: '
|
|
25
|
+
template: 'Run `gsc opportunities --min-imp 20 --json` for {{domain}}. Find the top 3 striking-distance queries (positions 8–18 with high impressions). For each query, locate its ranking page in our codebase, identify what content is missing compared to top SERP competitors, expand the page with a targeted FAQ and comparison table, and ping Google Indexing API via `gsc index <url>`.'
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
id: 2,
|
|
@@ -31,7 +31,7 @@ module GSC
|
|
|
31
31
|
title: 'The Untargeted Keyword Goldmine',
|
|
32
32
|
impact: 'High Impact (Create high-intent new landing pages)',
|
|
33
33
|
cli_command: 'gsc saved check 1 --json',
|
|
34
|
-
template: '
|
|
34
|
+
template: 'Inspect our saved keyword research with `gsc saved check 1 --json`. Identify the top 5 keywords with Opportunity Score > 65 that are currently flagged as 🚀 Untargeted. For each keyword, propose a dedicated landing page route, draft high-intent metadata, and generate a semantic content outline.'
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
id: 3,
|
|
@@ -40,7 +40,7 @@ module GSC
|
|
|
40
40
|
title: '5-Year Google Trends Seasonal Surf',
|
|
41
41
|
impact: 'Medium Impact (Catch seasonal breakout demand)',
|
|
42
42
|
cli_command: 'gsc trends "{{seed}}" --time 5y --json',
|
|
43
|
-
template: '
|
|
43
|
+
template: 'Run `gsc trends "{{seed}}" --time 5y --json`. Identify the historical peak search months, extract all rising breakout queries (+5000%), and update our landing page headings and marketing banners to capture the upcoming seasonal search surge.'
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
id: 4,
|
|
@@ -49,7 +49,7 @@ module GSC
|
|
|
49
49
|
title: 'Long-Tail Autocomplete Multiplier',
|
|
50
50
|
impact: 'Medium Impact (Target long-tail customer questions)',
|
|
51
51
|
cli_command: 'gsc planner "{{seed}}" --limit 50 --json',
|
|
52
|
-
template: '
|
|
52
|
+
template: 'Run `gsc planner "{{seed}}" --limit 50 --json`. Group all discovered long-tail queries by search intent (Transactional vs Informational), and generate an interactive FAQ accordion component in our template addressing the top 5 customer questions.'
|
|
53
53
|
},
|
|
54
54
|
|
|
55
55
|
# Category: Conversion & Click-Through Rate (CTR)
|
|
@@ -60,7 +60,7 @@ module GSC
|
|
|
60
60
|
title: 'The CTR Underperformer Double',
|
|
61
61
|
impact: 'High Impact (Double organic clicks with 0 rank changes)',
|
|
62
62
|
cli_command: 'gsc underperformers --limit 5 --json',
|
|
63
|
-
template: '
|
|
63
|
+
template: 'Run `gsc underperformers --limit 5 --json` for {{domain}}. For the page with the highest impressions but lowest CTR (<2%), read its current <title> and meta description in our codebase. Rewrite them applying the 50–60 character high-CTR formula (front-loading the exact query, adding bracketed hooks like [2026 Free Tool], and appending brand). Update the file and ping `gsc index <url>`.'
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
66
|
id: 6,
|
|
@@ -69,7 +69,7 @@ module GSC
|
|
|
69
69
|
title: 'Review & FAQ Rich Snippet Enabler',
|
|
70
70
|
impact: 'High Impact (Win star ratings and expandable FAQs in SERP)',
|
|
71
71
|
cli_command: 'gsc snippets --json',
|
|
72
|
-
template: '
|
|
72
|
+
template: 'Run `gsc snippets --json` on {{domain}} to check active search appearances. Then inspect our top traffic pages from `gsc top-pages --json` and inject valid Schema.org JSON-LD structured data (FAQPage or Product) so our Google SERP listings display star ratings and expandable FAQs.'
|
|
73
73
|
},
|
|
74
74
|
{
|
|
75
75
|
id: 7,
|
|
@@ -78,7 +78,7 @@ module GSC
|
|
|
78
78
|
title: 'Headline & H1 Alignment Overhaul',
|
|
79
79
|
impact: 'Medium Impact (Increase on-page conversion rate)',
|
|
80
80
|
cli_command: 'gsc top-queries --limit 10 --json',
|
|
81
|
-
template: '
|
|
81
|
+
template: 'Find our top 3 visited landing pages using `gsc ga4 --organic --json`. Audit their <h1> display headings against our copywriting rules (ensure zero trailing periods, strong benefit promise, and strict alignment with high-volume search queries from `gsc top-queries`).'
|
|
82
82
|
},
|
|
83
83
|
{
|
|
84
84
|
id: 8,
|
|
@@ -87,7 +87,7 @@ module GSC
|
|
|
87
87
|
title: 'Keyword Cannibalization Consolidator',
|
|
88
88
|
impact: 'High Impact (Stop competing against your own pages)',
|
|
89
89
|
cli_command: 'gsc cannibalization --json',
|
|
90
|
-
template: '
|
|
90
|
+
template: 'Run `gsc cannibalization --json` on {{domain}}. Detect any search queries where 2 or more of our URLs are competing against each other and splitting Google impressions. Recommend which URL should be the authoritative canonical, and add cross-linking or 301 redirects to consolidate ranking power.'
|
|
91
91
|
},
|
|
92
92
|
|
|
93
93
|
# Category: GA4 Behavioral, Ads & Conversion Analytics
|
|
@@ -98,7 +98,7 @@ module GSC
|
|
|
98
98
|
title: 'High-Bounce Traffic Leak Plugger',
|
|
99
99
|
impact: 'High Impact (Rescue lost visitors who bounce in <10s)',
|
|
100
100
|
cli_command: 'gsc correlation --json',
|
|
101
|
-
template: '
|
|
101
|
+
template: 'Run `gsc correlation --json`. Correlate high-impression GSC search queries against GA4 bounce rates. Find search queries driving visitors who bounce in under 10 seconds. Audit the page\'s above-the-fold hero section and align the primary value proposition directly to user search intent.'
|
|
102
102
|
},
|
|
103
103
|
{
|
|
104
104
|
id: 10,
|
|
@@ -107,7 +107,7 @@ module GSC
|
|
|
107
107
|
title: 'Real-Time Traffic Wave Monitor',
|
|
108
108
|
impact: 'Medium Impact (Live visitor diagnostic & health check)',
|
|
109
109
|
cli_command: 'gsc realtime --json',
|
|
110
|
-
template: '
|
|
110
|
+
template: 'Run `gsc realtime --json`. Check how many live visitors are currently on {{domain}}, which landing pages they are viewing, and verify that our conversion tracking and call-to-actions on those active pages are operating smoothly.'
|
|
111
111
|
},
|
|
112
112
|
{
|
|
113
113
|
id: 11,
|
|
@@ -116,7 +116,7 @@ module GSC
|
|
|
116
116
|
title: 'Google Ads & Organic Synergy Optimizer',
|
|
117
117
|
impact: 'High Impact (Cut wasted ad spend where you rank #1 organically)',
|
|
118
118
|
cli_command: 'gsc ads --json',
|
|
119
|
-
template: '
|
|
119
|
+
template: 'Run `gsc ads --json` and `gsc top-queries --json`. Identify expensive Google Ads keywords (high CPC) where our site already ranks in Top 3 organically, and suggest pausing those paid ads to save ad spend while doubling down on organic CTR.'
|
|
120
120
|
},
|
|
121
121
|
{
|
|
122
122
|
id: 12,
|
|
@@ -125,7 +125,7 @@ module GSC
|
|
|
125
125
|
title: 'Omni-Channel Attribution & Engagement Audit',
|
|
126
126
|
impact: 'Medium Impact (Identify top converting traffic channels)',
|
|
127
127
|
cli_command: 'gsc channels --days 30 --json',
|
|
128
|
-
template: '
|
|
128
|
+
template: 'Run `gsc channels --days 30 --json`. Compare organic search conversion rates against paid and direct traffic. Highlight which traffic channel has the highest customer engagement rate and recommend channel-specific landing page optimizations.'
|
|
129
129
|
},
|
|
130
130
|
|
|
131
131
|
# Category: Technical SEO, Crawl Health & Indexing
|
|
@@ -136,7 +136,7 @@ module GSC
|
|
|
136
136
|
title: 'The 90-Day Zombie Page Purge',
|
|
137
137
|
impact: 'High Impact (Reclaim crawl budget and prune dead weight)',
|
|
138
138
|
cli_command: 'gsc zombies --json',
|
|
139
|
-
template: '
|
|
139
|
+
template: 'Run `gsc zombies --json` on our sitemap. Identify all low-quality or obsolete pages that have received 0 impressions in the last 90 days. Recommend whether to update them with fresh content or retire them with `gsc remove <url>` to protect crawl budget.'
|
|
140
140
|
},
|
|
141
141
|
{
|
|
142
142
|
id: 14,
|
|
@@ -145,7 +145,7 @@ module GSC
|
|
|
145
145
|
title: 'Sitemap Coverage & Rapid Indexing Blitz',
|
|
146
146
|
impact: 'High Impact (Force Googlebot to index queued pages)',
|
|
147
147
|
cli_command: 'gsc inspect-sitemap https://{{domain}}/sitemap.xml --json',
|
|
148
|
-
template: '
|
|
148
|
+
template: 'Run `gsc inspect-sitemap https://{{domain}}/sitemap.xml --json`. Identify all URLs marked as "Discovered - currently not indexed" or "Crawled - currently not indexed". For any unindexed URL, batch ping Google Indexing API via `gsc index <url>` to accelerate indexing.'
|
|
149
149
|
},
|
|
150
150
|
{
|
|
151
151
|
id: 15,
|
|
@@ -154,7 +154,7 @@ module GSC
|
|
|
154
154
|
title: 'Ranking Decay Early Warning Detection',
|
|
155
155
|
impact: 'High Impact (Arrest traffic loss before it accelerates)',
|
|
156
156
|
cli_command: 'gsc decay --days 28 --json',
|
|
157
|
-
template: '
|
|
157
|
+
template: 'Run `gsc decay --days 28 --json`. Identify queries or pages experiencing period-over-period click or impression drops (>20%). Propose immediate content freshness updates and internal link boosts to reverse the decay.'
|
|
158
158
|
},
|
|
159
159
|
{
|
|
160
160
|
id: 16,
|
|
@@ -163,7 +163,7 @@ module GSC
|
|
|
163
163
|
title: 'Lost Query Resuscitation',
|
|
164
164
|
impact: 'Medium Impact (Recover queries that fell out of Google)',
|
|
165
165
|
cli_command: 'gsc decay --json',
|
|
166
|
-
template: '
|
|
166
|
+
template: 'Run `gsc decay --json` and filter by "lost". Find high-volume keywords that generated traffic last month but completely dropped off this month. Inspect the previous URL and restore missing topical sections.'
|
|
167
167
|
},
|
|
168
168
|
|
|
169
169
|
# Category: Programmatic SEO & Scalable Architecture
|
|
@@ -174,7 +174,7 @@ module GSC
|
|
|
174
174
|
title: 'Programmatic Landing Page Generator',
|
|
175
175
|
impact: 'High Impact (Build 50+ data-driven landing pages)',
|
|
176
176
|
cli_command: 'gsc saved check 1 --json',
|
|
177
|
-
template: '
|
|
177
|
+
template: 'Run `gsc saved check 1 --json`. Extract the top 10 untargeted city or feature keywords. Generate a reusable programmatic template that renders unique, value-dense content for each variation without creating duplicate content.'
|
|
178
178
|
},
|
|
179
179
|
{
|
|
180
180
|
id: 18,
|
|
@@ -183,7 +183,7 @@ module GSC
|
|
|
183
183
|
title: 'Competitor Gap Exploitation via Import',
|
|
184
184
|
impact: 'High Impact (Steal competitor high-volume terms)',
|
|
185
185
|
cli_command: 'gsc import clip --json',
|
|
186
|
-
template: '
|
|
186
|
+
template: 'Run `gsc import clip --json` using our latest competitor export from clipboard. Compare their highest volume keywords against our `gsc top-queries --json`. Identify the 5 most profitable keywords where our competitor ranks but we have zero presence.'
|
|
187
187
|
},
|
|
188
188
|
{
|
|
189
189
|
id: 19,
|
|
@@ -192,7 +192,7 @@ module GSC
|
|
|
192
192
|
title: 'Zero-Click Search & AI Overview Winning Strategy',
|
|
193
193
|
impact: 'High Impact (Win citations in Google AI Overviews)',
|
|
194
194
|
cli_command: 'gsc top-queries -s imp --limit 20 --json',
|
|
195
|
-
template: '
|
|
195
|
+
template: 'Run `gsc top-queries -s imp --limit 20 --json`. Identify informational queries where Google shows AI Overviews or direct answer boxes. Structure our content with concise 40-word definitions, numbered steps, and comparison tables to win the AI Overview citation.'
|
|
196
196
|
},
|
|
197
197
|
{
|
|
198
198
|
id: 20,
|
|
@@ -201,7 +201,7 @@ module GSC
|
|
|
201
201
|
title: 'Mobile vs Desktop SERP Parity Audit',
|
|
202
202
|
impact: 'Medium Impact (Fix mobile ranking discrepancies)',
|
|
203
203
|
cli_command: 'gsc devices --json',
|
|
204
|
-
template: '
|
|
204
|
+
template: 'Run `gsc devices --json`. Compare Mobile CTR vs Desktop CTR for {{domain}}. If mobile CTR lags by more than 30%, inspect our mobile viewport layouts, tap target sizes, and above-the-fold content density.'
|
|
205
205
|
},
|
|
206
206
|
|
|
207
207
|
# Category: Executive Briefings & Daily Standups
|
|
@@ -212,7 +212,7 @@ module GSC
|
|
|
212
212
|
title: '360° Executive SEO Health Briefing',
|
|
213
213
|
impact: 'High Impact (Complete C-Suite progress report)',
|
|
214
214
|
cli_command: 'gsc performance --days 30 --json',
|
|
215
|
-
template: '
|
|
215
|
+
template: 'Run `gsc performance --days 30 --json`, `gsc decay --json`, and `gsc opportunities --json`. Generate a markdown briefing summarizing: Total Clicks & Growth % MoM, Top 3 Emerging Keywords, Top 3 Striking-Distance Opportunities, and 3 Critical Action Items for this sprint.'
|
|
216
216
|
},
|
|
217
217
|
{
|
|
218
218
|
id: 22,
|
|
@@ -221,7 +221,7 @@ module GSC
|
|
|
221
221
|
title: 'New Feature Launch Indexing Blitz',
|
|
222
222
|
impact: 'High Impact (Index new releases within hours)',
|
|
223
223
|
cli_command: 'gsc index {{url}} --json',
|
|
224
|
-
template: '
|
|
224
|
+
template: 'Inspect the metadata, verify Schema markup, confirm robots.txt accessibility, and immediately submit our newly launched page at {{url}} to Google Indexing API via `gsc index {{url}}`.'
|
|
225
225
|
},
|
|
226
226
|
{
|
|
227
227
|
id: 23,
|
|
@@ -230,7 +230,7 @@ module GSC
|
|
|
230
230
|
title: 'Geographic Market Expansion Diagnostic',
|
|
231
231
|
impact: 'Medium Impact (Find international expansion markets)',
|
|
232
232
|
cli_command: 'gsc countries --limit 20 --json',
|
|
233
|
-
template: '
|
|
233
|
+
template: 'Run `gsc countries --limit 20 --json` and `gsc cities --limit 20 --json`. Identify our top 3 international or regional markets outside our primary country. Check if localized currency, language, or shipping details are needed on those landing pages.'
|
|
234
234
|
},
|
|
235
235
|
{
|
|
236
236
|
id: 24,
|
|
@@ -239,7 +239,7 @@ module GSC
|
|
|
239
239
|
title: 'Title Tag Pixel Width & Truncation Audit',
|
|
240
240
|
impact: 'Medium Impact (Prevent Google ... truncation on all pages)',
|
|
241
241
|
cli_command: 'gsc top-pages --limit 25 --json',
|
|
242
|
-
template: '
|
|
242
|
+
template: 'Crawl our sitemap via `gsc inspect-sitemap --json`, extract all page <title> tags from our repository, and flag any titles under 40 characters (too short) or over 60 characters (truncated by Google with ...). Propose rewritten versions for all flagged titles.'
|
|
243
243
|
},
|
|
244
244
|
{
|
|
245
245
|
id: 25,
|
|
@@ -248,7 +248,16 @@ module GSC
|
|
|
248
248
|
title: 'The Daily 5-Minute SEO Standup',
|
|
249
249
|
impact: 'High Impact (Daily check of pulses, wins, and anomalies)',
|
|
250
250
|
cli_command: 'gsc realtime --json',
|
|
251
|
-
template: '
|
|
251
|
+
template: 'Run `gsc realtime --json`, `gsc top-queries --limit 5 --json`, and `gsc decay --json`. Give me a 3-bullet standup: (1) Live visitors right now, (2) Yesterday\'s top performing search query, and (3) Any query that saw an unexpected drop requiring attention.'
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
id: 26,
|
|
255
|
+
category: 'growth',
|
|
256
|
+
category_name: '🚀 Growth & Striking Distance',
|
|
257
|
+
title: 'The Adaptive Question Engine & AI Overview Citation Radar',
|
|
258
|
+
impact: 'Maximum Impact (480d PAA harvest, AI Overview radar, answer synthesis & FAQ injection)',
|
|
259
|
+
cli_command: 'gsc questions-harvest -d {{domain}} --days 480 --synthesize --json',
|
|
260
|
+
template: "Execute an end-to-end autonomous Question Mining, AI Overview Citation Radar, and FAQ Schema Domination workflow for {{domain}}.\n\nStrip all hardcoded brand or niche assumptions—this playbook is 100% adaptive based on the live findings from {{domain}} and previous command outputs.\n\nExecute the following phased workflow step-by-step:\n\n### Phase 1: Deep Retrospective Search Console Harvest (480 Days)\n1. Run `gsc questions-harvest -d {{domain}} --days 480 --json` to uncover every question-intent query that {{domain}} has logged search impressions for across all historical search queries.\n2. Run `gsc strike -d {{domain}} --limit 15 --json` to detect high-impression striking distance queries ranking on Page 2 (Positions 4–20).\n3. From the harvested queries and striking distance results, identify:\n - The Top 3 High-Opportunity Questions (Positions 4–20, prime for rich snippets).\n - Any SERP Defense Questions (Positions 1–3, featured snippet holders).\n - The primary Landing Pages associated with these questions.\n\n### Phase 2: Adaptive Topic & Seed Extraction\n1. Analyze the keywords and questions identified in Phase 1 to dynamically extract the 2–3 core topical entities/themes representing the domain's primary products, services, or features.\n - For example: If queries mention pricing or api integration or security, extract \"pricing\", \"api integration\", etc. Do not assume or hardcode any topic.\n\n### Phase 3: Proactive Live Market Question Mining (People Also Ask & Suggest)\n1. For each core topical entity extracted in Phase 2, run:\n - `gsc questions \"<extracted_seed>\" --limit 20 --json`\n2. Classify discovered market queries into 4 conversion archetypes:\n - How-To / Implementation: Practical questions searchers ask when solving a problem.\n - Commercial Comparison: \"Best\", \"Vs\", \"Alternatives\" searches comparing solutions.\n - Policies & Rules: Compliance, eligibility, and configuration questions.\n - Cost & ROI: Pricing, \"worth it\", and value justification queries.\n\n### Phase 4: Google AI Overview (AIO) Citation Radar\n1. For the top 2 highest-impression queries from Phase 1 and Phase 3, run:\n - `gsc aio-hunter \"<target_query>\" --json`\n2. Analyze the radar telemetry:\n - Is Google displaying an AI Overview (AIO)?\n - What competitor domains does Google cite in the AIO carousel?\n - What specific information-gain statistics or factual bullets are missing from our content that Google is citing from others?\n\n### Phase 5: High-Citability Answer Synthesis & FAQ Schema\n1. Run `gsc questions-harvest -d {{domain}} --days 480 --synthesize --json` to automatically synthesize authoritative, 40–60 word Featured Snippet answers and schema.org FAQPage JSON-LD for our target pages.\n2. For any crucial PAA question discovered in Phase 3 not yet in our GSC logs, run:\n - `gsc answer \"<question>\" --brand {{domain}}`\n to synthesize a high-citability direct answer block with targeted information gain.\n\n### Phase 6: Codebase Integration & Instant Indexing\n1. Locate the source files in our local repository corresponding to the target landing page URLs (e.g. Markdown, HTML, Liquid, JSX/TSX, or Astro/Svelte templates).\n2. Insert an H2/H3 FAQ section containing the synthesized questions and authoritative answers.\n3. Embed the generated `<script type=\"application/ld+json\">` FAQPage schema into the page <head> or body.\n4. Notify Googlebot immediately of the enriched content by triggering:\n - `gsc index <target_url>`\n\nDeliver the final executive summary including:\n- Total questions harvested and new market questions discovered.\n- AI Overview radar assessment (AIO presence, cited competitors, citation strategy).\n- Exact file paths modified and diff of FAQ / schema additions.\n- Google Indexing API submission confirmations."
|
|
252
261
|
}
|
|
253
262
|
].freeze
|
|
254
263
|
|
|
@@ -272,9 +281,9 @@ module GSC
|
|
|
272
281
|
item = find(id)
|
|
273
282
|
return nil unless item
|
|
274
283
|
|
|
275
|
-
dom = domain || Config.default_domain || '
|
|
276
|
-
s = seed || '
|
|
277
|
-
u = url || "https://#{dom}"
|
|
284
|
+
dom = domain || Config.default_domain || '<your-domain.com>'
|
|
285
|
+
s = seed || '<target-keyword>'
|
|
286
|
+
u = url || (dom == '<your-domain.com>' ? '<target-url>' : "https://#{dom}")
|
|
278
287
|
|
|
279
288
|
item[:template]
|
|
280
289
|
.gsub('{{domain}}', dom)
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module GSC
|
|
6
|
+
class QuestionsHarvester
|
|
7
|
+
QUESTION_WORDS = %w[
|
|
8
|
+
who what where when why how can does do did is are should which will would could
|
|
9
|
+
].freeze
|
|
10
|
+
|
|
11
|
+
PHRASE_PATTERNS = [
|
|
12
|
+
/\b(difference between|vs|versus|compared to)\b/i,
|
|
13
|
+
/\b(best way to|how to|guide to|ways to|steps to)\b/i,
|
|
14
|
+
/\b(provider|providers|apps?|tools?|alternatives?|options?|solutions?)\s+(that|to|for|with)\b/i,
|
|
15
|
+
/\b(worth it|is it worth)\b/i,
|
|
16
|
+
/\b(pros and cons)\b/i,
|
|
17
|
+
/\?$/
|
|
18
|
+
].freeze
|
|
19
|
+
|
|
20
|
+
def self.harvest(rows, min_imp: 1, filter_page: nil, brand: nil, synthesize: false)
|
|
21
|
+
# rows: Array of {"keys" => [query, page], "clicks" => n, "impressions" => n, "ctr" => f, "position" => f}
|
|
22
|
+
raw_questions = {}
|
|
23
|
+
|
|
24
|
+
rows.each do |r|
|
|
25
|
+
keys = r['keys'] || []
|
|
26
|
+
query = keys[0].to_s.strip
|
|
27
|
+
page = keys[1].to_s.strip
|
|
28
|
+
|
|
29
|
+
next if query.empty?
|
|
30
|
+
next if filter_page && !page.downcase.include?(filter_page.downcase)
|
|
31
|
+
|
|
32
|
+
q_lower = query.downcase
|
|
33
|
+
is_question = false
|
|
34
|
+
matched_type = nil
|
|
35
|
+
|
|
36
|
+
# Check question words as distinct tokens
|
|
37
|
+
QUESTION_WORDS.each do |w|
|
|
38
|
+
if q_lower =~ /\b#{w}\b/
|
|
39
|
+
is_question = true
|
|
40
|
+
matched_type ||= w.upcase
|
|
41
|
+
break
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Check phrase patterns
|
|
46
|
+
unless is_question
|
|
47
|
+
PHRASE_PATTERNS.each do |pat|
|
|
48
|
+
if q_lower =~ pat
|
|
49
|
+
is_question = true
|
|
50
|
+
matched_type = 'PHRASE'
|
|
51
|
+
break
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
next unless is_question
|
|
57
|
+
|
|
58
|
+
clicks = (r['clicks'] || 0).to_i
|
|
59
|
+
impressions = (r['impressions'] || 0).to_i
|
|
60
|
+
ctr = (r['ctr'] || 0.0).to_f
|
|
61
|
+
position = (r['position'] || 0.0).to_f.round(1)
|
|
62
|
+
|
|
63
|
+
next if impressions < min_imp
|
|
64
|
+
|
|
65
|
+
# Capitalize query nicely as question sentence
|
|
66
|
+
formatted_question = query.sub(/^[a-z]/, &:upcase)
|
|
67
|
+
formatted_question += '?' unless formatted_question.end_with?('?')
|
|
68
|
+
|
|
69
|
+
dedup_key = [formatted_question.downcase, page.downcase]
|
|
70
|
+
|
|
71
|
+
if raw_questions[dedup_key]
|
|
72
|
+
existing = raw_questions[dedup_key]
|
|
73
|
+
existing[:clicks] += clicks
|
|
74
|
+
existing[:impressions] += impressions
|
|
75
|
+
existing[:position] = [existing[:position], position].min
|
|
76
|
+
existing[:ctr] = existing[:impressions].positive? ? ((existing[:clicks].to_f / existing[:impressions]) * 100.0).round(2) : 0.0
|
|
77
|
+
existing[:tier] = classify_tier(existing[:position], existing[:impressions])
|
|
78
|
+
existing[:opportunity_score] = calculate_opportunity_score(existing[:impressions], existing[:position], existing[:clicks])
|
|
79
|
+
else
|
|
80
|
+
opp_tier = classify_tier(position, impressions)
|
|
81
|
+
score = calculate_opportunity_score(impressions, position, clicks)
|
|
82
|
+
|
|
83
|
+
raw_questions[dedup_key] = {
|
|
84
|
+
raw_query: query,
|
|
85
|
+
question: formatted_question,
|
|
86
|
+
type: matched_type,
|
|
87
|
+
page: page,
|
|
88
|
+
clicks: clicks,
|
|
89
|
+
impressions: impressions,
|
|
90
|
+
ctr: (ctr * 100).round(2),
|
|
91
|
+
position: position,
|
|
92
|
+
tier: opp_tier,
|
|
93
|
+
opportunity_score: score
|
|
94
|
+
}
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Sort: High opportunity first, then by impressions descending
|
|
99
|
+
sorted_questions = raw_questions.values.sort_by { |q| [-q[:opportunity_score], -q[:impressions]] }
|
|
100
|
+
|
|
101
|
+
# Group by page
|
|
102
|
+
by_page = Hash.new { |h, k| h[k] = [] }
|
|
103
|
+
sorted_questions.each do |q|
|
|
104
|
+
by_page[q[:page]] << q
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
{
|
|
108
|
+
total_questions_harvested: sorted_questions.size,
|
|
109
|
+
high_opportunity_count: sorted_questions.count { |q| q[:tier] == 'HIGH_OPPORTUNITY' },
|
|
110
|
+
defense_count: sorted_questions.count { |q| q[:tier] == 'SERP_DEFENSE' },
|
|
111
|
+
pages_covered: by_page.keys.size,
|
|
112
|
+
questions: sorted_questions,
|
|
113
|
+
grouped_by_page: by_page,
|
|
114
|
+
recommended_faq_schemas: generate_faq_schemas(by_page, brand: brand, synthesize: synthesize)
|
|
115
|
+
}
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def self.classify_tier(position, impressions)
|
|
119
|
+
if position.between?(4.0, 20.0) && impressions >= 3
|
|
120
|
+
'HIGH_OPPORTUNITY'
|
|
121
|
+
elsif position.between?(1.0, 3.9)
|
|
122
|
+
'SERP_DEFENSE'
|
|
123
|
+
else
|
|
124
|
+
'LONG_TAIL'
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def self.calculate_opportunity_score(impressions, position, clicks)
|
|
129
|
+
# Weight: High impressions ranking in striking distance (pos 4-20) gets highest score
|
|
130
|
+
pos_factor = case position
|
|
131
|
+
when 4.0..10.0 then 3.0 # Page 1 striking distance (huge win potential)
|
|
132
|
+
when 11.0..20.0 then 2.0 # Page 2 striking distance
|
|
133
|
+
when 1.0..3.9 then 1.5 # Defend position 1-3
|
|
134
|
+
else 0.8
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
((impressions * pos_factor) + (clicks * 5)).round(1)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def self.generate_faq_schemas(grouped_by_page, max_per_page: 5, brand: nil, synthesize: false)
|
|
141
|
+
schemas = {}
|
|
142
|
+
|
|
143
|
+
grouped_by_page.each do |page, q_list|
|
|
144
|
+
top_qs = q_list.first(max_per_page)
|
|
145
|
+
entities = top_qs.map do |q|
|
|
146
|
+
answer_text = if synthesize
|
|
147
|
+
begin
|
|
148
|
+
require_relative 'answer_synthesizer' unless defined?(GSC::AnswerSynthesizer)
|
|
149
|
+
res = GSC::AnswerSynthesizer.synthesize(q[:question], brand: brand)
|
|
150
|
+
res[:direct_answer]
|
|
151
|
+
rescue StandardError
|
|
152
|
+
"Authoritative answer explaining #{q[:question]} for #{page.sub(%r{^https?://[^/]+}, '')}."
|
|
153
|
+
end
|
|
154
|
+
else
|
|
155
|
+
"Detailed guidance answering \"#{q[:question]}\" for #{page.sub(%r{^https?://[^/]+}, '')}."
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
{
|
|
159
|
+
'@type' => 'Question',
|
|
160
|
+
'name' => q[:question],
|
|
161
|
+
'acceptedAnswer' => {
|
|
162
|
+
'@type' => 'Answer',
|
|
163
|
+
'text' => answer_text
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
schemas[page] = {
|
|
169
|
+
'@context' => 'https://schema.org',
|
|
170
|
+
'@type' => 'FAQPage',
|
|
171
|
+
'mainEntity' => entities
|
|
172
|
+
}
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
schemas
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|