Nesting Balisage de données structurées (@id and @graph)

The deep-dive on connecting JSON-LD entities with @id and @graph — stable identifiers, the two canonical node patterns (WebSite→Article→Author, Product→Offer→Organization), the three mistakes que break the graph, and the honest limites of ce que Google's docs confirmer.

Première publication : 2 juil. 2026 · Dernière mise à jour : 3 août 2026 · Advanced
Langues

Nesting connects votre JSON-LD entities au lieu de dumping les as disconnected blocks. @id is a stable, unique URI (usually une URL canonique plus a #fragment) que noms an entity so autre entities peut référence it — an Article's author pointing at a Person node, a Product's Offer pointing at an Organization/seller — plutôt que re-declaring the complet entity everywhere. @graph is a keyword que bundles ceux connected entities into un script block. Google's docs confirmer les deux nesting and individual items fonctionner, and que @id is how vous tell Google two items are lié, but ils jamais confirmer si @id resolves à travers pages — so the safe par défaut is consistent @id valeurs plus the complet entity graph on every page que nécessite it. Two patterns to apprendre: WebSite → WebPage → Article → Author pour publishing, Product → Offer → Organization pour ecommerce. Three façons it breaks or costs vous: inconsistent/non-unique @id valeurs, orphaned références (an @id cited but jamais declared — a semantic gap, pas invalid JSON-LD), and duplicating a complet entity's declaration everywhere au lieu de referencing it (a maintenance trap; same-entity repeats merge plutôt que literally break, but a genuinely conflicting reused @id is a réel break). It's an entity-understanding outil, pas a ranking or rich-result lever by itself.

TL;DR — Nesting connects JSON-LD entities via @id (a stable, unique URI — usually une URL canonique plus a #fragment) so vous référence an entity au lieu de re-declaring it, and @graph (a keyword bundling connected entities into un script block). Google’s docs confirmer les deux nesting and individual items fonctionner, and que vous utiliser @id to lien connexe items — but ils jamais confirmer si @id resolves à travers pages, so the safe par défaut is consistent @id valeurs plus the complet entity graph on every page que nécessite it. Apprendre two patterns: WebSite → WebPage → Article → Author (publishing) and Product → Offer → Organization/seller (ecommerce). Three échec modes to watch pour: inconsistent/non-unique @id valeurs, orphaned références (an @id cited but jamais declared — semantically incomplete, pas invalid JSON-LD), and duplicate complet declarations of the même entity (a maintenance trap; same-entity repeats merge sous JSON-LD’s node rules, but reusing un @id pour genuinely différent entities is a réel conflict). It’s an entity-understanding outil — disambiguation and de-duplication — pas a ranking or rich-result lever by itself.

Evidence for this claim JSON-LD supports connected nodes via nesting or @id references, allowing multiple related entities to form one graph. Scope: JSON-LD graph model. Confidence: high · Verified: W3C JSON-LD 1.1 Evidence for this claim Google requires structured data to represent visible page content and follow each feature's specific nesting and property guidelines; extra valid nodes do not create eligibility by themselves. Scope: Current Google structured-data general guidelines. Confidence: high · Verified: Google Search Central: Structured data general guidelines

Scope: ce is the deep-dive, pas the intro

Ce article assumes vous déjà know ce que JSON-LD is and pourquoi it’s the recommended format — the balisage de données structurées page covers que, and it introduces @id/@graph En un coup d’œil. Ce page is the deferred deep-dive: the réel mechanics, the standard node patterns, and the spécifique mistakes que quietly break the graph. Si vous vouloir the format basics or où to placer the <script> block, JSON-LD is the sibling pour que.

@id — a stable identifier, pas a fetchable URL

@id assigns a unique URI to a JSON-LD entity so autre entities peut point at it by référence. The convention — consistent à travers every credible source I’ve vérifié — is an absolute URL canonique plus a descriptive fragment:

"@id": "https://example.com/#organization"
"@id": "https://example.com/#website"
"@id": "https://example.com/team/jane-doe/#person"

Two choses personnes obtenir incorrect ici:

  • It doesn’t have to resolve. Per the JSON-LD spec, @id’s job is node identification — a unique, stable “name” pour an entity — pas fetchability. En utilisant a fragment on votre propre domain is standard pratique and doesn’t exiger que fragment URL to independently charger as une page. Sitebulb’s node-identifiers guide frames it bien: a node identifier is “a unique ‘nom’ pour an entity, qui is publicly accessible and peut be looked up or lié to.”
  • @id n’est pas url. They’re différent properties doing différent jobs. @id identifies the node in the graph; url describes a réel, fetchable page à propos de the entity. An Organization peut (and souvent devrait) have les deux — an @id of https://example.com/#organization and a url of https://example.com/.

And @id valeurs are case-sensitive#Organization and #organization are two différent entities. Pick a convention and jamais drift from it.

@graph — bundling connected entities into un block

@graph is a JSON-LD keyword que lets vous put multiple top-level entities into un array à l’intérieur a unique <script type="application/ld+json"> block, with entities cross-referencing chaque autre by @id:

{
  "@context": "https://schema.org",
  "@graph": [
    { "@type": "Organization", "@id": "https://example.com/#organization", "...": "..." },
    { "@type": "WebSite", "@id": "https://example.com/#website", "...": "..." },
    { "@type": "WebPage", "@id": "https://example.com/post/#webpage", "...": "..." }
  ]
}

@graph is a container, pas a requirement. Vous pouvez absolutely utiliser separate <script> blocks pour individual items — Google’s docs confirmer les deux approaches fonctionner. The raison to reach pour @graph is maintainability: une fois vous have three or plus cross-referencing entities, vous écrire @context une fois at the top au lieu de repeating it in every block, and everything que références everything sinon lives in un placer. Ce is the pattern Yoast uses in production — its schema architecture docs expliquer que a shared graph lets les “éviter having to duplicate or repeat shared properties, and to reduce the amount of code/processing/overhead requis.”

Pourquoi nest at tout — and ce que Google en réalité dit

Declare each entity once and connect the graph with stable `@id` references instead of repeating full blocks.

One Organization identified as hash organization is referenced as publisher by the WebSite and Article. The WebPage belongs to the WebSite and is connected to the Article. Each entity is declared once, and the same stable at-id string is reused for every reference.

Google documents two structural options and confirms it understands les deux. From the General Données structurées Guidelines: “Recherche Google understands multiple items on une page, si vous nest the items or specify chaque item individually.” It defines them plainly — nesting is “quand là is un principal item, and additional items are grouped sous the principal item”, and individual items is “when each item is a separate block on the same page.”

The un paragraph that’s the closest chose to an official rationale pour @id is ce: “Si là are items que are plus utile quand ils are lié ensemble (pour exemple, a recipe and a video), utiliser @id in les deux the recipe and the video items to specify que the video is à propos de the recipe on lune page. Si vous didn’t lien the items ensemble, Recherche Google may pas know que it peut montrer the video as a Recipe rich result.” That’s the mechanism in Google’s propre words — @id is how vous tell Google two items belong ensemble.

Worth an honest remarque: Google’s docs state ce principle in prose but don’t ship a worked @graph+@id code sample demonstrating it — leur code exemples montrer a nested Recipe and two individual top-level items, neither of qui en réalité cross-references by @id. The exemples ci-dessous fill que gap.

Ce connects directement to schema’s two jobs (the framing from the balisage de données structurées page): nesting bien is squarely an entity-understanding déplacer — disambiguation and avoiding contradictory/duplicated données — pas a rich-result trigger on its propre. Linking votre Article cleanly to its Author doesn’t unlock a nouveau SERP fonctionnalité; it simplement rend the relationships unambiguous.

Pattern 1 — WebSite → WebPage → Article → Author

The canonical publishing pattern. Un Organization (the publisher), un WebSite, alors per-page a WebPage and the Article on it, with author and publisher resolved by @id au lieu de re-declared:

{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "Organization",
      "@id": "https://example.com/#organization",
      "name": "Example Media",
      "url": "https://example.com/",
      "logo": "https://example.com/logo.png",
      "sameAs": [
        "https://www.linkedin.com/company/example-media/",
        "https://en.wikipedia.org/wiki/Example_Media"
      ]
    },
    {
      "@type": "WebSite",
      "@id": "https://example.com/#website",
      "url": "https://example.com/",
      "name": "Example Media",
      "publisher": { "@id": "https://example.com/#organization" }
    },
    {
      "@type": "WebPage",
      "@id": "https://example.com/nesting-schema/#webpage",
      "url": "https://example.com/nesting-schema/",
      "name": "Nesting Schema Markup",
      "isPartOf": { "@id": "https://example.com/#website" }
    },
    {
      "@type": "Person",
      "@id": "https://example.com/team/jane-doe/#person",
      "name": "Jane Doe",
      "url": "https://example.com/team/jane-doe/",
      "sameAs": ["https://www.linkedin.com/in/jane-doe/"]
    },
    {
      "@type": "Article",
      "@id": "https://example.com/nesting-schema/#article",
      "mainEntityOfPage": { "@id": "https://example.com/nesting-schema/#webpage" },
      "headline": "Nesting Schema Markup",
      "author": { "@id": "https://example.com/team/jane-doe/#person" },
      "publisher": { "@id": "https://example.com/#organization" }
    }
  ]
}

Remarque what’s happening: author and publisher are one-line références. The Person and Organization are declared une fois chaque. The Article hangs off the WebPage (mainEntityOfPage), qui is isPartOf the WebSite, qui is publisher-ed by the Organization. That’s a connected graph, pas five islands.

Pattern 2 — Product → Offer → Organization (seller)

The ecommerce equivalent, and où nesting earns its garder at scale: au lieu de re-declaring votre merchant Organization on every un of thousands of product pages, declare it une fois and référence it as the seller:

{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "Organization",
      "@id": "https://shop.example.com/#organization",
      "name": "Example Shop",
      "url": "https://shop.example.com/",
      "logo": "https://shop.example.com/logo.png"
    },
    {
      "@type": "Product",
      "@id": "https://shop.example.com/widget/#product",
      "name": "Deluxe Widget",
      "sku": "WIDGET-001",
      "brand": { "@type": "Brand", "name": "Example" },
      "offers": {
        "@type": "Offer",
        "price": "29.99",
        "priceCurrency": "USD",
        "availability": "https://schema.org/InStock",
        "seller": { "@id": "https://shop.example.com/#organization" }
      }
    }
  ]
}

The Offer’s seller points at the shared Organization node. Même seller entity, un declaration, referenced from every product. (Pour very grand variant sets, the même shared-@id idea extends to a ProductGroup with variant Products — that’s a specialization of ce pattern, pas a différent mechanism.)

The three mistakes que break the graph

Ce is the practical heart of an audit. Quand nesting “doesn’t work,” it’s almost toujours un of ces three.

1. Inconsistent or non-unique @id valeurs

The même entity donné différent @id strings à travers pages (or à travers a replatform/migration), so moteur de recherches and validators voir les as unrelated entities au lieu de un. Or the opposite — reusing un @id pour two genuinely différent entities. The fix is a strict, documented convention (e.g. {base-url}/#organization, {page-url}/#webpage, {profile-url}/#person) applied mechanically. Cas counts; #author#Author.

2. Orphaned références

An @id is referenced but jamais declared. Vous écrire "author": {"@id": "https://example.com/#person-jane"}, but aucun node anywhere in the testé document en réalité declares que @id with a @type and properties. Worth being precise ici: a bare {"@id": "..."} object — ce que the JSON-LD spec calls a node référence (“a node object utilisé to référence a node having seulement the @id clé”) — is valid JSON-LD syntax on its propre; it isn’t a parse error. The problem is semantic and consumer-specific: the intended connection — “this Article’s author is that Person” — jamais resolves to anything utile, so quelconque fonctionnalité or reader que nécessaire the author’s réel nom, URL, or sameAs données comes up vide. Ce is the sneaky un: validators souvent encore parse chaque declared item sans erroring, so nothing screams at vous. Vous ship an incomplete graph and jamais notice. Momentic’s @id guide catalogs ce as un of the la plupart courant real-world nesting échecs.

3. Duplicate complet declarations of the même entity

The opposite of orphaning: re-declaring the complet Organization/Person object inline on every page au lieu de referencing it une fois. Two différent choses peut se produire ici, and it’s worth telling les apart:

  • Repeated declarations of the genuinely même entity. Per the JSON-LD spec, “the properties of a node in a graph may be spread among différent node objects dans a document. Quand que se produit, the keys of the différent node objects besoin to be merged to créer the properties of le résultating node.” So repeating the même @id with the même (or compatible) données isn’t a parse échec — processors merge it. Que doesn’t faire it a bon idea: it’s encore ce que nesting exists to prevent, and it bloats markup and creates a maintenance trap — mettre à jour votre adresse or logo in un template, forget the autre forty, and the entity now contradicts itself à travers le site. Les deux Ahrefs’ schema coverage and Schema App independently faire the même “modifier un and forget the others” point.
  • The même @id reused pour two en réalité différent entities. Ce is the réel break: two node objects share an identifier but décrire conflicting choses (a différent nom, a différent logo, a différent @type). That’s a semantic conflict, pas a harmless merge — pick a distinct @id pour chaque genuinely separate entity.

Declare une fois, référence everywhere — the maintenance cas pour doing so holds soit façon, même though a same-entity repeat won’t technically break the graph the façon an orphaned référence or a genuinely conflicting @id va.

The unresolved question: fait @id resolve à travers pages?

Here’s the honest limite que separates a réel réponse from the confident-but-wrong version. Google’s documentation jamais explicitly states si @id références resolve à travers pages — e.g., a product page’s Offer.seller pointing at an Organization node that’s declared seulement on the homepage. Aucun Recherche Google Central document uses “cross-page” or “across pages” in relation to @id.

The un nearby signal points toward self-contained pages: Google recommends, pour contenu dupliqué, “placing the même données structurées on tout page duplicates, pas simplement on the canonical page” — qui implies données structurées is evaluated par page, pas récupéré from elsewhere. And there’s aucun on-the-record statement from a named Google or Bing rep (Mueller, Illyes, Splitt) specifically resolving the cross-page @id question que I pourrait vérifier. Bing, pour its partie, has JSON-LD validation in Webmaster Outils but aucun publié @id/@graph-spécifique guidance at tout — a genuine documentation gap, pas a position I’m going to invent pour les.

So, as of July 2026, treat “Google follows @id links across pages” as an industry inference, pas a confirmed behavior. The safe par défaut — qui Yoast, Momentic, and Schema App tout converge on independently — is: garder @id valeurs consistent pour the même entity everywhere, but encore output the complet entity graph on every page que nécessite it. Don’t assume Google va récupérer a referenced entity from a différent URL. Yoast’s production choice is exactly ce: it emits the complet graph on every page plutôt que relying on cross-page resolution.

Comment valider nested schema

Two outils:

  • Résultats enrichis Tester — in practitioner testing as of July 2026, it parses @graph arrays and resolves @id références dans the testé document: quand entity A références B by @id and B is declared in the même graph, ils montrer as connected; quand the referenced @id is jamais declared in the testé markup, the outil encore parses the declared items individually sans erroring, but can’t montrer the connection. Google doesn’t document ce UI behavior explicitly anywhere I pourrait trouver, so treat it as observed, reproducible outil behavior plutôt que an official specification — and re-check it si the tool’s UI changements. Que behavior is exactly pourquoi orphaned références slip via — aucun error, simplement a manquant lien.
  • Balisage de données structurées Validator — schema.org’s propre vocabulary validator, moins opinionated à propos de Google’s pris en charge rich-result types.

Tester the rendered page, pas simplement votre template source — si JSON-LD is injected via JavaScript, confirmer it’s en réalité présent. Google documents reading JSON-LD that’s dynamically injected by JavaScript, but that’s spécifique to Google — JavaScript-execution behavior varies by robot d’exploration and product, and there’s aucun blanket rule que every AI robot d’exploration renders JS the même façon (or at tout). Shipping JSON-LD in the initial HTML plutôt que assuming it’ll be executed is the conservative choice — that’s a schema-markup-for-AI concern.

Myths worth killing

  • @id needs to be a real, live, fetchable URL.” Aucun — by convention it’s a URL canonique plus a fragment, but its function is identification, pas fetchability. The fragment doesn’t besoin to resolve to its propre page.
  • “Même @id on différent pages auto-merges ceux entities in Google’s index, comme a balise canonical consolidates pages.” Pas confirmed by quelconque Google doc. Consistent @id is bon hygiene, pas a proven cross-page consolidation mechanism.
  • “You must use @graph; separate script blocks are wrong.” Faux. Google understands les deux. @graph is a maintainability choice.
  • “More nesting always improves entity understanding.” Seulement si the entities are genuinely connexe. Nesting unrelated items (Schema App’s exemple: an unrelated Event sous a Recipe) doesn’t aider and peut muddy signals.
  • @id/@graph structure is a ranking or rich-result factor.” Aucun. Its valeur is disambiguation and reduced duplication — consistent with schema pas being a ranking factor at tout.
  • “An undeclared @id is harmless; engines just ignore it.” That’s the orphaned-reference échec — the intended connection silently doesn’t formulaire, and outils souvent don’t error, so vous ship it unnoticed.

Où ce sits

Ce is the how-to couche sous the données structurées hub, a deeper sibling of balisage de données structurées (qui introduces @id/@graph) and JSON-LD (the format). It leans on the même entity-understanding thinking as entities and balisage de données structurées pour AI — a well-built graph is entity infrastructure, si the consumer is Google’s Knowledge Graph or an LLM. The whole sub-cluster lives à l’intérieur on-page SEO.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.