The layer that breaks silently: how we test our own schema.
The one layer that changes no pixel on the page is the layer machines read most carefully. JSON-LD describes your site to the answer engine not sentence by sentence, but entity by entity.
This site’s graph is built from four families: identity (Organization, ProfessionalService, Person, WebSite), page (WebPage, ItemPage, CollectionPage), service (Service, HowTo, FAQPage) and content (TechArticle in guides, BlogPosting in the journal, Article in cases, DefinedTerm in the glossary). They all live in one @graph, wired to each other by @id — the author Person is both the Organization’s founder and every Article’s author. A model resolves "who, what, where" from those links.
Why @id sits at the centre of everything
Sites that copy their schema page by page introduce the same person forty times over. Forty separate Person objects can be forty separate humans to a model. @id solves it in one line: the person is defined once and everything else points at them. The bigger the graph, the bigger the win — the work on a case page never re-describes its creator, it links to the node that already exists.
- "@type": "Article"
- "author": { "@id": "…/#person" }
- "publisher": { "@id": "…/#org" }
- "isPartOf": { "@id": "…/#blog" }
- # three links, zero repetition
Every node answers one question
Organization says "who is this" and carries a logo — Google’s organization rich result does not work without one. Person says "who is behind it"; jobTitle and knowsAbout are the fields a model uses to match expertise. WebPage says "what is this page" and binds to the site through isPartOf. BreadcrumbList states the page’s place in the hierarchy. Article carries the writer, the date and the word count.
Two types exist specifically for answer engines. FAQPage marks question–answer pairs; that pair is exactly the unit a model quotes. HowTo gives the process step by step — the machine-readable form of "how does this work". Both sit on this site’s service pages, and their content is visible on the page as well.
Not lying in a field nobody sees
Schema is worth exactly as much as it is true: wordCount is really counted, timeRequired is computed from reading time, datePublished is the real publication day. Lying in a field that never renders is the most expensive lie there is — the only thing that reads it is the thing that remembers best.
There is a subtractive side to this too. This site’s Organization node has no sameAs: with no social profile list to publish, the field was simply never written. Same for telephone and address. Leaving it empty beats appearing to have filled it — and the verification suite stands guard in the opposite direction: if a fabricated profile ever slips in, the test goes red.
The same discipline applies to price. Writing offers or priceRange onto the Service node would have been easy; with no published price list, it was not written. Information that exists in schema but not on the page is a pattern Google explicitly forbids.
Schema does not slow the page down
JSON-LD is a script tag but it is not executable; it survives under the strictest Content-Security-Policy. This site runs default-src 'self' — the schema layer asked for no loosening at all. The weight is small too: a six-to-eight-node graph per page is a few kilobytes after gzip and blocks no request.
On the validation side two tools suffice: Google’s Rich Results Test catches rich-result eligibility, schema.org’s own validator catches type errors. But the real sentry belongs in the suite — this site has a separate test for each node type, because schema is the layer that breaks silently: no pixel changes, no error appears.
In the invisible layer, write only what can be verified.