CEO GSC read: add top-query & top-page breakdown so the board self-diagnoses the funnel #399

Closed
opened 2026-07-20 19:30:33 +00:00 by igor · 0 comments
Collaborator

Problem

lib/ceo.sh:ceo_read_gsc() (~line 384) gives the board only the aggregate scoreboard — it queries just the date dimension (lines 399–400) and renders clicks/impressions/CTR/avg-position, current vs prior. With only totals, the board can't tell where a weak funnel lives — a few head terms hitting the wrong pages, or a long tail with weak snippets — so it files CEO questions asking the operator to pull the query/page breakdown. Two this week alone: sharktankdb.com#82 and certifiedtradejobs.com#45.

The harness already has that data: lib/gsc.sh:gsc_query takes any dimension (query, page, query,page) under the same webmasters.readonly scope the scoreboard already uses. The board is asking the operator for something the machine can fetch itself.

Fix

Extend ceo_read_gsc to also pull and render, for the current window (seo_window):

  • Top queries by impressions (top ~10): impressions / clicks / CTR / position.
  • Top pages by impressions (top ~10): same columns.
  • A one-line concentration signal — e.g. "top-5 queries = N% of impressions across M distinct queries" — the exact discriminator (head-term concentration vs long tail) the board keeps asking for.

Model it on the sibling ceo_read_ga (same .seo.domain gate, same GOOGLE_SERVICE_ACCOUNT gate, same window). Add a sentence to the scoreboard prose telling the board to use the breakdown to diagnose the funnel (concentration vs long-tail; ranking-fine-but-CTR-weak) rather than filing a question for it.

Constraints

  • Read-only; no new OAuth scope (query/page dims are covered by webmasters.readonly).
  • Hardcode the top-N and reuse seo_window — no new config knobs (strong opinions, not dials).
  • Same failure posture as today: token/fetch failure = "scoreboard dark, do NOT guess," never a crash.
  • Still one digest model call; just a couple more gsc_query calls in the same on-demand read.

Tests

Extend the existing ceo_read_gsc block in bin/test-ceo.sh (~line 374): mock gsc_query to return query- and page-dim rows, assert the top-queries/top-pages tables and the concentration line render, and that an empty/failed fetch still degrades to the "scoreboard dark" note. Skip-safe (exit 0 if jq absent), per the suite.

Payoff

The board self-diagnoses the funnel and stops interrupting the operator with data the harness already has — directly serving the review-driven model. Worked example: sharktankdb#82 — the aggregate said "a problem exists"; the query/page pull showed it's long-tail + weak-CTR (season pages ranking page-1 with zero clicks), which aims the structured-data/titles work correctly.

## Problem `lib/ceo.sh:ceo_read_gsc()` (~line 384) gives the board only the **aggregate** scoreboard — it queries just the `date` dimension (lines 399–400) and renders clicks/impressions/CTR/avg-position, current vs prior. With only totals, the board can't tell *where* a weak funnel lives — a few head terms hitting the wrong pages, or a long tail with weak snippets — so it files **CEO questions asking the operator to pull the query/page breakdown**. Two this week alone: `sharktankdb.com#82` and `certifiedtradejobs.com#45`. The harness already has that data: `lib/gsc.sh:gsc_query` takes any dimension (`query`, `page`, `query,page`) under the same `webmasters.readonly` scope the scoreboard already uses. The board is asking the operator for something the machine can fetch itself. ## Fix Extend `ceo_read_gsc` to also pull and render, for the current window (`seo_window`): - **Top queries** by impressions (top ~10): impressions / clicks / CTR / position. - **Top pages** by impressions (top ~10): same columns. - A one-line **concentration signal** — e.g. "top-5 queries = N% of impressions across M distinct queries" — the exact discriminator (head-term concentration vs long tail) the board keeps asking for. Model it on the sibling `ceo_read_ga` (same `.seo.domain` gate, same `GOOGLE_SERVICE_ACCOUNT` gate, same window). Add a sentence to the scoreboard prose telling the board to **use the breakdown to diagnose the funnel** (concentration vs long-tail; ranking-fine-but-CTR-weak) rather than filing a question for it. ## Constraints - Read-only; no new OAuth scope (query/page dims are covered by `webmasters.readonly`). - Hardcode the top-N and reuse `seo_window` — no new config knobs (strong opinions, not dials). - Same failure posture as today: token/fetch failure = "scoreboard dark, do NOT guess," never a crash. - Still one digest model call; just a couple more `gsc_query` calls in the same on-demand read. ## Tests Extend the existing `ceo_read_gsc` block in `bin/test-ceo.sh` (~line 374): mock `gsc_query` to return `query`- and `page`-dim rows, assert the top-queries/top-pages tables and the concentration line render, and that an empty/failed fetch still degrades to the "scoreboard dark" note. Skip-safe (exit 0 if `jq` absent), per the suite. ## Payoff The board self-diagnoses the funnel and stops interrupting the operator with data the harness already has — directly serving the review-driven model. Worked example: `sharktankdb#82` — the aggregate said "a problem exists"; the query/page pull showed it's long-tail + weak-CTR (season pages ranking page-1 with zero clicks), which aims the structured-data/titles work correctly.
igor self-assigned this 2026-07-20 20:50:58 +00:00
igor added spent time 2026-07-20 21:00:21 +00:00
9 minutes
igor removed their assignment 2026-07-20 21:00:21 +00:00
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Total time spent: 9 minutes
igor
9 minutes
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
joshtronic/igor#399
No description provided.