The AI Citation Observability Data Dictionary
AI-search reporting becomes difficult to audit when a dashboard stores only a prompt, a brand name, and a score. The missing context matters: which answer system was tested, which interface was used, whether the run was signed in, what locale was active, which exact URLs were cited, and what the answer actually claimed.
This field reference defines a compact event model for AEO and GEO observations. It is designed for teams that want to compare mentions, citations, and claim accuracy without pretending that a volatile answer is a permanent ranking. The schema can be implemented in a spreadsheet, warehouse, or application database. Teams exploring a dedicated workflow can also review Corank's AI-search visibility platform.
Start with the unit of observation
One row should represent one answer generated from one controlled prompt run. Do not combine several answer engines, reruns, or locales into the same row. A single row may contain multiple cited URLs because one answer can reference several sources.
That rule makes the dataset composable. A team can calculate prompt coverage, mention rate, citation rate, and accuracy by grouping observation rows, while a reviewer can still return to the exact answer-level evidence.
The event is not the prompt itself. A prompt is a versioned input. An observation is the result of running that input under stated conditions.
Core identity fields
| Field | Type | Required | Definition and validation rule |
|---|---|---|---|
observation_id |
string | yes | Immutable unique identifier for this answer event. Never reuse it after deleting or rerunning an observation. |
prompt_id |
string | yes | Stable identifier for the research question. It remains constant when wording changes. |
prompt_version |
integer | yes | Positive integer identifying the exact prompt wording and metadata version. Increment it when wording, market, stage, or intent changes materially. |
prompt_text_hash |
string | yes | Hash of normalized prompt text. It detects silent wording changes without duplicating the full prompt in every export. |
run_timestamp |
datetime | yes | UTC timestamp for the completed answer. Store timezone-aware values rather than local clock strings. |
rerun_parent_id |
string or null | no | observation_id of the earlier event this run intentionally repeats. Leave null for the first observation. |
The stable prompt_id and explicit prompt_version solve different problems. The ID connects a research question over time; the version prevents a changed prompt from being treated as the same benchmark.
Execution-context fields
| Field | Type | Required | Definition and validation rule |
|---|---|---|---|
answer_system |
controlled string | yes | Product or answer system tested. Use a controlled vocabulary and preserve the label seen by the analyst. |
model_label |
string or null | no | Model name displayed in the interface or API response. Do not infer a hidden model version. |
interface_surface |
controlled string | yes | Where the run occurred, such as web UI, mobile UI, API, search mode, or research mode. |
session_state |
controlled string | yes | signed_out, signed_in_clean, signed_in_personalized, or unknown. Do not collapse personalized and clean runs. |
locale |
string | yes | BCP 47 language-region tag such as en-US. Record the tested locale even when the answer language appears obvious. |
market |
string or null | no | Commercial or geographic market intentionally represented by the run. Use a controlled internal label. |
Context fields are not decoration. They define which observations can be compared. A signed-out US-English web result and a personalized UK mobile result may both be valid, but they should not be silently averaged as if they were the same measurement condition.
Outcome fields
| Field | Type | Required | Definition and validation rule |
|---|---|---|---|
brand_mentioned |
boolean | yes | True only when the target brand or an approved unambiguous alias appears in the answer. |
target_domain_cited |
boolean | yes | True only when at least one rendered citation resolves to the canonical target domain or an approved subdomain. |
cited_urls |
array of URLs | yes | Exact resolved citation destinations in answer order. Use an empty array when the answer has no citations. |
citation_roles |
array of strings | yes | Role aligned to each cited_urls item: primary evidence, independent corroboration, directory, commentary, or incidental reference. |
claim_status |
controlled string | yes | accurate, partly_accurate, unsupported, incorrect, not_applicable, or not_reviewed. |
claim_summary |
string | yes | Short factual summary of what the answer said about the target entity. Do not paste promotional interpretation here. |
evidence_artifact_uri |
URI | yes | Durable screenshot, transcript, or response artifact that allows another reviewer to inspect the answer. |
analyst_note |
string or null | no | Concise interpretation or anomaly note. It must not replace the captured evidence. |
Mention and citation are deliberately separate. An answer can mention a brand without citing its site, cite the site without recommending the brand, or cite another source that makes an inaccurate claim. Those states require different interventions.
Example observation event
The values below are illustrative, not a claim about a live answer system.
{
"observation_id": "obs_20260808_0042",
"prompt_id": "category_best_fit_07",
"prompt_version": 3,
"prompt_text_hash": "sha256:example-only",
"run_timestamp": "2026-08-08T16:25:00Z",
"rerun_parent_id": "obs_20260725_0031",
"answer_system": "example_answer_system",
"model_label": null,
"interface_surface": "web_ui",
"session_state": "signed_out",
"locale": "en-US",
"market": "United States",
"brand_mentioned": true,
"target_domain_cited": false,
"cited_urls": [
"https://example.org/category-guide"
],
"citation_roles": [
"independent_corroboration"
],
"claim_status": "partly_accurate",
"claim_summary": "The answer placed the target in the category but omitted a key scope limitation.",
"evidence_artifact_uri": "https://evidence.example/obs_20260808_0042",
"analyst_note": "Review the canonical scope statement before the next controlled rerun."
}
Five ingestion checks
Run these checks before an observation enters reporting tables.
- Identity uniqueness. Reject an
observation_idalready present in the dataset. - Version integrity. Confirm that
prompt_text_hashmatches the registered text forprompt_idandprompt_version. - Citation consistency. Require
target_domain_cited = trueonly when at least one resolved URL matches the target-domain rule. - Array alignment. Require
cited_urlsandcitation_rolesto contain the same number of items in the same order. - Evidence completeness. Reject a final-status record that lacks an inspectable
evidence_artifact_uri.
These checks catch data errors before they turn into attractive but misleading charts.
Metrics that preserve the evidence
For a defined observation set, calculate each outcome independently:
- Mention rate = observations with
brand_mentioned = truedivided by all eligible observations. - Target-domain citation rate = observations with
target_domain_cited = truedivided by all eligible observations. - Citation given mention = mentioned observations that cite the target domain divided by all mentioned observations.
- Reviewed claim accuracy = accurate reviewed observations divided by observations whose
claim_statusis notnot_reviewedornot_applicable. - Repeatable citation rate = benchmark prompts citing the target domain in at least the required share of controlled reruns divided by rerun-eligible prompts.
Every metric should ship with the observation count, benchmark version, date window, answer systems, locales, and session-state filters. A percentage without those boundaries is not reproducible.
Quality-control queries
The following questions make a useful review queue:
- Which observations have
target_domain_cited = truebut no target-domain URL incited_urls? - Which prompt versions have more than one registered text hash?
- Which cited URLs lack a corresponding source role?
- Which inaccurate claims have no evidence artifact?
- Which reruns changed both prompt version and execution context, making before-and-after attribution weak?
- Which prompt classes are represented by too few observations to support a trend statement?
The goal is not to delete inconvenient results. It is to label measurement conditions and gaps clearly enough that another analyst can reproduce the logic.
What this schema intentionally excludes
This data dictionary does not define a universal AI-visibility score. Weighting mentions, citations, sentiment, accuracy, and commercial intent into one number hides the reasons a result changed. Keep raw outcomes and transparent derived metrics available even when leadership receives a summary view.
It also excludes inferred traffic and revenue attribution. Those belong in a separate model connected by documented campaign, referral, landing-page, and conversion identifiers. An answer observation proves what appeared in an answer under stated conditions; it does not by itself prove that the answer caused a sale.
Implementation checklist
- Register prompts separately from observations.
- Version prompt text and research metadata together.
- Store timestamps in UTC and preserve tested locale and market.
- Resolve and normalize citation destinations without discarding the original URL.
- Keep mention, citation, recommendation, sentiment, and accuracy as separate fields.
- Require answer-level evidence for every reported observation.
- Document eligibility filters beside every metric.
- Preserve historical records when taxonomy rules change.
- Rerun controlled benchmarks before attributing movement to an intervention.
AEO and GEO reporting becomes more useful when every summary can be traced to a specific prompt, answer, citation, and artifact. Corank focuses on AI-search visibility and citation analysis; this open data dictionary provides a portable structure teams can use to keep that work inspectable.