Technical GEO

Schema markup for AI citations

JSON-LD does not make an assistant cite you. It makes your page cheap to parse — who wrote it, when, and what each section answers — which is what decides between you and an equally good page that left all of that implicit. The rules below are the ones the Citely audit actually applies, not a restatement of the schema.org spec.

The one rule most pages break

Schema whose content does not appear in the rendered HTML is discarded. This is why so much FAQ markup does nothing: the answers live in the JSON-LD, the page shows a different summary or nothing at all, and both Google and the AI crawlers drop the block. The schema validates. It is simply never used.

The structural fix is to make drift impossible — render the FAQ and generate the schema from the same array. This page does exactly that:

const faqs = [
  { question: 'Does schema markup affect whether AI cites me?', answer: '...' },
];

// One source. The schema cannot describe an answer the page does not show.
<JsonLd data={{ '@context': 'https://schema.org', '@graph': [ faqSchema(faqs) ] }} />
{faqs.map((f) => (
  <div key={f.question}>
    <h3>{f.question}</h3>
    <p>{f.answer}</p>
  </div>
))}

What the audit extracts

Every application/ld+json block is pulled from the HTML and parsed, and the @type values are collected recursively — into @graph and into arrays, so nested nodes count. A block that fails to parse contributes nothing and raises nothing. That silence is the failure mode: a trailing comma from two years ago is still costing points, and nothing on the page looks wrong.

One @graph, not four blocks

A single graph lets nodes reference each other by @id instead of restating your organization in every block, where the copies eventually disagree.

{
  "@context": "https://schema.org",
  "@graph": [
    { "@type": "Organization", "@id": "https://example.com/#org",
      "name": "Example", "url": "https://example.com" },
    { "@type": "Article",
      "headline": "...",
      "datePublished": "2026-09-06",
      "dateModified": "2026-09-06",
      "author": { "@type": "Person", "name": "A Real Name" },
      "publisher": { "@id": "https://example.com/#org" } },
    { "@type": "FAQPage", "mainEntity": [ /* answers also rendered on the page */ ] },
    { "@type": "BreadcrumbList", "itemListElement": [ /* ... */ ] }
  ]
}

The four authority signals

Authority is 20 of the 100-point GEO score, split into four equal checks. Three of them are schema properties you can add today.

A named author

A visible byline, or an author property in your JSON-LD. An assistant summarising a claim wants someone to attribute it to; a page authored by nobody is a page with nothing behind the claim.

A published or updated date

datePublished and dateModified. Recency is one of the few things an assistant can check cheaply, and an undated page is treated as being of unknown age — which in practice means old.

At least three outbound citations

Links to primary sources other than yourself. This is the signal most marketing pages fail, because linking out feels like leaking traffic. It is the cheapest authority point on the list.

Any valid JSON-LD at all

One parseable application/ld+json block with a @type. Not the right type, not a rich set — any. A surprising share of pages fail this on a trailing comma nobody ever saw, because the block fails silently.

Three things schema will not fix

  • A page a crawler cannot fetch. Perfect markup behind a Disallow: / is markup nobody reads. Access comes first — see robots.txt for AI crawlers.
  • A page with no answer in it. Marking up a page that never states a claim plainly just describes the absence more precisely. Structured data is a wrapper, not content.
  • Client-rendered JSON-LD. If it is not in view-source, it is not there. Emit it server-side.

Frequently asked questions

Does schema markup actually affect whether AI cites me?

Indirectly, and the mechanism matters. No assistant reads your JSON-LD and decides to cite you because of it. What JSON-LD does is make the page unambiguous to parse: who wrote it, when, what kind of thing it is, and what question each section answers. A retrieval system that can resolve those cheaply is more likely to pick your page out of a set of otherwise similar candidates. Schema is not a ranking lever, it is a legibility one.

Why is my FAQ schema being ignored?

Almost always because the answers exist only in the JSON-LD and not in the rendered HTML. Both Google and the AI crawlers discard FAQPage schema whose answer text cannot be found on the page — it is the single most common structured-data mistake we see, and it is invisible because the schema itself is perfectly valid. The fix is to render the FAQ from the same array that generates the schema, so the two cannot drift apart.

Which schema types should I use?

For a marketing or documentation page: Article (or TechArticle), FAQPage, BreadcrumbList, plus Organization and WebSite emitted once site-wide. For a product: Product with an offers node. For anything procedural: HowTo. Adding types beyond what the page genuinely is does not help — a pricing page marked up as an Article is a page that has told the parser something false about itself.

Should I use one @graph or several separate script blocks?

One @graph. It lets your nodes reference each other by @id — an Article whose publisher points at your Organization node, a breadcrumb whose last item is the page itself — instead of restating the same organization data three times in three blocks that will eventually disagree. Multiple blocks are parsed fine, but they rot independently.

How does the Citely audit score structured data?

It pulls every application/ld+json block from the HTML, parses each one, and recursively collects the @type values — walking into @graph and into arrays, so nested nodes count. A block that fails to parse contributes nothing and raises no error, which is exactly how broken schema stays broken for years. Those extracted types then feed both the structural criterion and the fourth authority check.

Does JSON-LD need to be server-rendered?

Yes, for this purpose. Schema injected by client-side JavaScript after hydration is invisible to any crawler that does not execute JavaScript, which includes most AI retrieval fetchers. If your JSON-LD only appears in the DOM inspector and not in view-source, it does not exist as far as citation is concerned.

Related reading