Skip to content
ZERONE
Natrag na uvide
Arhitektonski patterni2026-07-06 · 7 min čitanja

How two domains become one Google entity: JSON-LD @id cross-references explained

We run zer0one.codes (studio) and zer0onelab.com (cloud product). For Google, they were long two separate companies — even though it's the same GmbH. The fix is a single line per JSON-LD node: stable @id URIs plus parentOrganization / subOrganization references. Google's Knowledge Graph then resolves both domains to the same entity.

We have one ZER0ONE company and two domains. Studio consulting on zer0one.codes, the cloud render product on zer0onelab.com. Both are legally the same company. For Google, they were long two separate entities.

The problem isn't duplicate content — the sites have completely separate content. The problem is entity resolution: Google sees on zer0one.codes an Organization named "ZER0ONE" and on zer0onelab.com an Organization named "ZER0ONE Lab". Two similar names, no explicit connection signals. Google's default heuristic is: "probably two similar companies, no relationship."

That leads to split rankings: when someone searches "ZER0ONE", they see both sites, but the trust score is split across two small entities instead of consolidating on one bigger company.

The technical solution

Schema.org's @id is a stable URI that acts as an entity identifier. Two nodes with the same @id are the same entity to search engines — regardless of which domain they sit on.

We restructured our JSON-LD so the master Organization on zer0one.codes carries subOrganization: [{ "@id": "https://zer0onelab.com/#organization" }] and the Lab node on zer0onelab.com carries parentOrganization: { "@id": "https://zer0one.codes/#organization" }. Both references match, no contradictions → both nodes get consolidated into one entity in the Knowledge Graph, with a master/sub relationship.

Side effect on author entity

We do the same for the founder Person. Michael is referenced on both domains (as author on BlogPosting, as founder on Organization). Without @id, Google sees two "Michael Jajagin" persons with potentially different signals. With @id: "https://zer0one.codes/#founder", all authorship across both domains is recognized as the same person. E-E-A-T trust score consolidates on one person.

LocalBusiness cascade

We extended the Organization @type to ["Organization", "LocalBusiness", "ProfessionalService"]. Unlocks Local Pack rankings. For a DACH-focused consulting studio, no CTO in Munich searches Google Maps for a Bogojevo studio — but the cascade is what matters. LocalBusiness signals Google "this is a real company with a physical address, not a shell for SEO." Higher-order trust signal.

The bug we found

First deploy showed the Lab domain emitting the wrong WebSite @id — the Studio URL. Root cause: render/page.tsx was configured force-static. Static generation runs without HTTP context, headers().get("host") returns null, our isLabHost() check always landed in the Studio branch.

Structural fix: host-specific JSON-LD nodes (WebSite per domain, LabOrg definition) moved out of the root layout into the respective landing pages. Layout now emits only shared entities that are identical on both hosts. Domain-specific JSON-LD lives on the domain-specific page.

When it's worth doing

Overhead if you only have one domain. Worth it when: you run one company across two or more domains (consulting + product, or multi-brand), author bylines span multiple domains, or you rank in a niche where entity confidence is critical.

Meta-lesson

Google's Knowledge Graph isn't a ranking system — it's an entity-resolution system that affects rankings. If you run one company across multiple domains and don't explicitly say "same company", Google decides heuristically. Explicit @id cross-references put your own entity confidence on a solid foundation.

For studios doing multi-domain setups: this trust-chain is part of ZER0ONE Studio Engineering Services. We just went through it, we know where it goes wrong.

Sličan izazov i kod vas?

Vjerojatno smo već vidjeli nešto slično. Razgovarajmo.

Započnite razgovor