Structured Data Errors

Ecommerce structured data
validation errors — find and fix

The most common structured data errors that block AI shopping agents and Google product rich results — with exact error messages, root causes, and Shopify-specific fixes for every error type.

TL;DR The top 3 product schema errors blocking AI agents: missing price or priceCurrency in Offers, missing availability URL (using plain text instead of full schema.org URI), and AggregateRating with ratingCount=0. Fix these first — they account for ~70% of Product rich result failures on Shopify stores.

Where to find your structured data errors

Three tools matter for diagnosing structured data errors. Use them in sequence:

  1. CatalogScan — Paste your store URL for an automated scan of your live structured data. Shows missing fields, invalid values, and AI agent compatibility score across your product pages. Run a free scan →
  2. Google Rich Results Test — Tests a single URL. Shows errors and warnings with exact property paths. Use this to confirm fixes on individual PDPs. Note: uses Google's rendering infrastructure, not live Googlebot — for production truth, use Search Console.
  3. Google Search Console → Rich Results — Search Console's Enhancements tab shows aggregate error counts across all indexed pages. This is the authoritative view of what Google actually sees. Individual page errors appear under URL Inspection.

Critical errors (block rich results entirely)

Error 1: Missing required offer properties

Error message: "Missing field 'price'" or "Missing field 'priceCurrency'"

Root cause: The Offer block inside your Product JSON-LD is missing the price and/or priceCurrency properties. This is required for Product rich results and for AI agent price extraction.

Broken pattern:

{
  "@type": "Product",
  "name": "Blue Sneaker",
  "offers": {
    "@type": "Offer",
    "availability": "https://schema.org/InStock"
    // ← missing price and priceCurrency
  }
}

Fix:

{
  "@type": "Product",
  "name": "Blue Sneaker",
  "offers": {
    "@type": "Offer",
    "price": "89.00",
    "priceCurrency": "USD",
    "availability": "https://schema.org/InStock"
  }
}

Shopify Liquid fix: In sections/product-template.liquid (or your theme's product JSON-LD block), ensure the price output uses {{ product.price | money_without_currency | remove: ',' }} and the currency uses {{ cart.currency.iso_code }}.

Error 2: Invalid availability value

Error message: "Invalid value for field 'availability'"

Root cause: Using plain text values ("in stock", "InStock") instead of the full schema.org URI. Google and AI agents require the full URL format.

Broken pattern:

"availability": "in_stock"         // ← Google Merchant Center format, not schema.org
"availability": "InStock"          // ← close but missing https://schema.org/ prefix
"availability": "in stock"         // ← plain text, invalid

Fix:

"availability": "https://schema.org/InStock"
"availability": "https://schema.org/OutOfStock"
"availability": "https://schema.org/PreOrder"
"availability": "https://schema.org/LimitedAvailability"

Error 3: Price is zero or missing currency

Error message: "Value '0' is out of range for field 'price'" or rich results suppressed silently

Root cause: Free products or mispriced products with price: "0" are treated as errors. Also: using money_with_currency in Liquid outputs "USD29.99" or "$29.99" — both fail schema.org price validation (must be numeric only).

// Broken: Liquid output includes currency symbol
"price": "{{ product.price | money }}"
// → outputs "$89.00" ← INVALID

// Fix: strip currency formatting
"price": "{{ product.price | money_without_currency | remove: ',' }}"
// → outputs "89.00" ← VALID

Error 4: AggregateRating with zero reviews

Error message: "Value '0' is out of range for field 'ratingCount'"

Root cause: The AggregateRating block is present on all product pages (usually added by a review app theme block) even when a product has no reviews yet. Google requires ratingCount to be at least 1.

Fix in Liquid:

{% if product.metafields.reviews.rating_count > 0 %}
"aggregateRating": {
  "@type": "AggregateRating",
  "ratingValue": "{{ product.metafields.reviews.rating | round: 1 }}",
  "reviewCount": "{{ product.metafields.reviews.rating_count }}",
  "bestRating": "5",
  "worstRating": "1"
},
{% endif %}

Warnings (reduce rich result quality and AI agent confidence)

WarningProperty missingImpactFix
"Missing recommended field 'image'"Product.imageNo product image in rich result; lower AI agent confidence for visual queriesAdd "image": "{{ product.featured_image | img_url: 'master' | prepend: 'https:' }}"
"Missing recommended field 'description'"Product.descriptionAI agents can't match query intent to product use casesAdd "description": "{{ product.description | strip_html | truncate: 500 | escape }}"
"Missing recommended field 'sku'"Offer.skuReduces product identity matching; GTIN is preferred but SKU is fallbackAdd "sku": "{{ product.selected_or_first_available_variant.sku | escape }}"
"Missing recommended field 'brand'"Product.brandBrand queries ("Nike running shoes") may not surface this productAdd "brand": { "@type": "Brand", "name": "{{ product.vendor | escape }}" }
"Missing recommended field 'gtin'"Offer.gtinGoogle's product knowledge graph match is weaker; AI Mode ranking reducedAdd {% if variant.barcode != blank %}"gtin": "{{ variant.barcode }}"{% endif %}
"Missing recommended field 'priceValidUntil'"Offer.priceValidUntilAI agents can't determine if sale price is still valid; may suppress sale productsAdd from metafield when running a sale; omit entirely for permanent prices

Shopify-specific structured data bugs

Dawn/Debut themes: JSON-LD only on first page load

Some older Shopify themes inject product JSON-LD via JavaScript (not server-rendered). Google's Rich Results Test (which renders JavaScript) may pass, but Googlebot's light crawl mode and AI agent crawlers (which don't fully execute JS) will see no structured data. Verify by checking the page source (Ctrl+U) — JSON-LD should be present in the raw HTML, not added by document.createElement('script').

Fix: Move JSON-LD to a Liquid block in the <head> of the product template so it's server-rendered.

Multiple conflicting Product blocks

A common issue when installing review apps (Yotpo, Okendo, Judge.me) alongside SEO apps (SEO Manager, Smart SEO) — both inject Product JSON-LD independently. The result is two @type: Product blocks on the same page with different prices, ratings, or availability values. Google and AI agents may use either block, creating inconsistency.

Fix: Disable JSON-LD output in one of the apps. Prefer keeping the SEO app's output and feeding review data into it via metafields, or use the review app's merge mode if available.

Variant price in JSON-LD doesn't update on variant select

If your theme renders JSON-LD server-side with the default variant price but the user selects a different variant (different price), the structured data never updates. For AI agents crawling the PDP, they see the default variant price regardless of which variant is canonically featured.

Fix: Ensure your server-rendered JSON-LD uses the canonical (default) variant price. If variant prices differ significantly, consider adding a priceRange note in the description or implement AggregateOffer for multi-variant products.

Validation error checklist for Shopify stores

CheckToolPriority
price and priceCurrency present and numeric (no $ or currency symbols)Rich Results TestCritical
availability uses full schema.org URI (https://schema.org/InStock)Rich Results TestCritical
AggregateRating only present when ratingCount ≥ 1Rich Results TestCritical
JSON-LD is server-rendered (present in page source, not JS-injected)View SourceCritical
No duplicate Product JSON-LD blocks from multiple appsView Source countHigh
image, description, brand presentRich Results TestHigh
gtin / sku presentRich Results TestMedium
Search Console Enhancements report shows 0 Product errorsSearch ConsoleOngoing

Use CatalogScan to run an automated structured data audit across all your product pages — it checks all of the above and scores your store's overall AI agent readiness in one scan.

Related: Shopify structured data testing · Product schema markup guide · Shopify schema markup

Frequently asked questions

What's the difference between a structured data error and a warning?

Errors block rich results entirely — they indicate missing required properties or invalid values. Warnings flag recommended properties — the rich result can still appear but quality suffers. For AI agents, treat price, availability, and image warnings as near-critical since those agents rely heavily on them even when Google only flags them as optional.

Why does my Shopify store pass the Rich Results Test but not show product rich results?

The test uses Google's rendering servers, not live Googlebot. For the authoritative view, check Google Search Console → URL Inspection. Other causes: domain too new (takes 3–6 months), prior structured data policy violation, or product has been out of stock for an extended period.

How long after fixing errors do rich results recover?

Google typically re-crawls within 1–7 days after requesting re-indexing via Search Console URL Inspection. Rich results appear or recover within a day after a successful re-crawl. AI agent (ChatGPT, Perplexity) recovery takes weeks — they crawl on their own schedule and don't respond to IndexNow.

Can I have too much structured data on a page?

Yes — Google penalizes structured data spam. Don't add Product markup to non-product pages, don't fabricate review counts, don't use InStock when items are out of stock, and don't add priceValidUntil dates in the past. All structured data values must match what's visible on the page.