Skip to main content
Compare a completed AI answer with the pages behind it. The result shows the searches the engine ran, the pages it retrieved and the ones it cited, the brands the answer names and the pages that name them, where your brand stands, and prioritized actions. It also maps the paragraphs of each cited page to the parts of the answer they correspond to, with an explanation for every link, and sums up what the cited pages have in common.
Poll GET /v1/async/task/:id, or supply webhook.url when submitting; the task reports taskType: "CITATION_ANALYSIS". Do not submit this analysis through POST /v1/async/task; use the dedicated endpoint. Earlier names, including GEO Audit’s, keep working: POST /v1/geo-audit, POST /v1/source-influence and POST /v1/research, the GEO_AUDIT, SOURCE_INFLUENCE and CITATION_ATTRIBUTION task types, and include.geoAudit and include.sourceInfluence; responses always use the new names.

Analyze a task you already ran

If the answer came from this API, send its task id. The analysis reads the answer and its citations from that task:
The task must be one of yours, COMPLETED, and still readable through GET /v1/async/task/:id. Its answer Markdown (text when the engine returned no Markdown) becomes answer, and its cited URLs become citations in the engine’s order: the first 100, with at most 10 discussion threads. Product and video card placeholders (googleusercontent.com links) and Google search links are skipped, since they have no page to read. The task’s prompt and country and its engine are used unless you send them. Sending taskId together with answer or citations is rejected with 400, and so is a task that is unfinished or has no answer text or cited URL. An unknown or expired task id returns 404.

Analyze every answer as you collect it

Add include.citationAnalysis: true to a collection request, and the analysis runs on the answer as soon as it is collected. It works with the answer engines (CHATGPT, GEMINI, PERPLEXITY, GOOGLE_AIO, GOOGLE_AIMODE, NAVER_AI_BRIEF, NAVER_AI_TAB, BING_SEARCH, BING_COPILOT), in single tasks, task batches, grids and POST /v1/batches.
The analysis reads the answer and its cited URLs the same way taskId does above. The answer’s result then carries response.citationAnalysis: the analysis task exactly as GET /v1/async/task/:id returns it, with task, credits and response or error.
  • Webhook: sent once, after the analysis finishes, with the answer and the analysis together.
  • Polling: the answer task is COMPLETED as soon as the answer is ready. Keep polling until response.citationAnalysis.task.status is COMPLETED or FAILED.
  • Batches complete when every answer and its analysis have finished.
  • No analysis: when the answer cites no URL to read, or your credits or the key’s daily limit cannot cover the analysis hold, response.citationAnalysis is { "error": "…" } and the answer is delivered right away.
  • Billing: the analysis is charged on its own, by usage like any Citation Analysis task. The answer’s charge does not change. A key limited to certain task types must also allow CITATION_ANALYSIS.

Payload

With taskId or include.citationAnalysis, these fields are filled from the answer’s raw data. For CHATGPT, the engine’s searches become queries and every page it retrieved becomes a citation with cited, position, citedText, publishedAt and query; the same URL with different tracking parameters is merged, and a page the answer links in its text or shows as a product card is cited. For Google AI Overview, the overview’s sources are cited and organic results outside them are non-cited, with position set to their organic rank. Other engines provide cited sources only.
The request rejects analysis with 400. Insights are included in every result.

Result

Results stored before v4 keep their earlier shape, without a version field.

version

Always 4 for this shape.

answer

The answer you submitted, unchanged. answerRanges are offsets into this exact string: JavaScript UTF-16 code units, start inclusive, end exclusive. Slice it as-is with answer.slice(start, end). Each links[] range identifies a whole semantic unit of your answer: a sentence, list item or table cell. Each brands[] range is the exact name as written. Boundaries refer to the original text.

queries[]

The searches the engine ran for this answer. Each has an id, its text, and sourceIds: the sources that search found. Empty when the engine exposed no searches and you sent none.

sources[]: one entry per page

  • id: opaque identifier, unique within the result.
  • url: the page URL; domain: its host.
  • channel: who controls the page, judged from its host:
    • own: your brand’s own site (exactly when own is true).
    • brand: the own site of another brand the result names, judged by its domain or by the answer linking it from that brand’s name.
    • editorial: a publisher; only the publisher can change the page. Hosts that are not recognized are reported as editorial.
    • retailer: an online store or marketplace.
    • review_platform: a customer or business review site.
    • community: a forum or Q&A site.
    • video: a video platform.
    • social: a social network.
    • blog_platform: a hosted blog service.
    • reference: an encyclopedia or wiki; never the target of an action.
  • cited: true when the answer cites the page, false when the engine only retrieved it.
  • position: the engine’s own rank for the page, or null when it gave none.
  • queryIds[]: the searches that found the page.
  • publishedAt: the publication date as the engine reported it, or null.
  • citedText[]: passages the engine itself reported citing; [] when none.
  • brandIds[]: brands named on the readable page, its title or citedText.
  • own: true when the page is on your brand’s own site.
  • paragraphs[]: the paragraphs of a cited page included in the result. Each has an id (globally unique across the whole result) and the text of the paragraph. A paragraph can be included with no link at all. Always empty for non-cited pages.
  • error: present only when the page could not be read. paragraphs is then empty, and the string is a short reason for that source.

brands[]

Every brand the result tracks: your brand (role: "target"), your competitors ("competitor"), and other brands the answer names ("answer").
  • rank: the order of the brand’s first name span in the answer, starting at 1; null when the answer does not name the brand.
  • answerRanges[]: the exact spans where the answer names the brand or one of its product names, in the same UTF-16 offsets, so answer.slice(start, end) returns the name as written. Matching ignores case and takes whole words (except in scripts written without spaces); it covers headings and table cells, never link URLs or image markup.
  • citedSourceIds[]: cited sources whose page names it.
  • retrievedSourceIds[]: non-cited sources whose page names it.
  • ownSourceIds[]: sources on the brand’s own site; filled for the target only.
  • paragraphId: the paragraph this link is about. It always points at a paragraph that exists in sources[].
  • answerRanges[]: the parts of the answer this paragraph corresponds to, as start/end pairs in the same UTF-16 offsets as above. A link can carry several ranges; the same answer text is not repeated across them. Each range is a whole answer unit (sentence, list item or table cell).
  • explanation: a short sentence describing the correspondence: what the paragraph states about that part of the answer.

visibility

Where your brand stands in this answer; null when no brand was sent.
  • brandId: your brand in brands[].
  • stage: one of:
    • mentioned: the answer names your brand.
    • on_cited_page: the answer does not name it, but a cited page does.
    • on_retrieved_page: only pages the engine retrieved without citing name it.
    • not_found: no page that was read names it.
  • rank: your brand’s rank in brands[].
  • answerBrands: how many brands the answer names.

actions[]

Prioritized next steps for your brand; [] when no brand was sent. priority starts at 1 (do first) and has no gaps. Actions are ordered by control: what your brand controls first (owned), then platforms it can post on (platform), then outreach (outreach). summary is one sentence and steps[] holds one to five concrete steps, both in the answer’s language. sourceIds, brandIds, queryIds and linkIds point at the evidence in this result. brandIds names your brand, or the rival brands those pages name. Third-party pages that the engine retrieved without citing and that name your brand are listed in brands[].retrievedSourceIds.

insights[]

Up to four short summaries of the result: which channels were cited, the format, freshness or criteria the cited pages share, how the answer’s brand order compares with what the cited pages cover, and where your brand sits. sourceIds names the pages and linkIds the links each summary rests on; at least one of them is non-empty, and they only name entries in this result. The steps to take are in actions[].

Reading the result

  • A paragraph without a link matched no part of this answer. An answer part with no range has no paragraph linked to it.
  • Unread pages are left out. When sources[].error is set, run the analysis again or send the page’s body to include that citation.
  • Retrieval data depends on the engine. Non-cited pages appear only when the engine exposes them (ChatGPT, Google AI Overview) or you send cited: false pages. Otherwise every source is cited, and your own page can only appear as cited.
  • Actions are ranked from the pages in this result. After you act on one, run the same prompt again and compare the answers.
  • Ids are internal. Do not persist s…/q…/b…/l…/a… identifiers as stable keys across runs; they are scoped to a single result.

Execution and limits

  • Input size. The analysis takes an answer up to 200,000 characters with up to 100 citations. Long answers, large source sets and very long pages are split into parts and analyzed.
  • Links follow the answer. The analysis links the passages that match each part of the answer, and every source with a match appears in the result. On a large page, or one that repeats the same statement in navigation, listings and reviews, it links the strongest passages.
  • Links come from page text. Sitemaps, link indexes and image galleries add no links, and a page made only of those is reported with no paragraphs.
  • A source that could not be read is reported in sources[].error without failing the task if another source is readable. The task fails when no source could be read, on an analysis failure, on a timeout, or on a service configuration error.
  • Requests are metered by usage, like the rest of the API. The submit response shows the temporary credit hold; the final charge is settled when the task reaches a terminal state.