Findings · 2026-08-20 · By VSNARY | Emmanuel Orta · 0 views
Duplicate @id in JSON-LD: one node parsed twice, not two businesses
An @id is the identifier. Two records carrying the same one are, by definition, the same record appearing twice.
An entity collision is a real problem. If two business records on one page declare the same phone number, the same coordinates, or the same identifier, a retrieval system has two candidates for one identity and no way to choose. It is invisible to every schema validator — the markup is perfectly valid — and it is exactly the kind of thing worth reporting.
So we built a check for it: look across the business records in a page’s JSON-LD and flag any two that claim the same identity.
On one site it reported four collisions across two nodes, including a shared phone number and a shared @id. We wrote that up as a genuine defect.
The tell #
Two records sharing an @id is not two businesses colliding. An @id is the identifier. Two records carrying the same one are the same record, appearing twice.
The check had found a duplicate of a single node and compared it against itself. Every field matched, because every field was the same field. Four “collisions” from one business.
Reading the live page settles it in one command:
business nodes in live HTML: 1 their @ids: ['https://example.com/#business'] distinct @ids: 1
One node. One identifier. The page was never wrong. Our extraction had read the same node twice and compared it against itself.
The fix, and why it is not “ignore @id collisions” #
The naive repair is to stop treating a shared @id as a collision. That would also delete the genuine case: two different businesses both handed the same identifier by a careless template. That is real, and worth catching. We corrected the check so one record read twice counts once, while two different records sharing an identifier still fire.
Checked across four sites afterwards, and the important result is the negative one: a site with two genuinely distinct business nodes still reports them as two, and still reports no collision between them. The dedupe did not suppress a real finding — which is the only evidence that a fix like this hasn't just turned the check off.
What the live page actually declares #
| Read from the live HTML | Value |
|---|---|
| Business nodes | 1 |
| Their @ids | https://example.com/#business |
| Distinct @ids | 1 |
Two records carrying an identical @id are the same record twice. They are never two businesses.
The process failure underneath it #
The part worth keeping is not the bug. It is what “verified” meant when we announced it.
We had verified that the check fired and that the report’s own self-checks passed. All of that was true. None of it was evidence that the finding was correct, because every one of those checks ran against our own output.
Confirming the accusation required the one thing we had not done: fetching the accused page and counting the nodes by hand.
For a tool whose whole proposition is that it reports what is actually there, an unverified accusation is the worst possible defect — worse than missing the problem, because a false finding sends someone to edit markup that was already correct.
The rule we now apply: for any finding that accuses a site of something, verification includes independently fetching that site and confirming the accusation by hand. Not the code path. The claim.
Every figure above came out of this scanner.
Point it at your own domain and see the same measurements, free.
The main product
Found this on your own site? We fix it for $749.
Scan free to see where you stand. The fix is one site, every finding implemented and re-measured, with a sealed before and after.
Questions this post answers
Are two JSON-LD nodes with the same @id a collision?
No. Under RDF two nodes with one @id are one subject described twice, and their properties merge. A collision is two different entities sharing a value that should identify one, such as the same url with different @ids or none.
How does the scanner treat duplicates now?
It counts one record read twice as one record. Any finding that accuses a site of a collision is verified by fetching the page and counting by hand.
Related findings
Comments
Comments are read before they appear. Nothing is published automatically, and no account is needed.
Writing about this? Facts, live figures and marks — every number on that page is dated and traceable to a scan.