A page-one ranking that nobody clicks is the cheapest problem in SEO to fix. The ranking work is done; the snippet is losing the click. This playbook finds those rows and sizes the clicks being left on the table.
Steps
-
Pull query and page rows.
google_search_console.querywithdimensions: ["query", "page"], a 28-day window ending 3 days ago,rowLimit: 2000. -
Keep page one, with real impressions. Filter to average position 1 to 10 and set an impressions floor (200 over 28 days is sensible; state the one you used). Strip branded queries first: their CTR is naturally very high and will distort everything below.
-
Build the site's own CTR curve. Round position to the nearest integer and take the median CTR of the remaining rows at each position 1 to 10. Use the site's own curve rather than an industry benchmark: a brand-heavy site or one whose results carry rich snippets has a curve of its own, and a generic one will flag the wrong rows.
-
Flag the underperformers and size them. A row is an underperformer when its CTR is below half the site median at its position. For each, compute missed clicks as (median CTR minus actual CTR) times impressions. Sort by missed clicks descending. This is the priority list.
-
Rule out SERP features before blaming the snippet. If rows at positions 1 to 3 are underperforming across the board, the query is probably being answered on the page by a featured snippet or AI overview, and no title rewrite will recover it. Run
google_search_console.querywithdimensions: ["searchAppearance"]over the same window to see how much of the site's visibility carries rich result types, and check the live result for the top few flagged queries with your own browsing. -
Compare the snippet to the query. Fetch each flagged page and read its title and meta description. The usual failures: the title leads with the brand instead of the topic, the description is a generic boilerplate, the title promises something different from what the query asks, or the page has no description and Google is picking a bad excerpt.
-
Report. A table sorted by missed clicks: query, page, position, impressions, clicks, CTR, site median CTR at that position, missed clicks. Then concrete rewrites for the top five, with the target query in the title and a description that answers the intent. Keep the SERP-feature cases in a separate group labelled "cannot be fixed by copy".
Gotchas
- Never compare CTR across positions. Position 1 and position 8 have different expected CTRs by a factor of ten. The comparison is always within a position band.
- An average position hides a split. A row "at 3.2" may be position 1 on desktop and 8 on mobile. Add
dimensions: ["query", "page", "device"]before diagnosing the biggest rows. - Tiny impression counts produce noisy CTRs. Ten impressions and zero clicks is not evidence of anything. Keep the floor.
- Sitelinks and brand queries look like huge CTR. They are, and they are not opportunities. That is why brand queries are stripped in step 2.
- Search Console lags 2 to 3 days. End the window 3 days back.