Structured data on Shopify product pages
How Product schema (JSON-LD) on your Shopify PDPs helps Google reconcile your feed against your landing page, and why matching structured data cuts price and availability mismatch disapprovals.
When Google crawls your Shopify product page, it looks for structured data, a machine-readable block that states the price, availability and product identity of what's on that page. If that block agrees with what your feed submitted, Google trusts the offer. If it disagrees, or is missing, you get price and availability mismatch warnings that suppress products. This is how to make the two sides agree.
What structured data is doing here
Your feed tells Google what you're selling: price, availability, identity, one offer at a time. But Google doesn't take the feed's word for it. It crawls the landing page the feed points to and checks that the page agrees. Structured data is the machine-readable summary Google reads on that page: a block of JSON-LD using schema.org's Product type that states the same facts the feed claimed.
When the feed and the structured data agree, Google trusts the offer and serves it. When they disagree (feed says £40, page's structured data says £50) Google raises a price mismatch and can stop showing the product until it's resolved. Availability works the same way: feed says in stock, page's structured data says out of stock, and the offer is held. Structured data is how the landing-page side of that check is answered cleanly instead of left to Google scraping visible text and guessing.
The three fields that cause mismatches
Most PDP-versus-feed disputes come down to three attributes. These are the ones your structured data must state, correctly and per variant:
| Structured-data field | Must match the feed's | Common Shopify failure |
|---|---|---|
price |
price / sale_price |
Theme emits product-level or first-variant price; doesn't update on variant select |
availability |
availability |
Page shows "sold out" while feed still says in stock (or vice versa) |
sku / gtin |
identity of the offer | Structured data identifies a different variant than the feed's offer |
The pattern is always the same: the feed submits variant-level facts, but the page's structured data reports something coarser or staler. Google sees two different answers for one offer and flags it.
Why Shopify themes get this half-right
Shopify themes almost all output some Product schema: so it's easy to assume the box is ticked. The gaps are in the detail:
- Product-level, not variant-level. A theme that outputs one price and one availability for a product with 24 variants will disagree with the feed on every variant that differs: exactly the size-based pricing and per-variant stock cases that matter most.
- Missing fields. Schema that includes
nameandimagebut omitsoffers.priceoroffers.availabilitygives Google nothing to reconcile against, so it falls back to scraping visible page text: less reliable, more mismatch-prone. - Stale on variant switch. If the structured data reflects the default variant and doesn't update when a shopper (or crawler) selects another, the price Google reads won't be the price for the offer it's checking.
- Availability logic that doesn't mirror the feed. If "continue selling when out of stock" leaves the feed reporting in-stock but the PDP's structured data reports out-of-stock, that's a mismatch waiting for the next crawl. The two availability signals have to be built from the same rule.
Making the two sides agree
The goal isn't "add structured data": it's "make the structured data state the same thing the feed does, per variant". Two moves get you there:
- Get the feed right first. Variant-level price, sale price via compare-at logic, and availability that mirrors what the page actually tells a shopper. The field mapping covers each of these, and variant-level data is what makes per-variant reconciliation possible at all.
- Make the PDP's structured data report the same values, per variant. Check that your theme emits
offers.priceandoffers.availabilityfor the selected variant, updates them on variant change, and uses the same availability rule the feed uses. If your theme only outputs product-level schema, that's the gap to close.
When both sides are built from the same variant-level truth, the reconciliation check passes quietly and the mismatch warnings that suppress otherwise-healthy products don't appear.
Deep dive Feed-to-landing-page consistency as a health signal
Price and availability mismatches are a leading cause of Shopify product disapprovals precisely because they're structural: nothing looks wrong inside Shopify, and the feed can pass its own validation, yet the offer still gets held because the landing page disagrees. The failure lives in the gap between two systems (feed and PDP) which is exactly where no single tool is watching by default.
/tools closes that gap from the feed side. The Feed Health Score checks that the price and availability an offer submits are internally consistent and mirror what the landing page should show, and disapproval prediction flags the price/availability-mismatch pattern before Google crawls and acts on it: so you fix the offer pre-emptively rather than after impressions are lost. When a mismatch is already live in Merchant Center, fixing disapproved products walks through resolving it.
The durable fix, though, is consistency by construction: a feed built from variant-level Shopify data on one side, and a PDP whose structured data is built from the same variant-level truth on the other. Get both reading from the same source and the reconciliation check stops being a risk and becomes a formality.
Quick checks
- View a product page's source and confirm a
ProductJSON-LD block exists withoffers.priceandoffers.availability. - Select a non-default variant and confirm those values change to match the selected variant.
- Compare the structured-data price and availability against what your feed submits for the same variant: they should be identical.
- Confirm the availability rule matches: if the feed reports in-stock, the page must not read "sold out".
For the wider list of Shopify data issues that surface as Google warnings, see common Shopify feed mistakes.
Frequently asked questions
Does structured data replace my feed?
No. The feed is what you submit to Google; the structured data on your PDP is what Google reads when it crawls the landing page to check the feed is telling the truth. They're two sides of the same offer, and they need to agree. Structured data doesn't stand in for a feed, it corroborates it.
My theme already outputs Product schema, am I done?
Maybe not. Many Shopify themes emit Product schema but omit price or availability, output them at product level instead of per variant, or leave stale values that don't update when a variant is selected. The block existing isn't the same as the block agreeing with your feed. Check the specific fields, not just presence.
Which matters more, the feed or the landing page?
Both, because Google cross-checks one against the other. A perfect feed with a landing page that shows a different price still gets a mismatch warning. Reconciling the two is the point, get the feed right, then make sure the PDP's structured data states the same price and availability.