squirrelscan
GitHub

JSON-LD @id: stable identifiers for your entities

The JSON-LD @id gives a node a stable IRI, so other nodes and pages can reference one entity, not redeclare it. How to write it and what breaks it.

The @id in JSON-LD is a node’s identifier: an IRI, normally an absolute URL, that names the thing the node describes, so other nodes and other pages can refer to the same thing instead of describing it again.

The JSON-LD 1.1 specification uses @id to uniquely identify node objects, and calls a node that contains only an @id a node reference. A relative @id is resolved against the document’s base, so #organization on the homepage and #organization on a blog post become two different identifiers. The fragment itself is a convention. Yoast uses https://example.com/#organization, and what matters is that the full value is absolute and byte-identical on every page.

Category: Structured Data

Why it matters

An @id is what turns forty copies of a company’s details into one company. Without it, every page’s organization is a separate node that only shares a name. With a relative or per-page id, it is worse, because the markup now claims forty different identities. Two plugins that each give the organization their own @id split it in two. A reference to an @id that nothing on the site declares points at nothing.

How squirrelscan checks it

These rules read squirrelscan’s site-wide entity map. schema/entity-identity fails when a named organization, local business, person or website is declared on several pages without an @id. schema/entity-split-identity fails when one entity, meaning the same @type set and name declared together on at least one page, appears under more than one @id. Two different authors with the same name on different pages are not merged. schema/entity-dangling fails when a referenced @id, other than a sameAs link, is declared nowhere in the crawl. A publisher declared on the homepage and referenced from articles resolves. schema/entity-id-format warns about identifiers that are neither an absolute http or https URL nor a global scheme such as urn: or doi:, after resolving relative ones where it can. schema/entity-orphan notes @ids declared on one page and referenced by nothing, leaving out page-level types such as articles, products and breadcrumbs.

RuleWhat it flagsSeverity
One organization, or sixty? Entities declared without an @idYour site declares the same organization on every page with nothing to say they are one thing. A search engine reading 60 pages sees 60 organizations.error
Two plugins, two @ids, one organization split in halfYoast declares your organization under one @id and WordLift under another. A search engine reads two companies, and neither gets the full picture.error
A publisher that points at nothingA reference to an @id that nothing in the crawl declares. squirrel checks against the whole site, so a publisher the homepage declares still resolves.error
A bare #organization is one entity per page, not one entityA relative @id resolves against the page it sits on, so the same fragment on forty pages is forty identifiers. The markup validates and the entity still never accumulates.warning
An @id that nothing points atGiving an entity an identifier is the expensive part. One that nothing references and that appears on a single page is doing no more than an inline block.info

How to fix it

Write the full URL, and reuse it byte for byte:

{
  "@context": "https://schema.org",
  "@graph": [
    { "@type": "Article", "@id": "https://example.com/post#article",
      "publisher": { "@id": "https://example.com/#organization" } },
    { "@type": "Organization", "@id": "https://example.com/#organization",
      "name": "Example Ltd", "url": "https://example.com/" }
  ]
}

Fix a template that concatenates a bare fragment without the site URL (the format fix). Choose one @id when two plugins compete, and turn off schema output in one of them (the split identity fix). Declare every referenced node somewhere in the crawl (the dangling fix), and give repeated entities an @id (the identity fix).

Run the check

squirrel audit https://example.com --rule-include schema/entity-identity,schema/entity-split-identity,schema/entity-dangling,schema/entity-id-format,schema/entity-orphan

A signed-out local audit costs nothing.

  • Entity: A thing a site describes in structured data, such as an organization, person or product, identified across pages so search engines and agents can tell it is one thing.
  • JSON-LD: JSON for Linking Data, the format Google recommends for structured data, embedded in a <script type="application/ld+json"> block.

References

Type to search…

↑↓ navigate↵ openesc close