Almost everything written about structured data stops at the same place: add the Article schema, add the FAQ schema, run the validator, see green ticks, done.
That gets you valid markup describing a page. It does not get you an entity — a thing the web agrees exists, with a stable identity that persists across every page you publish. The difference is what decides whether an assistant can confidently name you or has to hedge.
This is the graph running on the site you're reading, node by node, including the two mistakes I made first.
The core idea: reference, don't repeat
JSON-LD lets a node carry an @id, and lets other nodes point at that @id instead of describing the thing again.
Without it, forty articles each carry a fresh author block, and a parser sees forty separate mentions of somebody with the same name. With it, they all point at one identifier — and a parser sees one person who wrote forty articles.
Three stable identifiers carry this entire site:
| Identifier | Node type | Represents |
|---|---|---|
/#person | Person | Me, the human |
/#studio | Organization | The business |
/#website | WebSite | The publication |
Those three fragments never change. Every page on the site — article, case study, service page — hangs off them.
The Person node
The author node repeats on every article, so it carries only what establishes authority and leaves the exhaustive version to the homepage, which shares the same @id:
@id— the stable fragment. This is the whole point of the node.jobTitle— a plain string a model can repeat. Mine says "Freelance Web Developer & Designer".description— one self-contained sentence naming who I am, where I work from, and for whom. Written to survive being quoted alone.worksFor— a reference to/#studio.knowsAbout— the expertise list. Sixteen topics, every one backed by shipped work I can point at.sameAs— the external profiles. More on this below, because it's the load-bearing one.
On knowsAbout, honestly
It's tempting to list every technology you've heard of. Don't. knowsAbout is a claim, and claims that contradict the rest of your site make the whole graph less trustworthy, not more. My rule is that a topic only goes in if there is a project on the site demonstrating it.
The Organization node
The studio node is where verifiability lives. Beyond the obvious name, URL and logo:
foundingDate: "2022"— a date is a fact. "Established for years" is not.founder— points back at/#person. Person points to Organization viaworksFor; Organization points to Person viafounder. The link is deliberately bidirectional, so the relationship resolves whichever node a parser lands on first.address— a real PostalAddress with region and country.sameAs— the profiles plus the Google Business Profile URL.identifier— the Google Knowledge Graph MID, as a PropertyValue.
That last one is worth pausing on.
Mistake one: putting everything in sameAs
sameAs takes URLs of pages that represent the same entity — LinkedIn, GitHub, a Google Business Profile listing, marketplace profiles. It is the corroboration layer, and it matters more than any other property here.
Here's why. Your website claiming you exist and do good work is the weakest possible evidence, because every website claims that. Your website pointing at five external profiles that independently agree is a fundamentally different kind of claim. Assistants weight sources you don't control, and sameAs is you handing over the list of exactly those sources.
A Google Knowledge Graph MID, though, is not a URL. It's a coded value in an external system. Forcing it into sameAs produces a malformed entry — so it belongs in identifier as a PropertyValue with a propertyID naming the system it came from. Same for a company registration number or an ISNI.
Rule of thumb: if you can open it in a browser, it's sameAs. If it's a code, it's identifier.
Mistake two: the dangling @id
This one cost me real time, and it's the most common serious fault I find on client sites.
Once you learn to reference nodes by @id, the tempting next step is to shrink your pages: author: { "@id": ".../#person" } and nothing else, because the full definition lives on the homepage.
That is broken. A parser reading one page has no access to your homepage. It sees a pointer to a node that doesn't exist in the document — a dangling reference. The authorship claim resolves to nothing, and validators frequently pass it without complaint, so you never find out.
The fix is to define what you reference, on every page that references it. On this site the layout does that automatically: before a page's graph is written out, it walks the JSON-LD recording which identifiers are defined versus merely referenced, and repairs any reference left pointing at nothing. Once a system is generating hundreds of pages, catching this by hand is not realistic.
Disambiguating topics with about
The last piece. Tags on a post are free text — "GEO", "AI", "React" — and free text is ambiguous. GEO could be geography. React could be a chemical reaction.
So the tags are run through a lookup table that resolves them into schema.org Thing and Place nodes, each carrying a Wikipedia sameAs:
{ "@type": "Thing",
"name": "Search engine optimization",
"sameAs": "https://en.wikipedia.org/wiki/Search_engine_optimization" } Wikipedia here is not a citation for the reader — it's a public, stable identifier for a concept, of the kind knowledge graphs are already built on. Now "SEO" on my page and "SEO" on some other page are provably the same concept.
Two deliberate constraints. Tags that aren't in the table are silently dropped rather than emitted as raw strings — an unresolvable topic adds nothing and dilutes the ones that resolve. And the list is capped at four per page, because four unambiguous concepts describe a page better than fifteen vague ones.
What I deliberately don't emit
An entity graph is also defined by what you leave out.
There is no AggregateRating anywhere on this site. I have real Google reviews and could put a star rating in my markup, and it would very likely render. I don't, because the number isn't independently verifiable from my own codebase, and self-reported ratings are exactly the kind of claim that erodes trust in everything around them.
There is also no pricing in the schema, because there is no fixed price to state. Inventing a plausible one to fill an Offer node would be a lie with a validator's blessing.
Structured data is a set of assertions about reality. The temptation is always to assert slightly more than is true, and it's the wrong trade.
The honest summary
None of this will raise your rankings, and I'd distrust anyone who says otherwise. What it does is make you unambiguously identifiable — so that when something answers a question on your behalf, it names you correctly instead of hedging or naming a competitor whose facts were easier to read.
Start with three things: one stable @id per real entity, define every node you reference on the page that references it, and fill sameAs with profiles that corroborate you. That's most of the value.
I'm Divyansh Sood. The graph described here is running on this page — open the source and read it. If you'd rather have this implemented in your codebase than explained, it's part of SEO & GEO; the vocabulary around it is sorted out in the acronym guide.