XooCode(){

Schema Diff Tool

Paste your JSON-LD. See exactly what's missing.

Compare your markup against 14 hand-curated schema.org reference examples. Results come back split by Google’s required, recommended, and optional buckets so you know what will block a rich result and what’s just polish. Everything runs in your browser. Your markup never leaves your machine.

Private. Runs entirely in your browser.
Missing required (1)

These disqualify your markup from the Product snippet rich result.

  • offers.price
    "495.00"
Missing recommended (15)

Not blockers, but including these improves rich result quality and eligibility.

  • aggregateRating
    {
      "@type": "AggregateRating",
      "@id": "https://xoocode.com/shop/xootee-classic#rating",
      "ratingValue": "4.5",
      "reviewCount": "2",
      "bestRating": "5",
      "worstRating": "1"
    }
  • aggregateRating.ratingValue
    "4.5"
  • aggregateRating.reviewCount
    "2"
  • gtin13
    "5710911234567"
  • mpn
    "XOO-CLASSIC-1945"
  • offers.hasMerchantReturnPolicy
    {
      "@type": "MerchantReturnPolicy",
      "applicableCountry": "DK",
      "returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
      "merchantReturnDays": "30",
      "returnMethod": "https://schema.org/ReturnByMail",
      "returnFees": "https://schema.org/FreeReturn"
    }
  • offers.itemCondition
    "https://schema.org/NewCondition"
  • offers.priceValidUntil
    "2026-12-31"
  • offers.seller
    {
      "@id": "https://xoocode.com/shop/dunmore-1290"
    }
  • offers.shippingDetails
    {
      "@type": "OfferShippingDetails",
      "shippingRate": {
        "@type": "MonetaryAmount",
        "value": "49.00",
        "currency": "DKK"
      },
      "shippingDestination": {
      ...
  • review
    [
      {
        "@type": "Review",
        "author": {
          "@type": "Person",
          "name": "Dana Crook"
        },
        "datePublished": "2024-11-03",
      ...
  • review.author
    {
      "@type": "Person",
      "name": "Dana Crook"
    }
  • review.reviewRating
    {
      "@type": "Rating",
      "ratingValue": "4",
      "bestRating": "5",
      "worstRating": "1"
    }
  • review.reviewRating.ratingValue
    "4"
  • url
    "https://xoocode.com/shop/xootee-classic"
Missing optional (46)

Extras XooCode's example demonstrates. Add only if they make sense for your content.

  • aggregateRating.bestRating
    "5"
  • aggregateRating.worstRating
    "1"
  • audience
    {
      "@type": "PeopleAudience",
      "suggestedGender": "unisex",
      "suggestedMinAge": "16"
    }
  • audience.suggestedGender
    "unisex"
  • audience.suggestedMinAge
    "16"
  • award
    "Scandinavian Design Finalist 2024"
  • category
    "Apparel > T-Shirts > Graphic"
  • color
    "Natural Bone"
  • isRelatedTo
    {
      "@type": "Product",
      "name": "XooShoes Dunmore Edition",
      "url": "https://xoocode.com/shop/xooshoes-dunmore"
    }
  • isRelatedTo.name
    "XooShoes Dunmore Edition"
  • isRelatedTo.url
    "https://xoocode.com/shop/xooshoes-dunmore"
  • isSimilarTo
    {
      "@type": "Product",
      "name": "XooPremium Hooded Long Sleeve",
      "url": "https://xoocode.com/shop/xoopremium-hoodie"
    }
  • isSimilarTo.name
    "XooPremium Hooded Long Sleeve"
  • isSimilarTo.url
    "https://xoocode.com/shop/xoopremium-hoodie"
  • manufacturer
    {
      "@id": "https://xoocode.com#organization"
    }
  • material
    "100% Organic Cotton"
  • offers.hasMerchantReturnPolicy.applicableCountry
    "DK"
  • offers.hasMerchantReturnPolicy.merchantReturnDays
    "30"
  • offers.hasMerchantReturnPolicy.returnFees
    "https://schema.org/FreeReturn"
  • offers.hasMerchantReturnPolicy.returnMethod
    "https://schema.org/ReturnByMail"
  • offers.hasMerchantReturnPolicy.returnPolicyCategory
    "https://schema.org/MerchantReturnFiniteReturnWindow"
  • offers.shippingDetails.deliveryTime
    {
      "@type": "ShippingDeliveryTime",
      "handlingTime": {
        "@type": "QuantitativeValue",
        "minValue": "0",
        "maxValue": "1",
        "unitCode": "DAY"
      },
      ...
  • offers.shippingDetails.deliveryTime.handlingTime
    {
      "@type": "QuantitativeValue",
      "minValue": "0",
      "maxValue": "1",
      "unitCode": "DAY"
    }
  • offers.shippingDetails.deliveryTime.handlingTime.maxValue
    "1"
  • offers.shippingDetails.deliveryTime.handlingTime.minValue
    "0"
  • offers.shippingDetails.deliveryTime.handlingTime.unitCode
    "DAY"
  • offers.shippingDetails.deliveryTime.transitTime
    {
      "@type": "QuantitativeValue",
      "minValue": "1",
      "maxValue": "3",
      "unitCode": "DAY"
    }
  • offers.shippingDetails.deliveryTime.transitTime.maxValue
    "3"
  • offers.shippingDetails.deliveryTime.transitTime.minValue
    "1"
  • offers.shippingDetails.deliveryTime.transitTime.unitCode
    "DAY"
  • offers.shippingDetails.shippingDestination
    {
      "@type": "DefinedRegion",
      "addressCountry": "DK"
    }
  • offers.shippingDetails.shippingDestination.addressCountry
    "DK"
  • offers.shippingDetails.shippingRate
    {
      "@type": "MonetaryAmount",
      "value": "49.00",
      "currency": "DKK"
    }
  • offers.shippingDetails.shippingRate.currency
    "DKK"
  • offers.shippingDetails.shippingRate.value
    "49.00"
  • productID
    "xoo:XOO-TEE-CL-001"
  • releaseDate
    "2024-09-01"
  • review.author.name
    "Dana Crook"
  • review.datePublished
    "2024-11-03"
  • review.name
    "Comfortable and conversation-starting"
  • review.reviewBody
    "Picked this up at the Dunmore store after reviewing the shop itself last year. The print holds up after many washes and the cotton is genuinely soft. Love that the graphic tells a story."
  • review.reviewRating.bestRating
    "5"
  • review.reviewRating.worstRating
    "1"
  • weight
    {
      "@type": "QuantitativeValue",
      "value": "220",
      "unitCode": "GRM"
    }
  • weight.unitCode
    "GRM"
  • weight.value
    "220"
Properties in your markup not in XooCode's example (1)

Informational only. This isn't wrong. Schema.org has over 1400 properties and our example can't demonstrate all of them. Anything sensible you've added is yours to keep.

brand.name

How to use the Schema Diff Tool

The tool is built around a single workflow: paste your existing JSON-LD, pick the schema type you believe it represents, read the diff, fix the missing properties in your own source. It takes about ninety seconds from first paste to a fully-classified result.

  1. 1

    Pick a reference example

    Use the Reference example dropdown to choose which of XooCode’s 14 hand-curated examples you want to diff against. If you’re marking up a product page, pick Product. If you’re marking up a recipe, pick Recipe. The reference is the shape you’re aiming for; the diff tells you how far away you are.
  2. 2

    Paste your JSON-LD

    Paste the JSON-LD you’re currently serving on the page. You can paste with or without the <script type="application/ld+json"> wrapper — the tool strips that automatically. HTML-encoded characters (&lt;, &quot;) from a WordPress export or an HTML source view are also decoded.
  3. 3

    Read the four result sections

    The result lands in four collapsible sections: Missing required(red — these will block your rich result), Missing recommended(amber — these hurt quality but don’t disqualify you), Missing optional(grey — add only if they make sense), and Extra properties(your markup has things the reference doesn’t — not wrong, just informational).
  4. 4

    Click Why? for the rationale

    Every required and recommended row has a Why? button that pops a tooltip explaining the rich result that property governs and links to the exact Google Search Central docs page so you can read the requirement in context. This is the part that turns the diff from a checklist into a learning tool.
  5. 5

    Fix your source and re-paste

    The tool doesn’t edit your markup for you on purpose. You paste, read, fix in your own template or CMS, paste again. Two or three iterations and you end up with markup that matches our reference shape and passes Google’s Rich Results Test.

What the tool actually checks

The diff runs on property paths, not values. For every key in your JSON-LD object it produces a dotted path like offers.price or aggregateRating.reviewCount, builds the same set of paths for the reference example, and computes the two set differences: what the reference has that you don’t (missing) and what you have that the reference doesn’t (extra).

Arrays collapse. An offers key whose value is an array of Offer objects produces one path per unique sub-key across all elements, not one path per element. This matches how Google’s rich result eligibility works: the first valid offer in an array is enough to qualify, so the diff doesn’t punish you for having one or ten.

Every missing path is then classified against the reference example’s propertyStatus map, which is hand-authored from the current Google Search Gallery requirements for that schema type. Paths not in either the required or recommended list default to optional.

How the diff works under the hood

Nothing about the Schema Diff Tool is magical. It’s about fifty lines of TypeScript wrapped in a React textarea. The entire algorithm lives in a pure function called computeDiff that takes a string (your markup) and a reference example object, and returns a discriminated union describing the result.

Step 1 — parse and strip

We strip the <script type="application/ld+json"> wrapper if present, decode any HTML entities (&lt;, &quot;, &amp;), and run the result through JSON.parse. If parsing fails we return an error state and the UI renders the parse message inline instead of a diff.

Step 2 — collect paths

We walk the parsed object depth-first, building a sorted set of dotted paths for every non-@-prefixed key. @context, @type, @id, and any other JSON-LD keyword is skipped because those are syntax, not content. The walker collapses arrays: an array of Offers produces one set of paths per unique sub-key across all elements.

Step 3 — set difference

We compute missing = example \ user and extra = user \ example as plain JavaScript Sets. If the intersection is empty we assume you pasted the wrong schema type and render the mismatch banner instead of a diff. This heuristic catches the most common paste error — pasting a Recipe schema while the Product reference is selected.

Step 4 — classify missing paths

For every path in the missing set we look up its status against the reference example’s hand-curated propertyStatus map and push it into one of three buckets: required, recommended, or optional. The map is committed to source alongside the example JSON so reviewers can audit both together.

Step 5 — render with rationale

The UI renders each bucket as a collapsible <details> section with a Why? popover on required and recommended rows. The popover links to the specific Google Search Central docs page for the rich result that property governs, so the tool doubles as a teaching interface instead of just a checklist.

Why we built this tool

Google’s Rich Results Test is the canonical validator. Schema.org’s Schema Markup Validator is the canonical vocabulary checker. Both are excellent tools. Neither of them answers the question most authors actually have, which is “what properties should I be including that I’m not?”.

The validators tell you whether what you have is valid. They don’t tell you whether what you have is complete. A Product schema with only name and @type is technically valid — it will parse without error. It’s also useless. The Rich Results Test will flag it as ineligible but won’t tell you what a “good” Product schema looks like at the other end.

That’s the gap the Schema Diff Tool fills. It uses our hand-authored reference examples as the comparison baseline and shows you the delta. The output is a concrete, actionable list of property names you can search for in your codebase. It’s a first step, not a replacement: once the diff is clean, run the result through the Rich Results Test to catch value-level mistakes.

Building it was also an excuse to make the reference examples earn their keep. An example that’s only consumed by readers of a single page is a document; an example that’s consumed by a diff engine becomes a shape contract. Every property we put in a reference is now a property we’re willing to recommend to every user of the tool — which raised the bar on the examples themselves.

What this tool isn't

Knowing what a tool doesn’t do is as important as knowing what it does. The Schema Diff Tool is deliberately narrow.

It IS a shape diff

It compares the set of property paths in your markup against a reference. Output is a categorized list of what you're missing and what you have extra.

It is NOT a validator

It doesn't check whether your property values are well-formed. A price of 'free' will pass the diff as present even though Google requires a number. Run the Rich Results Test after.

It IS a teaching tool

Every required and recommended row links to the exact Google docs page for the rich result that property governs. You learn the vocabulary while you fix your markup.

It is NOT a crawler

It doesn't fetch pages for you. Paste your JSON-LD in yourself. We never accept URLs as input, never call external services, and never send your markup off your machine.

It IS private

Runs entirely in your browser. No server round-trip, no analytics on the diff content, no logging. You can verify in your network tab.

It is NOT a generator

It won't write markup for you. If you want to generate Recipe, Product, or SoftwareApplication schema from a form, use the XooCode builders instead.

Authoritative sources this tool references

The tool’s rationale popovers and the reference examples themselves are built on top of primary sources. If you want to verify anything the diff tells you, these are the documents to check.

  • schema.org — the canonical vocabulary. Every XooCode example references the schema.org type definition so you can read the authoritative meaning of every property.
  • Google Search Gallery — the index of every rich result type Google supports, with per-type required and recommended property lists. Everything in a XooCode propertyStatus map is sourced from this gallery.
  • Google Rich Results Test — paste the same markup there after the diff is clean to catch value-level errors the shape diff can’t see.
  • Schema Markup Validator — schema.org’s own validator, maintained independently from Google. Useful when you want vocabulary conformance feedback without Google’s rich result rules layered on top.
  • JSON-LD 1.1 Specification — the W3C recommendation behind the notation. Useful reference when you start hitting advanced features like @id, @graph, and context reuse.