TL;DR
- Google's "automatic item updates" cross-checks your feed price against two extra on-page signals: the
ProductJSON-LD block and theog:price:amountOpen Graph tag.- The most common Shopify culprits: discount apps that update the visible price but leave JSON-LD stale, and multi-currency apps that rewrite the displayed price without touching
cart.currency.iso_code.- Fix: route
offers.price,priceCurrency, and the displayed price through the same Liquid variable — no hardcoded values, no divergent app outputs.
If you build or maintain Shopify stores for clients running Google Shopping campaigns, this is the kind of silent failure that generates support tickets weeks after launch: a wall of Merchant Center disapprovals citing "inconsistent value" or "price mismatch," on products whose Shopify prices look perfectly correct.
The cause isn't the feed. It's a three-way signal conflict on the live page — and Merchant Center is comparing all three.
This article covers how Google's automatic item updates work, which Shopify-specific patterns cause the three signals to diverge, and the single Liquid pattern that eliminates the root cause.
Why does Google reject prices it can already read from the feed?
Merchant Center doesn't only trust the price you submit in your product feed. Google's crawlers also perform automatic item updates — they visit the live page, read the price from the structured data (Product JSON-LD) and the Open Graph tags (og:price:amount), and compare that against your feed. If any of those three sources disagree, Google either overrides the feed price silently or disapproves the listing outright for "inconsistent value."
A store can have a perfectly correct Shopify product price and still get disapproved because one of the other two signals is out of sync.
Where does the divergence come from in Shopify?
A half-applied sale. A discount app updates the displayed price but never touches the JSON-LD block, which keeps rendering the pre-sale figure. Shoppers see the sale price; Google's structured-data reader sees the old one.
A multi-currency or currency-conversion app. This is the single biggest source of this bug. These apps rewrite the price a visitor sees based on geolocation or a currency switcher, but frequently don't touch cart.currency.iso_code or the JSON-LD price/currency fields — those keep reporting the shop's base currency. Google reads two different currencies or amounts for the same offer, triggering the currency_mismatch / price_mismatch pattern.
A hardcoded price in a theme edit. Someone typed a price directly into a Liquid template instead of pulling it from the product object. It looks fine at launch and quietly goes stale the next time the price changes in Shopify admin.
Duplicate schema from an app. If a review app or SEO app injects its own Product block alongside the theme's native one, you end up with two different prices on the same page. Google picks one arbitrarily — if it picks the stale one, that's what gets compared to your feed.
What does the fix look like in Liquid?
Every price on the page — the visible price, the Open Graph tag, and the JSON-LD offers.price — must come from the same Liquid variable, live, at render time:
"offers": {
"@type": "Offer",
"price": "{{ product.selected_or_first_available_variant.price | divided_by: 100.0 }}",
"priceCurrency": "{{ cart.currency.iso_code }}",
"availability": "{% if product.available %}https://schema.org/InStock{% else %}https://schema.org/OutOfStock{% endif %}"
}
No hardcoded numbers, no values from a separate app config, no currency assumed from the shop's default market. If the client runs Shopify Markets or a currency-conversion app, cart.currency.iso_code must reflect the converted currency the shopper is actually seeing — verify the app writes to that value rather than only restyling numbers client-side.
Availability deserves the same treatment: drive it from product.available, not a hardcoded value, or it becomes its own disapproval vector.
How do you audit this on a client's store?
- Open the disapproved product on the storefront. View source or open DevTools → find the
<script type="application/ld+json">block. Note thepriceandpriceCurrency. - Search the same page source for
og:price:amountandog:price:currency— these must match exactly. - Compare both against what the shopper actually sees and against the price in the Merchant Center feed.
- If the client runs a multi-currency or localization app, repeat from a session simulating a different country/currency — the visible price often switches while schema and OG tags stay in the base currency.
- If any two of those four numbers disagree, you've found the mismatch. Trace which app or template owns the wrong value and route it through the Liquid variable above.
This failure produces zero visible symptoms for weeks — the storefront looks normal, sales keep coming in, and the only signal is a slow bleed of disapproved SKUs in a Merchant Center tab the merchant rarely checks.
Related reading
- Your review stars disappeared from Google? The 5 Shopify causes
- The phantom noindex: how Shopify apps silently hide your products from Google
Have you run into a currency or discount app that handles the schema side correctly out of the box — or have you always had to patch it manually?
The full version of this article — with screenshots and ongoing updates — lives on the StoreCanary blog.
Top comments (0)