Skip to content
Technical SEO

Structured data, written as a graph instead of a pile

Most sites emit five disconnected JSON-LD blocks that never reference each other. One @graph with stable @id values says something the pile cannot: that these things are the same entity.

How should structured data be organised so a machine can tell the entities apart?

Mostafa Nouh — portraitMostafa NouhPublished 7 min read

The usual pattern is a plugin adding an Organization block, a theme adding a WebSite block, a breadcrumb plugin adding a third and an SEO plugin adding an Article. Four islands. Nothing in them says the article's author is the person in the Organization, so a consumer has to guess — and when it guesses wrong it merges you with someone who shares your name.

Stable identifiers are the whole trick

json
{
  "@context": "https://schema.org",
  "@graph": [
    { "@type": "Person",  "@id": "https://example.com/#person",  "name": "..." },
    { "@type": "WebSite", "@id": "https://example.com/#website",
      "publisher": { "@id": "https://example.com/#person" } },
    { "@type": "BlogPosting",
      "@id": "https://example.com/insights/slug#article",
      "author":   { "@id": "https://example.com/#person" },
      "isPartOf": { "@id": "https://example.com/#website" } }
  ]
}
Three nodes, two references, one entity resolved.

The @id values never change, they are absolute URLs, and the fragment makes them unambiguous. Every page on this site emits the same Person @id, so a consumer reading twelve of these pages accumulates one person rather than twelve.

What you refuse to assert matters as much

Structured data is a set of claims, and a false claim is worse than a missing one. This site does not emit an Organization node for XORV AnswerRank, because XORV is a product in development and asserting that a legal organisation exists would be a fact nobody confirmed. It is modelled as a SoftwareApplication authored by a Person — which is true.

Two languages, one entity

On a bilingual site the Person and the WebSite keep the same @id in both languages, while inLanguage, name and description are localised. The alternative — a separate Arabic entity graph — asserts that there are two people, which is the exact confusion structured data exists to prevent. Reciprocal hreflang does the rest.

A graph worth emitting

  • One <script type="application/ld+json"> per page, containing one @graph.
  • Absolute @id URLs with fragments, identical across every page and both languages.
  • Nodes reference each other by @id — never copy a Person node into an Article.
  • Every asserted property is visible or true on the page itself.
  • BreadcrumbList matches the breadcrumbs a human sees.
  • Validate the output, not the intention — read the rendered HTML.

Sources

Contact

Have a site or store that needs to work better?

Tell me what is happening and on which page. A diagnosis is a useful first deliverable on its own.

I read every message myself and reply within one working day — usually with a question or two before anything else, because a scope worth quoting needs them answered.

Available for remote work aligned to EST hours
Mostafa Nouh — portrait

Mostafa Nouh

Full-Stack Developer & Product Builder

Location
Egypt · Remote