A restrained markup model in which every node, @id, and relationship agrees with the page's visible, verifiable claims.

Each template gets one page role and one primary entity. We remove duplicate or unsupported nodes, then validate the rendered production output. The draft isn't the acceptance state. Technical SEO and engineering leads whose templates each generate their own version of the same entity in structured data.

Every JSON-LD block on the site says the same thing the page and the approved graph already say, checked on the live pages.

Figure slotting a labeled node into a large node-and-edge lattice representing schema markup

Some of the 500+ brands we've worked with

See all references
  • GE
  • Silverline
  • AVVA
  • Lezzet
  • Ekol
  • Yolcu360

Five steps from the approved graph to a validated, deployed template.

How we hold ourselves to it

  • One @id per template
  • Visible-content parity
  • Production gets checked
  • No invented relationships
  1. Map templates to entity roles

    Every page gets one documented role and one permitted slice of the approved public graph before any markup is written.

    A template-to-entity map with the primary @id and the graph fragment each page is allowed to express.

    AI assist
    Agent inventories representative templates, their visible entities, and current graph fragments, and proposes an expected primary identifier for each.
    Human gate
    Content, entity, and technical owners approve each template's role and the graph boundary it's allowed to touch.
  2. Reconcile identifiers with the canonical graph

    Current identifiers and canonical URLs get checked against the register before any relationship gets attached to them.

    An identifier reconciliation register with merge, retain, or replace decisions for every @id.

    AI assist
    Agent diffs rendered identifiers against the canonical graph and groups duplicate or conflicting nodes by template.
    Human gate
    The entity owner and an engineer approve merge, retain, or replace for every identifier that doesn't already match.
  3. Verify every relationship against evidence

    Each proposed relationship gets checked for direction, an approved graph edge, and visible-page support before it ships.

    An approved relationship register that records every unsupported edge as an explicit rejection.

    AI assist
    Agent links every proposed relationship to visible page evidence and an approved edge, flagging anything reversed, inferred, or sensitive.
    Human gate
    Domain, privacy, and legal owners approve relationship direction and reject anything unsupported or prohibited.
  4. Remove duplicate and unsupported markup

    Duplicate nodes and relationships the visible page can't support get traced and removed in a sequence that doesn't break dependent templates.

    A defect map with a safe removal sequence and affected-template dependencies.

    AI assist
    Agent locates duplicate nodes and unsupported properties and drafts a removal sequence with dependencies flagged.
    Human gate
    Engineering, content, and entity owners approve the removal scope, migration order, and rollback plan.
  5. Validate production syntax and parity

    We parse the live JSON-LD and compare identifiers, edges, and visible facts on representative and edge-case pages after release.

    A syntax, parity, and regression report from the actual deployed pages.

    AI assist
    Agent renders production candidates and runs syntax, parity, direction, and regression checks against the approved fixtures.
    Human gate
    An independent technical SEO reviewer approves only output that passes the original graph and visible-parity rules.

Engineering gets one implementable template specification, along with a metric showing whether live pages still match the approved model.

  • Entity markup audit

    A rendered-page audit of duplicate identities, conflicting @id values, and edges the visible page doesn't support.

    Accepted when

    What to remove, reconcile, or retain before any new relationship markup goes live.

    Cadence: Duplicates flagged

  • Schema relationship specification

    Canonical nodes, directed edges, provenance, and explicit exclusions, mapped by template.

    Accepted when

    One approved graph contract content and engineering both build from, without claiming an external knowledge-panel effect.

    Cadence: Graph contract set

  • Reusable template implementation plan

    Ownership, examples, and safe reference behavior included, so an editor can't accidentally recreate the duplication problem.

    Accepted when

    Graph fragments mapped to CMS fields and components, so new pages reference canonical entities without cloning them.

    Cadence: Fields mapped

  • Graph parity rate

    Measured on the live deployment, with the page set and the pass rule both agreed before we compare anything, so a passing draft that regresses in production doesn't get counted as a win.

    Accepted when

    The share of reviewed production pages where the approved graph, the visible page, and the rendered JSON-LD all agree.

    Cadence: Production checked

  • Parity fixtures wired into your release pipeline

    A release reruns the check when a template, identifier, or relationship changes. A previous pass isn't evidence that the markup stayed stable.

    Accepted when

    The fixture set that reruns the parity check on every affected release, automated wherever the template pipeline allows it.

    Cadence: Release-triggered

Two templates emit two different @id values for the same organization, and the JSON-LD claims a relationship the visible copy never mentions.

A good fit when

  • Every template invents its own markup — The about page, the product page, and the author bio each generate their own Organization node.
  • The graph and the page disagree — A JSON-LD block asserts a "parentOrganization" relationship or a job title that the visible text on the same page never states.
  • Identifiers drift across locales or templates — The English page and its localized variant use two canonical URLs, splitting one node into two.
  • An approved entity graph already exists — This method implements an agreed canonical model, and a missing one goes to Entity Relationship Mapping first.
  • Each template resolves to one primary @id — It also carries a documented purpose and a primary entity taken from the approved graph.
  • Visible content must support every property — A fact belongs in JSON-LD only when a reader can verify it from the page's visible text.
  • The deployed output needs its own check — A build step, a caching layer, or a CMS default can quietly change what ships. We check the live production output.

Better handled as other work when

  • You want a guaranteed rich result — Correct markup makes a page eligible to be understood, and it forces no rich result, panel, or AI citation.
  • Invented relationships are prohibited — Syntactically valid markup still fails when its meaning is false. Leaving the field empty is safer than inventing a value.
  • You want the markup to guarantee an outcome — Markup earns eligibility, and a well-formed JSON-LD block still cannot manufacture a real relationship.
  • Schema App

    authors the JSON-LD itself, tied to the one approved graph so duplicate nodes can't slip in

  • Schema.org Validator

    the vendor-neutral syntax check, separate from any one engine's own rules

  • Google Rich Results Test

    the live-parity check on rendered production output, not the draft

A current template and its rendered markup are enough to start. Zeo traces each block to its approved entity, flags unsupported properties, and checks the production result.
Validate your JSON-LD

Markup makes a page eligible to be understood accurately by machines. It can't create a real-world relationship or determine how an external system displays one.