← Back to Course Index

Module 3.3 — Nesting and @id Referencing in Structured Data

Structured data is not just a collection of isolated schema blocks scattered across a page. At its best, it forms a connected entity graph — a machine-readable picture of how the things described on your page and across your site relate to one another. This module teaches you the two mechanisms that make that graph possible: nesting and @id referencing.

By the end of this module you will understand not only the syntax but the architectural reasoning behind these patterns, and you will be able to hand-author a fully connected JSON-LD block that validates cleanly and communicates rich entity relationships to search engines.

Why a Connected Graph Matters

Google does not just read keywords — it builds a model of entities (things with identity) and the relationships between them. When your structured data expresses those relationships explicitly, you are giving the engine a shortcut: instead of inferring that the brand of this product is the same organization as the site owner, you assert it directly.

A flat list of schema blocks — one for Product, a separate one for Organization, another for BreadcrumbList — describes three independent facts. A connected graph with nesting and @id links describes a network of related facts. The latter is significantly more valuable signal for Knowledge Graph reinforcement, entity disambiguation, and rich-result eligibility.

JSON-LD Fundamentals Recap

JSON-LD (JSON for Linked Data) is the format Google recommends for structured data. Before getting into nesting, make sure these core concepts are solid:

Nesting: Embedding an Entity Inside Another

Nesting means placing one schema type directly inside a property of a parent type. The child entity becomes an inline description of a property value rather than a separate top-level object.

The most common example is a Product that contains an Offer, which itself contains an AggregateRating and a Brand:

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Noise-Cancelling Headphones Pro",
  "image": "https://example.com/images/headphones-pro.jpg",
  "description": "Professional-grade noise-cancelling headphones.",
  "brand": {
    "@type": "Brand",
    "name": "SoundCore"
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.7",
    "reviewCount": "312"
  },
  "offers": {
    "@type": "Offer",
    "url": "https://example.com/products/headphones-pro",
    "priceCurrency": "USD",
    "price": "249.99",
    "availability": "https://schema.org/InStock",
    "seller": {
      "@type": "Organization",
      "name": "Example Store"
    }
  }
}

Notice how brand, aggregateRating, offers, and seller each have their own @type. This is nesting. The child types inherit context from their parent and create a hierarchical, richly described object.

Rules and Best Practices for Nesting

@id: Giving Entities a Persistent Identity

The @id property assigns a stable, globally unique identifier to an entity. In practice, this is always a URL — either a real page URL, a fragment URL, or a canonical URL representing the entity's "home" in your data model.

Once an entity has an @id, any other entity anywhere on the site can reference it by that identifier — without repeating all its properties. The reference is simply an object containing only the @id:

{ "@id": "https://example.com/#organization" }

A parser or search engine that has already seen the full definition of https://example.com/#organization knows that this reference points to that same entity.

Defining and Referencing Entities with @graph

The canonical pattern is to use a single @graph array in one <script type="application/ld+json"> block. This allows you to define entities (with all their properties) and then cross-reference them within the same document.

Here is the complete structure for a product page, demonstrating both nesting and @id referencing:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@graph": [

    {
      "@type": "Organization",
      "@id": "https://example.com/#organization",
      "name": "Example Store",
      "url": "https://example.com",
      "logo": {
        "@type": "ImageObject",
        "url": "https://example.com/logo.png"
      },
      "sameAs": [
        "https://twitter.com/examplestore",
        "https://www.facebook.com/examplestore"
      ]
    },

    {
      "@type": "WebSite",
      "@id": "https://example.com/#website",
      "url": "https://example.com",
      "name": "Example Store",
      "publisher": { "@id": "https://example.com/#organization" }
    },

    {
      "@type": "BreadcrumbList",
      "@id": "https://example.com/products/headphones-pro#breadcrumb",
      "itemListElement": [
        {
          "@type": "ListItem",
          "position": 1,
          "name": "Home",
          "item": "https://example.com"
        },
        {
          "@type": "ListItem",
          "position": 2,
          "name": "Headphones",
          "item": "https://example.com/headphones"
        },
        {
          "@type": "ListItem",
          "position": 3,
          "name": "Noise-Cancelling Headphones Pro",
          "item": "https://example.com/products/headphones-pro"
        }
      ]
    },

    {
      "@type": "Product",
      "@id": "https://example.com/products/headphones-pro#product",
      "name": "Noise-Cancelling Headphones Pro",
      "image": "https://example.com/images/headphones-pro.jpg",
      "description": "Professional-grade noise-cancelling headphones for audiophiles.",
      "sku": "NCH-PRO-001",
      "brand": {
        "@type": "Brand",
        "name": "SoundCore"
      },
      "manufacturer": { "@id": "https://example.com/#organization" },
      "aggregateRating": {
        "@type": "AggregateRating",
        "ratingValue": "4.7",
        "bestRating": "5",
        "reviewCount": "312"
      },
      "review": [
        {
          "@type": "Review",
          "reviewRating": {
            "@type": "Rating",
            "ratingValue": "5",
            "bestRating": "5"
          },
          "author": {
            "@type": "Person",
            "name": "Jordan M."
          },
          "reviewBody": "Exceptional noise cancellation, incredibly comfortable."
        }
      ],
      "offers": {
        "@type": "Offer",
        "url": "https://example.com/products/headphones-pro",
        "priceCurrency": "USD",
        "price": "249.99",
        "priceValidUntil": "2025-12-31",
        "availability": "https://schema.org/InStock",
        "itemCondition": "https://schema.org/NewCondition",
        "seller": { "@id": "https://example.com/#organization" }
      }
    },

    {
      "@type": "WebPage",
      "@id": "https://example.com/products/headphones-pro#webpage",
      "url": "https://example.com/products/headphones-pro",
      "name": "Noise-Cancelling Headphones Pro — Example Store",
      "isPartOf": { "@id": "https://example.com/#website" },
      "primaryImageOfPage": {
        "@type": "ImageObject",
        "url": "https://example.com/images/headphones-pro.jpg"
      },
      "breadcrumb": { "@id": "https://example.com/products/headphones-pro#breadcrumb" },
      "about": { "@id": "https://example.com/products/headphones-pro#product" }
    }

  ]
}
</script>

Anatomy of the Pattern: What Each Part Achieves

Let us break down the key decisions in the block above:

Choosing Between Nesting and Referencing

The decision rule is straightforward:

When in doubt, ask: "If I move to a different page on this site, does this entity still exist as the same thing?" If yes, it deserves an @id.

Designing @id URIs Consistently

The value of @id must be a URI. It does not have to resolve to a real page, but it must be stable, unique, and consistent across your entire implementation. The recommended conventions are:

Cross-Page Entity Referencing

The power of @id extends beyond a single page. When the same @id value appears in schema blocks across multiple pages, parsers and search engines can merge those descriptions into a unified entity profile.

For example, if every product page on your site includes:

"seller": { "@id": "https://example.com/#organization" }

…and your homepage defines https://example.com/#organization in full (with name, url, logo, sameAs, contact info, etc.), Google can associate the full organizational profile with every seller reference across the entire catalog. You are contributing incrementally to an entity's description each time it appears — which compounds into a stronger Knowledge Graph signal over time.

This is the core mechanism behind entity SEO: consistent, cross-page use of stable @id URIs that resolve to the same entity is how you build machine-readable authority.

Common Mistakes to Avoid

Validation Workflow

After authoring a nested, cross-referenced JSON-LD block, validate it rigorously:

Scaling This Pattern Programmatically

Hand-authoring this block on one product page is a learning exercise. In production, it must be generated programmatically from your CMS data. The architecture decisions you make here carry directly into Phase 4:

Hands-On Practice

Before moving on, complete the following exercise without looking at any pre-built examples:

  1. Pick a real or hypothetical product page. Write the full @graph-based JSON-LD block from scratch, including: Organization (with @id and sameAs), WebSite (referencing Organization), BreadcrumbList (with at least three levels), Product (with nested Brand, AggregateRating, at least one Review, and an Offer whose seller references the Organization @id), and a WebPage that references the breadcrumb and the product.
  2. Validate the block in the Schema Markup Validator. Resolve every error and warning.
  3. Then run it through the Rich Results Test and note which features Google considers it eligible for.
  4. List every @id you used and write a one-sentence justification for why each entity deserved a persistent identifier.

Module Milestone

You have completed this module when you can: