> ## 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.

# First analysis on an account

> The Phase 0–5 runbook for a deep data-science analysis on an account you have never touched — site structure, acquisition, panel construction, ground truth, analysis, reporting.

Read this before running a deep analysis on an account you have never
touched. It is the runbook from real engagements, expanded to the steps,
the gates between them, and what "good" looks like at each gate. The order
matters: each phase establishes facts that can invalidate the next. Skipping
Phase 0 is how confident, wrong, statistically significant answers get
produced.

The same runbook is available mid-session as the resource
`aga://guides/first-analysis`, and the `gsc-content-deep-dive` prompt walks an
agent through it.

## Phase 0 — Site structure (do not skip)

Everything here is cheap to check and expensive to miss.

* Call `gsc_get_context` FIRST — before any performance call. Record the
  publishing base, CMS URL, `reverseProxy`, matched property set, first
  publish date, maturity block, and placeholder flag. A reverse-proxy rewrite
  or migration splits the dataset: every cohort spanning it is invalid.
  Expect undiscovered migrations here — a proxy change discovered late
  invalidates every cohort definition built before the discovery. The
  placeholder flag matters too: accounts still on the shared placeholder
  space will never match a GSC property, and the performance tools refuse to
  pull until the real domain is set.
* Call `gsc_list_sites` — confirm which GSC properties aggregate.
* Enumerate EVERY hostname in a page-dimension export (rows carry
  `tags.hostname` / `tags.pageClass`). Legacy subdomains hide here — it is
  common to find a forgotten `blog.` subdomain quietly holding a large share
  of an intent class at deep positions.
* Identify migrations, replatforms, proxy changes. Each is a structural
  break; cohorts split there.
* Ask the client: what bulk operations ran, and when? What does the content
  itself record (bylines, modified-time meta, schema.org)?

**What good looks like:** you can name every hostname in the property, every
structural break date, and every bulk operation — before you have pulled a
single performance row.

**Common first-timer mistake:** building cohorts from publish dates alone and
discovering the migration after the event study is written.

## Phase 1 — Acquisition, on a budget

Google enforces a daily per-property load quota. When it trips, EVERY call
fails until it resets the next day — narrower date ranges and tiny row limits
fail identically, because it is a property-level daily cap, not a
request-size limit. Enumerate the pulls you need before you start.

1. **Size first.** Call `gsc_query_analytics` before exporting — it is cheap
   (totals plus top rows) and tells you whether the range fits.
2. **Export `[page, date]` in monthly slices**; verify `truncatedByApi: false`
   on each. The cap is 25,000 rows per property per call, and a single busy
   month on a growing site can approach it. Auto-partitioning rescues capped
   pulls, but then you must verify `coverageRatio` of at least 0.98 —
   avoiding the cap is cleaner.
3. **Export `[query, date]`** the same way.
4. **Pull `[page, query]` EARLY** for a recent window and read
   `meta.anonymization` — it reports what fraction of impressions and clicks
   sits on named queries. Do not leave this for later: this block has
   retracted headline findings after they were already reported. See
   [GSC data fidelity](/guides/gsc-data-fidelity).
5. **Download every export immediately.** The file lives on the MCP server,
   not your machine — a local read of the returned `filePath` fails. The
   response carries a pre-signed `downloadUrl` that expires in about an hour:

   ```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.
6. **Pull the content corpus** with `articles_search`
   (statuses `["published"]`): slugs, `publishDate`, `updatedAt`.
7. **Pull the content planner per mode, with an explicit `accountId`** — the
   session's current account is an in-memory override that can reset silently,
   subagents especially. Use the returned rows, not `questionCounts.total`,
   which can undercount badly — the returned rows are authoritative.
8. **Prefer one wide export plus local re-slicing** (`gsc_query_export`, or
   pandas over the downloaded JSON) over many narrow API calls. Identical
   params reuse the 6-hour cache.

**What good looks like:** a written pull list before the first export, every
export under the cap with `truncatedByApi: false`, and every file downloaded
within the hour.

**Common first-timer mistake:** iterating exploratorily against the API until
the quota trips mid-analysis, then losing the afternoon.

## Phase 2 — Panel construction

* **Normalize URLs**: strip fragments (GSC reports table-of-contents anchors
  as distinct URLs — thousands of rows may be fragment duplicates that fold
  back into parent slugs), fold www/non-www, trailing slashes, and query
  strings.
* **Audit every substring path filter.** A filter like
  `page contains "articles"` can also match unrelated URLs that happen to
  contain the string. Enumerate what the filter caught; exclude explicitly
  and record the impression cost.
* **Cut the panel at today − 3 days**; GSC data settles over about 3 days.
  `meta.incompleteDays` flags only dates inside that real lag window — a
  months-old export carries no flags.
* **Reconcile.** Sum the merged exports and compare against a single
  `gsc_query_analytics` call over the same range. Do not proceed until they
  match; after normalization, the panel should differ only by your deliberate
  exclusions. This gate catches filter mistakes, overlapping date ranges,
  and silent truncation.
* **Write canonical intermediates** — one page panel, one query panel.
  Everything downstream reads these, so a normalization fix propagates once.

**What good looks like:** merged totals reconcile exactly, exclusions are
itemized with their impression cost, and one canonical panel file is the
single input to every later step.

## Phase 3 — Ground truth

* **Validate `publishDate`**: does any page show impressions before its
  recorded publish date? If none do, the field can be trusted.
* **Test whether `updatedAt` is real or a bulk touch**: count distinct dates
  and the max articles sharing one. Hundreds of articles sharing a handful
  of timestamps means a bulk operation, not update history.
* **If `updatedAt` is dead, look for the true date IN THE CONTENT**: the
  true dates may exist only in the content itself — bylines, schema.org
  blocks, `article:modified_time`. Ask the client what their content
  contains — in practice this field is recovered because the client mentions
  it, not because analysis finds it.
* **Compute the instrument's coverage PER PERIOD** (named-query share of
  impressions) and check it is stable — the named share can double within
  months as a site grows, and distinct-query counts are not comparable
  across those months.
* **Validate every proxy against ground truth on a sample** before it carries
  an analysis; report the mis-assignment rate. Unvalidated proxies have
  mis-assigned nearly an entire cohort and silently dropped a large share of
  a corpus from every denominator.

**What good looks like:** every date field in the panel is either validated
against the data or labelled as a measured proxy with its error rate.

## Phase 4 — Analysis

Split cohorts at every structural break; de-trend every age curve; use
balanced panels and report N at every point; run placebos before believing
any event study; size segments at page level. The full rule set is the
companion guide [Analysis guardrails](/guides/analysis-guardrails) — read it
before modelling. It exists because each rule, broken once, produced a
confident wrong answer.

## Phase 5 — Reporting

* Quote bounds, not point estimates, wherever the instrument is biased —
  page-level ceiling vs named-query floor. The page-level ceiling can be
  several times the named-query floor; the truth is between, and the bound
  is the finding.
* State explicitly what each result does NOT establish.
* Keep discarded estimators documented so they stay discarded — both the dead
  estimator and the one that replaced it belong in the record.
* List the assumptions unverifiable from data, and name who can verify them.

The bias rules behind these are in [GSC data fidelity](/guides/gsc-data-fidelity).

## See also

* [GSC data fidelity](/guides/gsc-data-fidelity) — the instrument watchouts
  behind every acquisition rule above
* [Analysis guardrails](/guides/analysis-guardrails) — the Phase 4 rule set
* [Prompts and resources](/guides/prompts-and-resources) — invoke this
  runbook as the `gsc-content-deep-dive` prompt
* [Search Console deep dive](/workflows#7-search-console-deep-dive) — the
  lighter-weight export recipe for routine questions
