10 JSON-LD bugs I find in every commerce audit (and what they cost)
Field-level JSON-LD bugs that fail silently across 45K+ PDP catalogs. Each one mapped to the rich result it kills, the AI engine that drops you, and the dollar cost I model for clients.
I've audited enough commerce sites this year to see the same ten JSON-LD bugs over and over. Schema validators say green. Rich Results Test says eligible. Yet the Product rich result never appears in Google Shopping, ChatGPT cites a competitor for queries the brand should own, and the team can't tell which fix moves the needle.
This is the catalog. Each bug includes the failure mode, the engines it breaks, and the rough revenue band I project against a 45,000 PDP catalog at $80 AOV with 2.1% baseline conversion. Numbers are illustrative, not promises. The point is the math, not the figure.
1. Organization @id drifts per page
The most common bug. The CMS emits an Organization JSON-LD block on every template, but the @id is set to the page URL each time. Validators pass because each block is internally consistent. AI engines see fifty thousand separate organizations with the same name. Brand entity merge fails. Citations collapse.
Fix: pin Organization to a single stable @id like https://yoursite.com/#organization. Reference it everywhere.
Revenue band: high. AI citation share across all five engines drops by 30 to 60 percent until resolved. (How each engine handles @id differently is documented in How AI answer engines actually resolve your @graph.)
2. Product entity references brand by nested object instead of @id
{
"@type": "Product",
"name": "Acme Widget",
"brand": { "@type": "Brand", "name": "Acme" }
}
That looks fine. It validates. ChatGPT's parser treats every Product on every PDP as belonging to a different Brand entity that happens to share a name. Across a 45K catalog you get 45K Brand entities. Knowledge graph fragments.
Fix: hoist Brand to a top-level entity in your @graph with a stable @id, then reference it from every Product:
{ "@type": "Brand", "@id": "https://yoursite.com/#brand", "name": "Acme" }
{ "@type": "Product", "name": "Acme Widget", "brand": { "@id": "https://yoursite.com/#brand" } }
Revenue band: medium-high. Affects long-tail brand-plus-product queries where you should be the obvious answer.
3. Missing offers.priceValidUntil
Google deprecates Offer rich results that go stale. Without priceValidUntil, the rich result silently disappears from Shopping after 90 days even if the price never changed. Most teams assume Google is still rendering them.
Fix: emit priceValidUntil as a date one year out, refreshed on every page render. Cheap to implement, immediate impact.
Revenue band: medium. Pure click-through-rate loss on category-level queries where the rich result was the differentiator.
4. AggregateRating with reviewCount of 0 or 1
Google requires at least three reviews to render a star rating. Anything below that is not just suppressed, it's a rich result eligibility violation that can affect the page's broader trust signals. Sites that emit AggregateRating with reviewCount: 1 are explicitly worse off than sites that emit nothing.
Fix: gate AggregateRating output behind a server-side check for reviewCount >= 3.
Revenue band: low individually, high in aggregate. Long tail of PDPs with one or two reviews quietly losing rich results across the catalog.
5. Image URLs that 404 or redirect
Google fetches the JSON-LD image. If it 404s, redirects, or returns non-image content, the entire Product rich result is suppressed. Common causes: the schema generator pulls from a CDN path that's been deprecated, or the image was deleted but the JSON-LD wasn't regenerated.
Fix: validate image URLs at schema-emit time. RankLabs flags this as a hard error per template, not per page, so the report points at the generator function not 12,000 individual PDPs.
Revenue band: high on the affected templates. Often hits 20 to 40 percent of a catalog when it hits.
6. SKU and gtin13 missing or duplicated across variants
Google's Merchant Center deduplicates by gtin13. If your variants share a GTIN by mistake, only one variant gets indexed. If the GTIN is missing entirely, AI shopping engines (ChatGPT plugins, Perplexity Shopping) can't match your inventory against price comparison results.
Fix: enforce GTIN uniqueness at the database layer, emit only when set. Emit sku as the stable per-variant identifier.
Revenue band: high on multi-variant catalogs. Apparel, beauty, and home are the worst hit.
7. BreadcrumbList items reference inconsistent URLs
Half the breadcrumbs use https://yoursite.com/category, the other half use https://yoursite.com/category/. Google's breadcrumb merge fails. The blue navigation breadcrumb in search results disappears even though everything technically validates.
Fix: emit canonical URLs only. Trailing slash policy enforced at the @id constructor.
Revenue band: low individually, but breadcrumbs disappearing across the category tree compounds into measurable CTR loss.
8. JSON-LD injected client-side after hydration
The schema only exists in the rendered DOM, not the initial HTML response. Most AI engine fetchers (ChatGPT's, ClaudeBot, PerplexityBot) don't execute JavaScript. They see no schema at all. Validators run on the rendered DOM, so the team thinks it's fine.
Fix: emit JSON-LD server-side in the initial HTML response. Tag manager templates and React-only schema components are the recurring offenders.
Revenue band: catastrophic. AI engines cite zero of your pages until this is fixed. I find this on roughly one in three engagements. The post-fix half-life of well-architected schema is 60 to 90 days without monitoring, which is why CI gates are non-negotiable. (Schema decays. Here's the half-life I've measured.)
9. Review entities with no itemReviewed @id reference
Each Review block has itemReviewed set to a nested Product object instead of an @id reference back to the canonical Product entity in the page graph. Result: review signal doesn't aggregate into the Product the way Google expects, and AggregateRating gets built from the wrong sample.
Fix: every Review's itemReviewed is { "@id": "/products/123#product" }, never a nested object.
Revenue band: medium. Affects rich result eligibility on PDPs with strong review programs.
10. ItemList on category pages with no positions
Category page emits an ItemList without position numbers on each ListItem. Google can't construct the carousel rich result. The fix is one line per item, but the bug is everywhere because most ORM-backed schema generators forget to set position.
Fix: enumerate items with their 1-indexed position.
Revenue band: medium. ItemList carousels are increasingly the way Google AI Overviews surface category-level answers.
What to do with this list
If you run a commerce site, point a schema crawler at your top ten templates and check each of these ten bugs. Most teams find at least four. The fix per bug is small. The compounding cost is not.
If you want me to do this for you, the Audit is the engagement. RankLabs runs all ten checks plus another forty across the schema graph, breadcrumb chain, AI engine emulation, and crawlability layer, then I model the per-fix revenue impact and ship a 90-day prioritized roadmap. The Sprint is what executes the roadmap with CI gates that keep the fixes shipped.