The search universe
Your search universe is the set of seed terms your account tracks in the content planner. Each seed term represents a topical cluster, and each cluster contains queries — long-tail searches your ideal customers actually make, derived from real search evidence. The API and some tools call queries “questions”.content_planner_list_seed_terms
lists the seed terms in your universe; content_planner_list_questions lists
the queries (API: questions) under one seed term.
The tracked universe is the campaign and standard tiers — the scope every
reporting_* figure uses, and the planner’s default. Backlog terms sit outside
it. See
campaigns, standard, backlog, and archived.
Citations and brand mentions
Two atomic units measure performance:- Citation — a URL used as a source. Google has two kinds: AI Overview citations (a URL used as a source in the AI Overview) and organic citations (the traditional blue-link ranking). ChatGPT citations are URLs used as sources in ChatGPT responses.
- Brand mention — your brand is named in a Google AI Overview or a ChatGPT response.
Pass a mode as the
mode parameter on the content planner tools.
Which tools cover which channel
Do not mix channels when reading figures. Each tool family covers one side:- All
reporting_*tools return Google data only — traditional organic rankings and Google AI Overview citations/mentions. “AI” anywhere in reporting output means Google AI Overview, never ChatGPT. The account overview payload says so explicitly:sourceChannel: "google". - ChatGPT data comes from the content planner — pass
mode: "chatgpt-ranking"(citations) ormode: "chatgpt-mentions"(brand mentions) tocontent_planner_list_seed_termsorcontent_planner_list_questions. Per-query ChatGPT responses are available viasearch_intelligence_get_serpwithtype: "chatgpt". - The content planner returns an aggregate view per mode — every planner
response includes
domainCounts(the most-cited domains) andbrandCounts(the most-mentioned brands) computed for the selected mode, over exactly the seed terms that call returned. Both are a top-50 list, and eachcountis the number of queries where that domain or brand appears — at most once per query — not a citation total. This makes the ChatGPT competitive mix answerable in one call:content_planner_list_seed_termswith achatgpt-*mode, parallel toreporting_get_top_entitiesfor Google. Read both lists with reading counts and ranks correctly. - The
gsc_*tools are a different lens entirely — actual Google Search Console performance (clicks, impressions, CTR, position) for your site, not citation tracking. See Search Console performance and the AGA split.
Aggregate metrics
At the account level, reporting tracks how many searches you monitor, how many of them you rank for or get mentioned in, the resulting rate, and average positions — on Google (organic + AI Overviews). Aggregate views also show the most-cited domains and most-mentioned brands across your universe —reporting_get_top_entities returns these (mode: "ranking" for domains,
mode: "mention" for brands), and reporting_get_account_overview bundles
them into a one-call briefing. For the ChatGPT competitive mix, use
content_planner_list_seed_terms with a chatgpt-* mode — its domainCounts
and brandCounts give the same kind of aggregate for ChatGPT.
Every one of these figures covers campaign + standard seed terms only — see
campaigns, standard, backlog, and archived.
Reading counts and ranks correctly
The entity lists are shaped for reference, not for ranking off array position. Read them like this:- The list is a top 10 plus a pinned reference row.
reporting_get_top_entities(entities) andreporting_get_account_overview(topCitedDomains,topMentionedBrands) return the top 10 by count, plus your own domain or brand appended as a pinned reference row when it falls outside that top 10. Array position is not a rank, and list length is not a count of competitors. Readrank(1-indexed,nullon a pinned row) andisPinnedReference. Report a pinned row as outside the top 10 with its exact rank not returned — never as 11th, and never as last place. - A pinned row with
count: 0means not cited or not mentioned at all. Say that, rather than reading it as a low rank. - The two overview lists have separate denominators. Every
percentintopCitedDomainsis againsttopCitedDomainsTotal(queries with Google search results analyzed); everypercentintopMentionedBrandsis againsttopMentionedBrandsTotal(queries whose Google AI Overview named a brand). Quote each count or share against its own total. Never read a mention figure againsttopCitedDomainsTotalor againstuniverse.totalQuestions. Onreporting_get_top_entities, the singletotalfield carries whichever denominator the requestedmodeselected. - The planner’s
domainCountsandbrandCountscount differently. They are a top-50 list, and eachcountis the number of queries where that domain or brand appears — at most once per query — not a citation total. Neither list pins an own-entity row or carries anisOwnflag, so your own domain or brand is not necessarily present in them. - Query rows carry no lifecycle tier. Tier is a seed-term property — read
it from the parent seed term on
content_planner_list_seed_terms.
Campaigns, standard, backlog, and archived
Every seed term sits in one of four lifecycle tiers:
Your tracked universe is campaign + standard. A backlog term is in
consideration only — it has no generated queries and no SERP data — so it is
excluded from every
reporting_* figure and from the content planner’s
default scope. Never count backlog terms in a tracked-universe figure without
saying so.
content_planner_list_seed_terms returns campaign + standard terms when you
omit priorityTier, and echoes the applied scope as tierScope. Pass
priorityTier: ["backlog"] to inspect backlog terms, and label that read as a
backlog read.
On reporting_get_top_entities and reporting_get_account_overview,
campaign: false (the default) does not mean “every seed term”: the universe
is always campaign + standard. campaign: true narrows it to campaign-tier
terms only. Backlog is excluded either way, and the same campaign + standard
scope applies to reporting_get_trend, reporting_get_wins, and
reporting_get_urls. Because the planner default matches, a universe size from
the reporting tools reconciles with a planner count taken at that default
scope.
Archived is a separate toggle, not a tier filter. showArchived: true returns
the archived rows instead of the active ones, never both. Both planner tools
echo which set came back as archivedOnly.
Publishing density
Where more content is published against queries, your account gets cited more. Low-density seed terms naturally have lower ranking and mention rates — a weak rate on a term with little published content is a coverage gap, not necessarily a performance problem. CheckpublishedCount per seed term in
content_planner_list_seed_terms before judging a term’s rates.
Competitor views
You can view the same universe from a competitor’s perspective:- Pass a competitor domain as
referenceUrlon the content planner tools to see which queries that domain ranks for. - Pass a competitor brand name as
referenceBrandto see which queries that brand gets mentioned for.
reporting_get_urls, use the search filter (substring on the host) or
host filter (exact host, url view only) to drill into a competitor’s
citations across your universe.
Search Console performance and the AGA split
Thegsc_* tools read your site’s actual organic performance from
Google Search Console — clicks, impressions, CTR, and average position —
rather than tracking citations in AI answers. This is the ground truth of what
the content does once published.
Prerequisite: these tools work only when [email protected] is added to
your Google Search Console property with Full access (Search Console →
Settings → Users and permissions). The tools read through that shared
service account; without access they can’t resolve your property.
Three things shape how the numbers are assembled:
- Property resolution. Your account’s publishing URL (the reverse-proxy
rewrite when set, otherwise the CMS URL) is matched against the GSC
properties the service account can see. A domain property
(
sc-domain:example.com) covers the whole site including subdomains. When an account only has URL-prefix properties, AGA content may live on a separate property from the main site — for exampleresources.example.comtracked apart fromexample.com. Neither property alone is the true picture, so the aggregate tools query every same-domain property and merge the results; aperPropertybreakdown in every response shows the composition. Accounts still on the shared placeholder space (*.sites.aigrowthagent.co— a test space for accounts not fully set up, not an official domain) are never matched to a GSC property — never theaigrowthagent.coproperty, which belongs to AI Growth Agent — and the performance tools refuse to pull until the real domain is set. - The AGA split. Aggregate tools separate performance into AGA content vs the main domain — what share of clicks, impressions, and growth comes from AI Growth Agent slugs — by matching GSC page URLs against your published articles’ exact slugs and publishing base. Exact slug matches, not subdirectory prefixes: a subdirectory can mix AGA and non-AGA content, so a prefix match would misstate the split. Each split reports its strategy and confidence; when an account can’t be segmented confidently, the tools say so instead of estimating.
- Recency lag. GSC finalizes data with a delay, so default date ranges end
about 3 days ago and the most recent days are always incomplete. Every
performance response lists the affected dates in
meta.incompleteDays— only dates inside the real lag window (today−3 … today at call time) are flagged, so historical pulls carry no flags. Never trend on flagged days.
gsc_export_dataset —
the response includes a pre-signed downloadUrl for the raw file (curl it
immediately; the signature expires in ~1 hour and the file lives on the MCP
server) — and slice it with gsc_query_export. Compact summaries are the
default everywhere else. Before trusting query-level numbers, read
GSC data fidelity — Google withholds rare
queries, so named queries are a biased floor; query-frame responses carry a
queryBiasNote saying so.
Evaluating AGA content performance
The standard reading path, and the stance behind it:- Impressions come first. AI traffic doesn’t click, so impressions are the primary signal of how visible your content is to AI. Clicks and CTR describe human traffic only — report them as such, and never present a click decline as an AI-visibility decline. When the AGA split is available, lead with the AGA impression share.
- Aggregate, then split. Start with the site-wide property-frame trend
(
gsc_get_overview), then read the AGA-vs-main-domain split: what percent of total impressions AGA content drives, and how the two populations move separately. The overview’s AGA share divides AGA’s page-filtered impressions by the property total, and main is the property total minus AGA. It matches the GSC UI (page filter on the publish path ÷ unfiltered total), so report it as measured.gsc_query_analyticsandgsc_export_datasetsplits stay same-frame (AGA ÷ the classified page rows). - Cadence follows account maturity. The
maturityblock ongsc_get_contextreports how long the account has been publishing. In the first ~8 weeks, read week-over-week (gsc_compare_periodswithperiodPreset: "wow") to see which pages are picking up. After that, read month-over-month and 3-month-over-3-month ("mom"/"qoq"). Never read a mature account week-over-week. - Indexing coverage for new accounts. What percent of published slugs
have any impressions? Join
articles_search(statuses["published"]) against a["page"]-dimension pull or export on the slug. Pages published or updated long ago with persistent zero impressions are retire candidates — retiring them can help the domain over time. Diagnose suspects withgsc_inspect_urlandgsc_list_sitemaps. - Web Stories are a separate format. AGA ships a Web Story twin per
article under a
/web-stories/path, so the same slug appears twice in GSC.tags.isWebStorysplits them — analyze Web Story URLs separately from article URLs. - Split the AI and human stories. Use
tags.queryShapeto tell which queries and pages win human vs AI-shaped traffic. Alongside the impressions-first principle, this is the AI-visibility narrative. - An article’s impact is not confined to its target query. One article can rank or be cited across many queries — its blast radius. The planner prioritizes queries where the account is not yet ranking or mentioned, so a query the account is winning may have no dedicated article; trace the ranking or cited URL and it is usually an AGA article published against a different query. Highlight articles with disproportionate cross-query impact as wins — they are the corpus’s workhorses, and the top candidates to refresh and to replicate the pattern from.
Reading Search Console data correctly
GSC numbers depend on how they were grouped and retrieved. Every performance response carries ameta block stating the assumptions behind its numbers —
read it before quoting a figure.
- Aggregation frames never reconcile.
meta.aggregationFramelabels the frame:property(date/device/country groupings without a page filter — the true site total),page(above the property total — GSC counts one page impression per URL shown, so a search surfacing three of your URLs counts three times; only a little above when searches show one of your URLs, far above with sitelinks and brand results, more than 80% on one measured account),query(named queries only — anonymized queries are excluded), orpage_query. The same question answered in two frames gives two different numbers; neither is wrong. Pick one frame per analysis and name it. - The page-filter trap. A page filter combined with device, country, query,
or any other page-less grouping silently drops to the named-query table,
losing roughly half the impressions. The response is labelled
query, soqueryBiasNotefires.["page"]or["date"]alone plus a page filter stays page-level (["date"]is the GSC UI chart with a page filter) and is labelledpage. - URL matching is exact — inspect the canonical form. The URL Inspection
API and the GSC page filter match exact URL strings. The wrong slash variant
answers “Page with redirect” or “URL is unknown to Google” for a page that
is actually indexed and ranking — and the same wrong-URL cause produces
different-looking verdicts. There is no universal slash rule: WordPress
canonicalizes to a trailing slash, Next.js and Framer away from it. Match
the site’s canonical form. The tools do this for you: slug-resolved URLs are
built in canonical form,
gsc_inspect_urlre-inspects thegoogleCanonicalURL (or the toggled slash variant when Google reports none) on a non-PASS verdict and records what happened incanonicalNote, andgsc_get_page_performanceretries the toggled variant when a page returns zero rows. - Completeness is measured, not assumed. The API caps each request at
25,000 rows, returned clicks-first — so a capped pull keeps clicks intact
but discards the zero-click impression tail. The tools auto-partition capped
pulls (by device, then by page-regex) and reconcile the union against an
uncapped denominator pulled with the same filters. Check
meta.completeandmeta.coverageRatio(union ÷ denominator) before any impression-based analysis; click-based analysis survives capping.meta.partitionsUsedshows what was split, andcoverageNotewarns when coverage falls short. - Query data is never the whole story. Named queries cover roughly
52–65% of impressions; the rest are anonymized by Google. On measured
properties the anonymized residual converts better than named queries.
On
["page", "query"]pulls,meta.anonymizationreports named vs anonymized impressions, clicks, and CTR so the hidden share is visible. - Row tags pre-classify the data. Query rows carry
tags.queryCharsandtags.queryShape(humanunder 30 chars,ambiguous30–59,ai_shaped60 and over — a behavioural inference from length, since GSC exposes no AI Overview flag; the fixed threshold deliberately under-counts AI-shaped traffic rather than misclassifying human queries). Page rows carrytags.hostnameandtags.pageClass:canonical(your publish base),cms_origin(the CMS host indexed alongside the reverse proxy — a duplicate-content split),tenant_subdomain(other customers’*.sites.*sites inside a domain property — exclude these),main_site(a different, brand-query-driven population), orother. Page rows also carrytags.isWebStory, marking Web Story twins of articles — split them off before judging article performance. - CTR and position are derived.
ctris a fraction (0.0028 = 0.28%);positionis 1-indexed and impression-weighted within a row. Re-weight position by impressions after any aggregation — never average positions. - Pass
accountIdexplicitly. The session’s current account is an in-memory override that can reset silently. compare_periodstotals are exact; movers follow your dimensions. PassperiodPreset(wow/mom/qoq) or explicit dates. Period totals, deltas, and growth-share denominators come from an extra["date"]-grouped pull per period, so they match the GSC UI on any account size. Movers and segments are in the requested dimensions’ frame (meta.aggregationFrame). Each growth share is the page-filtered AGA delta ÷ the unfiltered property delta — the same numbers the GSC UI shows. Shares can be negative or exceed 1.
Reading trends
Always read rate changes against universe size. When you add new seed terms or queries, the denominator grows and the rate naturally dips — that is expansion, not decline. Trends answer whether growth or decline is happening on a stable universe base.reporting_get_trend carries what you need to tell the difference: compare
totalQuestions per snapshot and the comparison.universe change against the
rate movement before concluding anything about performance. The trend is
Google-only; for ChatGPT movement, compare content planner chatgpt-* mode
results over time.
Where to go next
- Available MCP tools — every tool, parameter, and return value
- Common workflows — multi-step recipes that put these concepts to work
- Guides — prompts and resources, the first-analysis runbook, and the GSC data-fidelity and analysis-guardrails rule sets
- How is my content performing in Google search? — a worked example of the Search Console tools