Why one graph instead of scattered blocks?

Many sites emit JSON-LD as multiple disconnected script tags: a breadcrumb block from the SEO plugin, an Article block from the theme, an Organization block hard-coded years ago. Each block is valid alone, but together they describe fragments with no declared relationships — three silent strangers instead of one family. A single @graph with @id references states the relationships explicitly: this Article was written by this Person, published by this Organization, sold as this Product. For AI grounding — the pipeline stage that cross-checks facts — connected markup is corroborating markup. Disconnected duplicates can even look like conflicting claims.

What does the one-graph pattern look like?

Skeleton for an article page:

{"@context":"https://schema.org","@graph":[
  {"@type":"Organization","@id":"https://example.com/#org","name":"Example Co","url":"https://example.com/","logo":"https://example.com/logo.png","sameAs":["https://www.wikidata.org/wiki/Q12345"]},
  {"@type":"WebSite","@id":"https://example.com/#site","url":"https://example.com/","publisher":{"@id":"https://example.com/#org"}},
  {"@type":"Person","@id":"https://example.com/#author-jdoe","name":"J. Doe","jobTitle":"Analyst","worksFor":{"@id":"https://example.com/#org"}},
  {"@type":"Article","@id":"https://example.com/post#article","headline":"...","datePublished":"2026-11-04","dateModified":"2026-11-06","author":{"@id":"https://example.com/#author-jdoe"},"publisher":{"@id":"https://example.com/#org"},"isPartOf":{"@id":"https://example.com/#site"}}
]}

The same pattern extends to commerce: add a Product node with @id, brand referencing the org, and offers nested inside — see Product schema.

What are the @id conventions?

  • Use stable, URL-based identifiers: https://example.com/#org for the organization, #site for the website, page URL plus #article for articles.
  • Re-use the same @id for the same entity on every page — that is what lets parsers merge mentions into one node.
  • Reference, do not repeat: once the Organization node exists in the graph, other nodes point to it with {"@id":"...#org"} rather than duplicating its fields.
  • Cross-reference real-world identifiers with sameAs (Wikidata, official profiles) so the graph ties into external knowledge graphs — see entity linking.

Implementation checklist

  • Consolidate all JSON-LD output into one template-generated script block per page.
  • Define your canonical entity IDs once (org, site, each author) and reuse them site-wide.
  • Nest page-specific nodes (Article, Product, FAQPage) into the same graph and connect them by reference.
  • Validate with the Rich Results Test and Schema.org validator on every template type.
  • Serve the block in the initial HTML, not via tag manager — non-rendering AI crawlers must see it; see JavaScript rendering and AI.

Common pitfalls

First, duplicate entity definitions with slightly different fields — two Organization blocks where one says ‘Example Co’ and the other ‘Example Company Ltd’ — which reads as two entities to a parser. Second, broken references: an @id that nothing defines, or an author @id that changes per article, preventing author-entity consolidation (see author entities). Third, plugin conflicts where an SEO plugin and a schema plugin each emit their own partial graphs; pick one source. Fourth, nesting everything blindly — a graph can be one flat array of nodes connected by references; deep physical nesting is optional, correct referencing is not. For type-by-type details, start with Organization schema.

How do you migrate from scattered blocks to one graph?

  1. Inventory. Crawl a sample of every template and list all JSON-LD blocks, their types and their sources (theme, plugin, custom code).
  2. Design the target graph. Define canonical @id values for the organization, website and each author; decide which nodes each template emits.
  3. Centralize generation. Move JSON-LD output into one template function and disable competing plugin output — two plugins emitting rival Organization nodes is the most common pre-migration state.
  4. Roll out by template. Articles first (highest citation value), then products or locations, then the rest.
  5. Validate and monitor. Rich Results Test per template, then watch Search Console enhancement reports for error spikes after launch.

Expect one surprise: consolidation effects are gradual. Knowledge panels and AI brand answers reflect the cleaner graph over weeks as engines re-crawl and re-reconcile — measure with the monthly prompt set in measuring AI visibility rather than expecting day-one movement.

Where to go next

Apply the pattern to Article and Author schema, Product schema and LocalBusiness schema.

Frequently asked questions

Is @graph required, or can I nest objects directly?
Both are valid JSON-LD. Nesting objects directly works for simple pages, but the @graph plus @id pattern scales better, avoids duplicate entity definitions, and mirrors how knowledge graphs merge data.
Do AI engines require the @id pattern?
No engine requires it, but connected markup is easier to parse unambiguously and aligns with the entity-centric grounding AI pipelines perform. It is best practice, not a mandate.
How do I keep @id values stable across a redesign?
Anchor them to permanent URLs (your domain plus fragments like #org) rather than page paths or database IDs, and centralize generation in one template so URLs changing does not change entity IDs.