What this check tells you
Product JSON-LD gives machines a structured description of a product, but syntactic validity does not prove factual accuracy. The useful check compares each structured value with the visible product and selected variant.
Before changing the Theme
Duplicate the live Theme. Record the product URL and save the current JSON-LD. Check whether the Theme or an installed SEO app already emits Product schema. Adding another Product block can create conflicting entities.
Step 1: locate every JSON-LD block
Open the product page, use View Source, and search for:
application/ld+json
In browser DevTools, this script collects parsed blocks and keeps parsing failures visible:
[...document.querySelectorAll('script[type="application/ld+json"]')].map((node, index) => {
try {
return { index, value: JSON.parse(node.textContent) };
} catch (error) {
return { index, error: error.message, raw: node.textContent };
}
});
Expand arrays and @graph objects. More than one Product object is not automatically wrong, but overlapping objects with different prices, URLs, availability, or identifiers require investigation.
Step 2: compare field by field
Create a table for:
| Field | Visible page | JSON-LD | Result |
|---|---|---|---|
| name | Product heading | Product.name |
Match or conflict |
| URL | Canonical product URL | Product.url |
Match or conflict |
| brand | Visible brand | Product.brand |
Match, missing, or invented |
| SKU | Selected variant | Product.sku or Offer SKU |
Match or conflict |
| price | Selected variant price | Offer.price |
Match or conflict |
| currency | Storefront currency | Offer.priceCurrency |
Match or conflict |
| availability | Purchasable state | Offer.availability |
Match or conflict |
| image | Primary product image | Product.image |
Reachable or stale |
Record the JSON path and raw value. “Missing product name” is too vague when the actual issue is Product.name missing from one schema block.
Step 3: find the Theme source
Search Theme code for application/ld+json, structured_data, schema.org/Product, or the affected field name. Shopify Themes often generate structured data in a product section or snippet. An SEO app can inject another block outside that file.
If the Theme has no Product block and no app provides one, Shopify Liquid can produce structured data from the current product:
Do not add this snippet until duplicate Product output has been ruled out.
Step 4: preview the exact product and variant
Use the duplicated Theme preview. Open the same product and select representative variants: in stock, out of stock, discounted, and a variant with a distinct SKU. Repeat the field comparison.
Expected result:
- One coherent Product entity for the canonical product.
- Offers that represent actual purchasable variants.
- Price, currency, availability, and identifiers consistent with the visible state.
- Public image and product URLs returning successful responses.
Common failure modes
- A Theme block and SEO app emit conflicting Product entities.
- JSON-LD always describes the first variant while the page shows the selected variant.
- Sale price is visible but the old price remains in Offer data.
- Out-of-stock inventory is emitted as
InStock. - Product and variant SKUs are mixed.
- A localized page points structured URLs to another market.
- JSON is valid, but Liquid produced a blank or escaped value.
Verify after publishing
Fetch the public product page without an authenticated Shopify session. Save the final JSON-LD and timestamp. Use a structured-data validator for syntax, but repeat the manual field comparison because validators cannot decide whether the values match the merchant’s actual offer.
Rollback
Revert the changed Theme file or republish the prior Theme. If an app injected the conflict, disable only its structured-data feature after confirming another source remains. Recheck the public page after rollback.
Community discussion
Add to the article
Ask a technical question, share a storefront result, or challenge a conclusion with evidence.