dateModified, weak Open Graph cards, no pagination noindex, ambiguous entity signals to Google's Knowledge Graph. Two specs worked through them. The result: every page now ships a coherent JSON-LD graph linking the site, the author, and the publisher across stable @id URIs. Articles emit BlogPosting plus a BreadcrumbList; the homepage layout emits Person plus Organization with sameAs links to every owned profile. Pagination pages emit noindex,follow so link equity flows through without polluting the index.scripts/seo-snapshot.mjs uses the same service-account credentials but bypasses the MCP entirely, pulling Google Search Console, Google Analytics 4, Bing Webmaster Tools, and Google Ads Keyword Planner directly into a single dated JSON snapshot. Snapshots are committed to git because Google's data window is only 16 months, and what isn't snapshotted is lost forever. A companion scripts/seo-snapshot-diff.mjs prints the delta between any two snapshots with ANSI colors and box-drawing characters in the terminal, falling back to plain ASCII for CI and pipes.scripts/keyword-audit-articles.mjs flags every article where Google Ads suggests a higher-volume keyword the article could target with light editing. scripts/keyword-discover-topics.mjs produces a ranked editorial backlog seeded from the site's article categories and top GSC queries, filtering out anything already covered by existing slugs. scripts/keyword-validate-lps.mjs verdicts each landing page as WELL_TARGETED, UNDER_INVESTED, or OVER_AMBITIOUS. scripts/keyword-probe-url.mjs is a one-shot competitor URL probe. Each report writes dated markdown into docs/strategy/data/. Future Claude Code agents can invoke any of these scripts, ingest the output, and incorporate it into the next quarterly audit doc without human intervention beyond final review. The agent brief in docs/documentation/agents/ documents the full surface so a fresh agent session can pick up the work without re-discovery.gsc.topQueries table inside each snapshot. Drift detection is now a seo-snapshot-diff.mjs call. Editorial decisions can cite specific numbers from the latest snapshot instead of intuition. And because every spec was scoped tightly and the scripts share a single auth module at scripts/lib/google-ads.mjs, the whole pipeline can be extended (a fifth engine, a new report shape, a different cadence) without touching the existing surface.Posted Sep 12, 2026
Built a repeatable, data-driven SEO operation for coffey.codes.