Nesting, Relationships, and the @id Pattern
Session 2.9 · ~5 min read
Every schema block you have written so far, Organization, Person, LocalBusiness, Product, Service, FAQ, HowTo, is an island. Each describes something, but without explicit connections between them, Google has to infer the relationships. And as we established in Session 2.1, inference is probabilistic. Declaration is deterministic.
This session introduces the @id pattern, nesting, and the @graph construct. Together, they turn isolated schema blocks into a connected entity graph. This is where structured data becomes genuinely powerful.
The Problem With Isolated Schema
Consider a website with three pages, each containing its own schema block:
- Homepage: Organization schema for "Acme Corp"
- About page: Person schema for "Jane Smith"
- Service page: Service schema for "Automation Consulting"
Without connections, Google sees three separate data objects. It may or may not realize that Jane Smith founded Acme Corp, or that Acme Corp provides Automation Consulting. With @id references, these three objects become a single, connected graph that explicitly describes the relationships.
Acme Corp"] P1["Person
Jane Smith"] S1["Service
Consulting"] end subgraph With @id O2["Organization
Acme Corp"] <-->|founder / worksFor| P2["Person
Jane Smith"] O2 <-->|provider| S2["Service
Consulting"] end style O1 fill:#222221,stroke:#8a8478,color:#ede9e3 style P1 fill:#222221,stroke:#8a8478,color:#ede9e3 style S1 fill:#222221,stroke:#8a8478,color:#ede9e3 style O2 fill:#222221,stroke:#c8a882,color:#ede9e3 style P2 fill:#222221,stroke:#6b8f71,color:#ede9e3 style S2 fill:#222221,stroke:#6b8f71,color:#ede9e3
How @id Works
The @id property assigns a unique identifier to a schema object. This identifier is a URI (usually your website URL with a hash fragment). When another schema object references that same @id, Google knows they are talking about the same entity.
// On the homepage
{
"@context": "https://schema.org",
"@type": "Organization",
"@id": "https://www.acmecorp.com/#organization",
"name": "Acme Corp",
"founder": {
"@type": "Person",
"@id": "https://www.acmecorp.com/#person-jane-smith"
}
}
// On the about page
{
"@context": "https://schema.org",
"@type": "Person",
"@id": "https://www.acmecorp.com/#person-jane-smith",
"name": "Jane Smith",
"worksFor": {
"@type": "Organization",
"@id": "https://www.acmecorp.com/#organization"
}
}
The @id values are arbitrary strings, but the convention is https://yourdomain.com/#identifier. The hash fragment ensures the URI is unique and does not conflict with actual page URLs. Common patterns:
| Entity | @id Convention |
|---|---|
| Organization | https://example.com/#organization |
| Person (founder) | https://example.com/#person-firstname-lastname |
| Website | https://example.com/#website |
| LocalBusiness | https://example.com/#localbusiness |
| Product | https://example.com/#product-productname |
| Service | https://example.com/#service-servicename |
| Contact point | https://example.com/#contactpoint |
Nesting vs. Referencing
There are two ways to connect schema objects: nesting (inline) and referencing (via @id).
Nesting means putting the full object inside another:
"founder": {
"@type": "Person",
"name": "Jane Smith",
"jobTitle": "CEO"
}
Referencing means pointing to the object using @id:
"founder": {
"@type": "Person",
"@id": "https://www.acmecorp.com/#person-jane-smith"
}
Use nesting when the referenced entity has only a few properties and does not appear elsewhere. Use @id referencing when the entity has its own dedicated schema block (on the same or different page) with full details. The @id approach is cleaner and avoids duplicating data.
The @graph Construct
Instead of separate <script> tags for each schema block, you can use @graph to put them all in one block:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Organization",
"@id": "https://www.acmecorp.com/#organization",
"name": "Acme Corp",
"url": "https://www.acmecorp.com",
"founder": { "@id": "https://www.acmecorp.com/#person-jane-smith" }
},
{
"@type": "Person",
"@id": "https://www.acmecorp.com/#person-jane-smith",
"name": "Jane Smith",
"jobTitle": "CEO",
"worksFor": { "@id": "https://www.acmecorp.com/#organization" }
},
{
"@type": "WebSite",
"@id": "https://www.acmecorp.com/#website",
"name": "Acme Corp",
"url": "https://www.acmecorp.com",
"publisher": { "@id": "https://www.acmecorp.com/#organization" }
}
]
}
</script>
The @graph approach has two advantages: all entities share a single @context declaration, and the relationships between them are visually clear in one block. Either approach (separate scripts or @graph) is valid. Google processes both identically.
#website"] -->|publisher| O["Organization
#organization"] O -->|founder| P["Person
#person-jane-smith"] P -->|worksFor| O O -->|"provides (via Service)"| S["Service
#service-consulting"] S -->|provider| O P -->|"author (via Article)"| A["Article
Blog post"] A -->|publisher| O style W fill:#222221,stroke:#8a8478,color:#ede9e3 style O fill:#222221,stroke:#c8a882,color:#ede9e3 style P fill:#222221,stroke:#6b8f71,color:#ede9e3 style S fill:#222221,stroke:#6b8f71,color:#ede9e3 style A fill:#222221,stroke:#c47a5a,color:#ede9e3
Key concept: Real entity authority comes from connected schema, not isolated snippets. A single Organization block with name and URL is a whisper. An Organization connected to its founder (Person), its services (Service), its content (Article with author), and its website (WebSite with publisher) is a clear, loud declaration of a real entity with real relationships.
Cross-Page @id References
The @id pattern works across pages. Your homepage defines the Organization with @id: "https://example.com/#organization". Your blog post references that same @id in its Article schema's publisher property. Google crawls both pages and connects the dots.
This is why consistent @id values are critical. If your homepage uses #organization and your blog post uses #org, Google cannot connect them. Establish your @id conventions early and document them.
Common Relationship Properties
| Property | From Type | To Type | Meaning |
|---|---|---|---|
founder |
Organization | Person | Who founded the org |
worksFor |
Person | Organization | Where the person works |
publisher |
Article / WebSite | Organization | Who publishes the content |
author |
Article | Person | Who wrote the content |
provider |
Service | Organization | Who provides the service |
brand |
Product | Organization | Who makes the product |
parentOrganization |
Organization | Organization | Parent company |
alumniOf |
Person | Organization | Educational background |
Further Reading
- W3C: JSON-LD Node Identifiers (@id)
- W3C: JSON-LD Named Graphs (@graph)
- Google: Combining Multiple Schema Entities
- Schema.org: Data Model Documentation
Assignment
Combine all the schema blocks you have created in Sessions 2.4 through 2.8 into a connected graph.
- Assign consistent
@idvalues to every entity (Organization, Person, Product/Service). - Replace all inline nesting with
@idreferences where appropriate. - Create a single
@graphblock for your homepage that includes Organization, Person, and WebSite. - Draw a diagram (on paper or digitally) showing all the entities and their relationships. Every arrow should correspond to a property in your schema.
- Validate the combined graph using the Schema Markup Validator.