Using @id in Schema.org Markup for SEO & Knowledge Graphs

Posted in:
Insights
//
February 5, 2025
The complete guide to using @id for SEO and Knowledge Graphs
Using @id in Schema.org Markup for SEO, LLMs, & Knowledge Graphs by Tyler Einberger
//
Est. Read Time:
8 minutes

The @id attribute in JSON-LD structured data is the foundation for creating clear and maintainable internal entity relationships with your schema markup. To understand how to use it effectively, we must start with its fundamental role in JSON-LD and build up to implementation patterns.

What @id Does

In JSON-LD structured data, @id creates unique identifiers for nodes in your data graph. Unlike the Schema.org properties url and identifier that communicate information to search engines, @id is an internal reference system within your JSON-LD markup. This distinction is important because it affects how we use @id in practice.

<div class="post-note">TL;DR: @id gives a schema node a stable, unique identifier (usually a URL or URL fragment) that can be referenced elsewhere. This takes isolated bits of JSON‑LD and turns them into a connected data graph, the core principle of linked data.</div>

Let's look at a basic implementation:

{
  "@context": "https://schema.org",
  "@type": "Organization",
  "@id": "https://example.com/#organization",
  "name": "Example Company",
  "url": "https://example.com"
}

The @id creates a reference point for this organization entity in this example. The value looks like a URL, but it doesn't need to point to a webpage - it's just an identifier. We commonly use URL-style formatting because it helps maintain uniqueness and provides a logical structure for our identifiers.

Understanding References and Connections

When we define an entity with an @id, we can reference it elsewhere in our structured data. This creates explicit connections in our data graph. Here's how that works:

{
  "@context": "https://schema.org",
  "@type": "WebPage",
  "name": "About Us",
  "publisher": {
    "@id": "https://example.com/#organization",
    "url": "https://example.com"
  }
}

When a JSON-LD parser processes these snippets, it recognizes that the WebPage's publisher refers to the same entity defined in our first example. This connection is precise and unambiguous, thanks to the matching @id values. 💪

Here's another way to visualize it:

@id = url + unique name

//what I do

@id = {url for @type entity home} + #{schema-type}

@id = https://example.com/#organization

Page Level vs. Site Level (Scope of @id)

Here's where things get fun - and where many implementations go wrong. We need to understand three key concepts about scope:

  1. Fragments: When you use a fragment on its own, like #organization, it creates a reference point within the current page only. The fragment resolves against the current page's URL. This works fine for connecting entities on the same page but becomes problematic for site-wide references.
  2. url + @id: To create proper entity connections across pages, you need both @id and url properties working in tandem. While your @id might be something like https://example.com/#organization,  pair it with the url property (like "url": "https://example.com") to establish where this entity lives (entity home). The @id alone isn't enough - the combination of @id and url creates the best connection across same-site pages.
  3. Search engines: Search engines, like Google, process structured data on a page-by-page basis. So, even if you use the same @id across different pages, the search engine won't automatically merge this information. This leads us to an important implementation pattern.

<div class="post-note-cute"><b>Note:</b> Just like search engines, publicly available schema.org markup testing tools—like Google Rich Results Tester and Schema.org Validation Tool—analyze on a page by page basis. They will not find or flag @id error. Even crawling tools like Screaming Frog will not catch these; even if you have all of the Structured data settings turned on. It's up to you to implement properly and be confident about it!. You got this. 🫡</div>

I prefer the Schema.org validation tool to the Google Rich Results Testing Tool.
https://validator.schema.org/

Let's jump back in.

The "Cross-Page" Implementation Pattern

To properly reference entities across pages, you must use both @id and url properties together. Here's how that works:

First, define your entity with both properties:

{
  "@context": "https://schema.org",
  "@type": "Product",
  "@id": "https://example.com/products/blue-shirt#product",
  "url": "https://example.com/products/blue-shirt",
  "name": "Classic Blue Shirt"
}

Then, when referencing this product from another page, you need to include both properties again:

{
  "@type": "Product",
  "@id": "https://example.com/products/blue-shirt#product",
  "url": "https://example.com/products/blue-shirt"
}

The @id creates the unique identifier, while the url property tells search engines where to find this entity's home. You need both to create proper cross-page connections.

When referencing this product from another page:

{
  "@context": "https://schema.org",
  "@type": "WebPage",
  "name": "Featured Products",
  "mainEntity": {
    "@id": "https://example.com/products/blue-shirt#product",
    "url": "https://example.com/products/blue-shirt"
  }
}

We include the @id for consistent identification and the url property to tell search engines where to find the content. This pattern ensures each page can stand alone while maintaining consistent entity identification across your site.

More Advanced Entity Identification in Schema.org

Disambiguation is important to consider no matter what. Structured data gives us the ability to do this through the combination of @id for internal references and sameAs for connecting to authoritative sources across the web. Here's what this looks like in practice:

{
  "@context": "https://schema.org",
  "@type": "Article",
  "@id": "https://example.com/blog/seo-tips#article",
  "author": [
    {
      "@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",
        "https://en.wikipedia.org/wiki/Jane_Doe",
        "https://g.co/kgs/JWFoNWi"
      ]
    },
    {
      "@type": "Person",
      "@id": "https://example.com/team/john-smith#person",
      "name": "John Smith",
      "url": "https://example.com/team/john-smith",
      "sameAs": [
        "https://www.linkedin.com/in/john-smith",
        "https://en.wikipedia.org/wiki/John_Smith_(author)",
        "https://g.co/kgs/Mx7yP9"
      ]
    }
  ]
}

The @id property creates unique references within your structured data, while sameAs links connect to authoritative external profiles. This combination helps search engines confidently identify who's who, even when dealing with common names or multiple authors.

You might just influence a knowledge panel in Google Search with these practices.

A Person Knowledge Panel in Google Search for "Tyler Einberger"
See for yourself: Tyler Einberger

The @graph Technique

For complex pages with multiple related entities and @types, the @graph technique helps organize our markup while maintaining clear relationships:

{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "Organization",
      "@id": "https://example.com/#organization",
      "name": "Example Company",
    },
    {
      "@type": "WebPage",
      "@id": "https://example.com/about#webpage",
      "publisher": {
        "@id": "https://example.com/#organization"
      }
    }
  ]
}

This  keeps our markup organized and makes relationships explicit while ensuring all necessary information is on each page.

External Entity Connections

For connecting to external entities, entity linking through the sameAs property is the preferred approach. While @id and url work together to establish connections within your own website, sameAs helps search engines understand how your entities relate to established entities across the web:

{
  "@context": "https://schema.org",
  "@type": "Organization",
  "@id": "https://example.com/#organization",
  "url": "https://example.com",
  "sameAs": [
    "https://wikipedia.org/wiki/Your_Company",
    "https://wikidata.org/entity/Q12345",
    "https://twitter.com/YourCompany",
    "https://www.linkedin.com/company/your-company"
  ]
}

Entity linking through sameAs serves a different purpose than internal references with @id/url. While @id/url helps establish connections between your own content, sameAs helps search engines build a broader knowledge graph by connecting your entities to authoritative external sources. This is particularly valuable because:

  1. It helps search engines understand your entity in relation to established knowledge bases
  2. It provides additional verification of your entity's identity
  3. It contributes to the global knowledge graph's understanding of your entity
  4. It can help search engines display rich results by drawing from these connected sources

The sameAs property can point to various types of authoritative sources:

  • Knowledge bases (Wikipedia, Wikidata)
  • Social media profiles
  • Official listings
  • Industry databases

By using entity linking through sameAs alongside your internal @id/url connections, you create a more complete picture of your entities for search engines to understand.Practical Implementation StrategyWhen implementing @id across a site, follow this systematic approach:

  1. Start with your organization entity - it's typically the most referenced.
  2. Create a consistent pattern for different entity types.
  3. Document your @id naming conventions for team reference.
  4. Include both @id and url properties for cross-page entities.
  5. Validate your implementation using Schema.org's validator.
  6. Maintain complete markup on each page despite references.

Remember that while current search engine processing happens page by page, implementing @id thoughtfully creates structured data that's both maintainable and ready for future developments in how search engines might process connected data.

Testing and Validation

Always test your implementation using Google's Rich Results Test and.or Schema.org's validator. The Schema.org validator is my preference as it validates more than rich result-eligible types. It also shows how your connected pieces of schema markup work together.

Pay special attention to:

  • Consistent formatting of @id values
  • Presence of required properties on each page
  • Proper resolution of references
  • Clear entity relationships

I do not use the fragment approach for schema.org @id

Best Practices for Using @id (On‑Page and for Cross‑Page Linking)

Here are some practical implementation details:

1. Choose a Consistent Format

Use your page’s canonical URL plus a hash and a descriptive entity name. For example:

  • Homepage: "@id": "https://example.com/#organization"
  • Product Page: "@id": "https://example.com/widgets/widgetA#product"

Some people prefer using just a fragment (e.g., "@id": "#product123"), which is resolved against the page URL. Either works, but the full URL plus fragment is often clearer. 

<div class="post-note-cute">Note: As of January 2024, Google's examples favor using hashtags for in‑page identifiers.</div>

2. Use Meaningful Fragments

Descriptive fragments like #organization or #author-jane-doe are more straightforward to debug and understand than generic ones like #id1.

3. One ID per Entity

Assign a unique, unchanging @id to each entity and always use that same identifier when referring to it. Avoid using the same @id for different entities to prevent unintended merging.

4. Keep IDs Stable

Treat your @id values as permanent labels. Avoid dynamic components (like timestamps) that change on every page load. Consistency is important—if "Product123" is represented by https://example.com/products/123#item, use that exact string every time.

5. Complete Each Page's Schema

Since Google processes each page independently, every page's structured data must include all required properties—even if you reference an entity from another page via @id. If necessary, include a minimal duplicate of the entity by including url (or use the @graph technique) to help the page stand independently.

6. Use HTML Links to Reinforce Connections

Even though structured data @id linking across pages isn’t automatically merged, traditional HTML links are still recognized. For example, if our Organization has a dedicated page, include an HTML link (e.g., <code><a href="/about-us#organization">Our Organization</a></code>) on relevant pages. This reinforces the connection to search engines and knowledge graph builders.

7. Use sameAs for External Entity Linking

To connect our internal entity with external authoritative sources (like Wikipedia or Wikidata), use the sameAs property. This helps search engines further disambiguate and consolidate our entity in the global Knowledge Graph.

8. Test Your Markup

Run your schema/pages through Google's Rich Results Test or Schema.org's validator. I prefer the Schema.org validator since it validates more than what’s available as a rich result in Google Search. 

Building for the Future

While search engines currently process structured data page by page, implementing @id consistently creates a foundation for better-organized structured data. The Web Almanac shows growing adoption of JSON-LD (now at 41% of pages), with sophisticated entity relationships becoming more common, especially in ecommerce and local business implementations.The careful use of @id and url properties helps create clear entity relationships that benefit current SEO needs and prepare for future developments in how search engines might process connected data.

Key takeaways as an image.

<div class=post-note-cute"><p>Follow these practices to be confident your structured data is actionable (for immediate SEO features) and strategically sound for long‑term semantic SEO and AI readiness.</p><p>Happy knowledge graph building!</p></div>

Schema.org Quiz Time

Tell me what's wrong with my homepage schema.org markup, and I'll give you a shoutout in this article. (Hint: I'm not talking about the lack of @graph implementation).

{
	"@context": "https://schema.org",
	"@type": ["Organization","LocalBusiness"],
	"name": "Momentic",
	"alternateName":["Momentic®","Momentic SEO","MOMENTIC","Momentic LLC","Momentic Marketing","Momentic Inc.","Momentic Inc","MOMENTIC LLC"],
	"legalName":"Momentic, LLC",
	"logo": "https://assets-global.website-files.com/6213ddd7bd3eb80dfdbf1d95/62a215921d30e82307ea5f1b_Momentic%20Landscape%20(2022)-p-500.webp",
	"image": "https://assets-global.website-files.com/6213ddd7bd3eb80dfdbf1d95/62a215921d30e82307ea5f1b_Momentic%20Landscape%20(2022)-p-500.webp",
	"photo":"https://assets-global.website-files.com/6213ddd7bd3eb80dfdbf1d95/629a2e6de39f70f44dcbf99c_Momentic%20Office-p-800.webp",
	"@id": "https://momenticmarketing.com/#organization",
	"slogan":"Dead set on delivering results.",
	"url": "https://momenticmarketing.com/",
	"description": "Momentic is an SEO marketing firm that generates long-term, quantifiable growth for their clients.",
    "founder":[{
		  "@type":"Person",
		  "name": "Tyler Einberger",
		  "alternateName": "Twin Lull",
		  "familyName": "Einberger",
		  "givenName": "Tyler",
		  "description": "COO of Momentic",
		  "id": "https://momenticmarketing.com/team/tyler-einberger#person",
		  "url": "https://momenticmarketing.com/team/tyler-einberger",
		  "mainEntityOfPage": "https://momenticmarketing.com/team/tyler-einberger",
		  "image": "https://assets-global.website-files.com/6213ddd7bd3eb8fb93bf1da4/62aca4fdd09d20d370c8d62b_Tyler%20Talking%20Color.png",
		  "sameAs": [
			"https://www.google.com/search?kgmid=/g/11f0ztyxj9",
      "https://www.google.com/search?kgmid=/g/11l75w9y_g",
      "https://www.google.com/search?kgmid=/g/11hcx8tsrp",
			"https://www.wikidata.org/wiki/Q123358916",
			"https://twitter.com/web_shredder",
			"https://www.crunchbase.com/person/tyler-einberger",
			"https://uwm.edu/sce/instructors/tyler-einberger/",
			"https://www.youtube.com/channel/UCxg3CGv4QpT5rIQV6rrh9DQ",
			"https://www.linkedin.com/in/tyler-einberger",
			"https://tylereinberger.com/",
			"https://tylereinberger.wordpress.com/",
			"https://music.apple.com/sc/artist/twin-lull/1546007568",
			"https://www.tiktok.com/music/My-English-6922647194210142209",
			"https://open.spotify.com/artist/217ReduBchO4xG62Udd2oS"
		  ],
		  "jobTitle": "Chief Operations Officer",
		  "worksFor": {
			"@id": "https://momenticmarketing.com/#organization"
			}
	 },
	 {
		  "@type":"Person",
		  "name": "Tony Van Hart",
		  "familyName": "Van Hart",
		  "givenName": "Tony",
		  "description": "CEO of Momentic",
		  "url": "https://momenticmarketing.com/team/tony-van-hart",
		  "mainEntityOfPage": "https://momenticmarketing.com/team/tony-van-hart",
		  "image": "https://assets-global.website-files.com/6213ddd7bd3eb8fb93bf1da4/62b0bef0dbb46258df206926_Tony.png",
		  "sameAs": [
			"https://www.linkedin.com/in/tony-van-hart-2609ba24",
			"https://www.instagram.com/tonyyyyy/",
			"https://www.crunchbase.com/person/tony-van-hart",
			"https://theorg.com/org/momentic/org-chart/tony-van-hart"
		  ],
		  "jobTitle": "Chief Executive Officer",
		  "worksFor": {
			"@id": "https://momenticmarketing.com/#organization"
			}
		}
	],
	"mainEntityOfPage":"https://momenticmarketing.com/",
	"telephone" : "+14144889140",
	"priceRange": ["$", "$$"],
	"address": {
		"@type": "PostalAddress",
		"streetAddress": "316 N Milwaukee St #350",
		"addressLocality": "Milwaukee",
		"addressRegion": "WI",
		"postalCode": "53202",
		"addressCountry": "US"
		},
    "geo": {
    "@type": "GeoCoordinates",
    "latitude": 43.0344638,
    "longitude": -87.9056667
		},
	"hasMap":"https://www.google.com/maps/place/Momentic/@43.0344638,-87.9056667,15z/data=!4m6!3m5!1s0x880519a6770691a3:0xd9a2d7728252b777!8m2!3d43.0344638!4d-87.9056667!16s%2Fg%2F11gg9bgn53",
	"areaServed": {
		  "@type": "Country",
		  "name": "United States",
		  "sameAs": ["https://en.wikipedia.org/wiki/United_States","https://www.google.com/search?kgmid=/m/09c7w0"]
		},
    "openingHoursSpecification": {
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": [
      "Monday",
      "Tuesday",
      "Wednesday",
      "Thursday",
      "Friday"
		],
    "opens": "08:00",
    "closes": "17:00"
		},
    "sameAs": [
		"https://www.google.com/search?q=Momentic&ludocid=15682333739270190967",
		"https://goo.gl/maps/n4GRXhrcrsHGZpXm8",
		"https://www.facebook.com/MomenticSEO/",
		"https://twitter.com/MomenticSEO",
		"https://www.instagram.com/momenticseo/",
		"https://www.linkedin.com/company/momentic-seo",
		"https://www.crunchbase.com/organization/momentic-677e",
		"https://theorg.com/org/momentic",
		"https://clutch.co/profile/momentic"
		] 
 }

Shoutout to Shaikat Ray who was helpful in calling out Tony's missing @id.

<div class="post-note-cute"><p><strong>Free IRL Schema.org event in Milwaukee on April 16th!</strong><p>Martha van Berkel, CEO of Schema App, will be presenting live at MKE DMC on April 16, 2025. In this session, we’ll discuss how digital marketers and SEOs can leverage Schema Markup to build a reusable content knowledge graph and help search engines / LLMs understand your content and its connections more accurately.</p> <p>Event details & RSVP here!</p></div>

basic visual representation of a knowledge graph for a person
Image via Schema App | What is a Content Knowledge Graph?

Further Reading

Here are some helpful and contextually relevant resources I gathered for y'all to help you on your journey.

Bar chart showing increase over time with Momentic logo