How SEO analytics collection works
The problem: search platforms report metrics in cumulative windows, with multi-day lag, retroactive corrections and per-surface quirks. Read naively, the data produces confident nonsense. The analytics layer’s job is to turn that into owned time series with the distortions named and handled.
Layer 1 — collectors into owned storage
Section titled “Layer 1 — collectors into owned storage”A daily collection run sweeps the connected sources — search console (impressions, clicks, queries, indexation), a second search engine’s webmaster surface, SERP presence and discovery-eligibility probes, CDN analytics, and a domain-authority probe — each as its own collector with its own cadence quirks. Everything lands in six Postgres tables with idempotent upserts on natural keys; the raw per-day JSON is treated as ephemeral scratch. The database is the only durable truth.
Layer 2 — the instance snapshot and health score
Section titled “Layer 2 — the instance snapshot and health score”The workhorse table is the daily per-site snapshot: one row per site per day, carrying the raw window values plus a computed composite health score and a set of boolean health flags — canonicalization drift, scheme mismatches, feed bloat, title overflow, crawler silence, rising 404s. One function computes all of it, so the dashboard, the nightly report and the alerts read the same verdicts.
Layer 3 — the distortions, named
Section titled “Layer 3 — the distortions, named”This is the part most analytics setups leave implicit. Rules for reading this data, stated as system knowledge:
- Cumulative windows. Snapshot impression/click values are long-window cumulative totals — a weekly figure is always the delta of two snapshots, never a raw column.
- Maturation lag. Fresh days arrive incomplete and get corrected for up to several days — a zero delta on yesterday means “not finalized”, not “no impressions”.
- Top-N breakdowns never sum to totals — expected sampling behavior, not a data-quality bug.
- Different windows per source. The CDN reports rolling 30-day windows; bot-hit sampling uses a shorter adaptive window; the two cannot be compared cell-to-cell.
The topic feedback loop consumes this data through maturity filters precisely because of these distortions — young pages are excluded from verdicts until their signal has settled.
The trade-offs, honestly
Section titled “The trade-offs, honestly”Some cells of the matrix are deliberately empty: one analytics suite and one commercial SEO API are not integrated (evaluated, not wired); the page-experience collector exists but is skipped in production to conserve quota; and the geographic breakdown is collected upstream but not yet persisted into the time series — a documented gap, so nobody mistakes “not stored” for “no traffic”. The authority probe runs through an indirect weekly path because the production host’s address class is blocked by the provider — an honest workaround, recorded as such.
See it in two minutes
Section titled “See it in two minutes”The analytics API domain exposes the snapshots and health flags; the
weekly owner report is built from exactly these tables — every number in
it traceable to a row.
Specs: SPEC-068 (analytics storage), SPEC-086/087 (probes), SPEC-096 (health detectors), SPEC-125 (the consuming loop).