> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aigrowthagent.co/llms.txt
> Use this file to discover all available pages before exploring further.

# GSC data fidelity

> What the instrument does to the data — anonymization, the 3-day lag, row caps, the daily quota, and remote export files. Read this before trusting any figure from the gsc_* tools.

Read this before trusting any figure from the `gsc_*` tools. Google Search
Console is not a neutral recorder: it censors queries, lags about 3 days,
caps rows, and rate-limits properties. Every rule below exists because a
confident wrong answer was produced without it.

The same content is available mid-session as the resource
`aga://guides/gsc-data-fidelity`.

## Anonymization: named queries are a biased floor

Google withholds rare queries. It is common for well under half of
impressions — and even fewer clicks — to be attributable to a named query.
Three properties of that hidden tail matter:

* **It is not random.** Rare long-tail phrasings live there — exactly where
  conversational AI-style queries sit — and hidden queries often convert
  better than named ones. The named sample is biased, not just incomplete.
* **The naming rate is non-stationary.** The named share can double within
  months as a site grows. Distinct-query counts are NOT comparable across
  periods — later months look broader partly because Google names more of
  them.
* **Zero is the most fragile finding.** NEVER claim "zero clicks" from query
  data. A claim of "zero clicks for an entire intent class" has collapsed
  the moment page-level data was checked: the clicks were real, sitting on
  queries Google refuses to name.

**Get the denominator.** Pull `[page, query]` and read `meta.anonymization`
— it reports named vs anonymized impressions, clicks, and CTR. Query-only
pulls never surface it; you need the page-level denominator alongside the
named total. Pull it early: this block has retracted headline findings after
they were already reported.

Query-frame responses without a page denominator carry a top-level
`queryBiasNote` restating this: `gsc_query_analytics`, `gsc_export_dataset`,
`gsc_query_export`, and `gsc_compare_periods` all say so when their rows are
query-level. Read it as a standing warning, not a per-call observation.

**Operating rule:** use query text to learn WHAT KIND of demand exists and to
find specific opportunities — never to size a segment, compare breadth across
periods, or claim something earns no clicks. Size segments at page level;
page data has no anonymization. Every query-derived figure is a floor. Where
the instrument is biased, quote bounds (page-level ceiling vs named-query
floor), not point estimates. The page-level ceiling can be several times the
named-query floor — the truth is between, and the bound is the quotable
result.

## The \~3-day lag and incompleteDays

GSC data settles over about 3 days; the most recent days revise upward. Cut
analysis at today − 3.

`meta.incompleteDays` flags only dates that fall inside the real lag window —
today−3 … today at the time of the call. Historical pulls carry no flags: a
January export requested in September is complete and says so. Never trend on
flagged days; never discard unflagged historical data because of a stale
mental model of the flag.

## Row cap, partitioning, coverage

* `gsc_export_dataset` caps at 25,000 rows per property per call. Slice large
  accounts by month so every export lands under the cap — a single busy
  month on a growing site can run to tens of thousands of rows.
* Capped pulls auto-partition (device → page-regex) and reconcile against an
  uncapped denominator. Gate impression-based analysis on `coverageRatio` of
  at least 0.98 and `truncatedByApi: false`. Click-based analysis survives
  capping either way — the cap discards the zero-click impression tail first.

## The daily quota

Google enforces a daily per-property load quota. When it trips, EVERYTHING
fails — pulls can fail repeatedly for hours, and a tiny analytics request
fails identically to a huge export, because it is a property-level daily
cap, not a request-size limit. It resets the next day.

When the quota is exhausted the tools return GSC 429 errors with
quota-specific guidance — the daily per-property cap, the next-day reset, and
the budgeting rules below. Treat a 429 as "stop pulling today," not "retry
smaller."

Budget your pulls:

* Enumerate what you need before you start, rather than iterating
  exploratorily against the API.
* Prefer one wide export plus local re-slicing (`gsc_query_export`, or pandas
  over the downloaded JSON) over many narrow calls.
* Exploit the 6-hour identical-params cache instead of re-pulling.
* Have a labelled proxy method ready. When page×query attribution is
  unavailable, pages can be classified by their own target search term
  instead — a documented proxy, clearly labelled, replaced with real
  attribution once quota returns.

## Export files are remote

`gsc_export_dataset` writes the file on the MCP server, not your machine. The
returned `filePath` is a server path — reading it locally fails. The response
also carries a pre-signed `downloadUrl` that expires in about an hour;
`curl` it immediately:

```bash theme={null}
curl -sS -o data/aug.json "https://mcp.aigrowthagent.co/exports/<hash>?exp=...&sig=..."
```

Do not collect URLs and fetch hours later. Files are auto-deleted after 24
hours, and identical params within 6 hours reuse the existing file — pass
`forceRefresh` to bypass.

## Filters and metadata

* A substring path filter catches unrelated URLs — a filter like
  `page contains "articles"` can also match pages that merely contain the
  string. Enumerate what it caught before trusting it.
* `updatedAt` may be a bulk touch: count distinct dates and the max articles
  sharing one — hundreds of articles sharing a handful of timestamps means a
  bulk operation. True update dates may live in content bylines or
  schema.org markup — ask the client what their content contains.
* The session's current account is an in-memory override that can reset
  silently — pass `accountId` explicitly on every call, subagents especially.
  `content_planner_list_questions`'s `questionCounts.total` can undercount;
  the returned rows are authoritative.

## See also

* [First analysis on an account](/guides/first-analysis) — where these rules
  sit in the Phase 0–5 runbook
* [Analysis guardrails](/guides/analysis-guardrails) — the analytical
  patterns for modelling on top of this data
* [Reading Search Console data correctly](/concepts#reading-search-console-data-correctly)
  — aggregation frames, the page-filter trap, and the `meta` block
* [Available MCP tools](/tools#google-search-console-gsc) — full input and
  output reference for the `gsc_*` tools
