Mismatched value (page crawl) for price in Merchant Center: finding the cause on a WooCommerce store
Google compares the price in your product data with the price in the HTML of the product's landing page and in its structured data, and can disapprove the item when they differ. On a WooCommerce store the usual causes are a variation's address, a sale that ended, tax, currency and a cached page.
- By
- WP Ministry
- Published
- Tested on
- WordPress 7.1.3, WooCommerce 11.2.0, PHP 8.3.35
In short
- Google's troubleshooter names the disapproval "Mismatched value (page crawl) [price]". Its help page calls it "Mismatched product price". It is one check, of the feed against the landing page.
- WooCommerce prints the visible price and the structured data from the same product, so they nearly always agree. Look for the gap between the page and the feed.
- A variation's address prints that variation's price in the structured data, while the price in the HTML is still the range until a script runs.
- A sale with an end date changes the page at that moment, with nobody saving anything. The feed changes when the product is next sent.
- With tax on, the page follows "Display prices in the shop". Google wants tax left out of the price for the United States and Canada and included everywhere else.
- After a fix, request a website check in Merchant Center or wait for the next crawl. Google gives no closer time than hours or days.
Merchant Center disapproves a product for a mismatched price when the price in your product data is not the price Google's crawler finds on the product's landing page, in the HTML the server sends or in the page's structured data. On a WooCommerce store those two parts of the page nearly always agree with each other, because WooCommerce prints both from the same product. So the question is which price the page printed when Google looked, and why the feed held a different one.
There are five usual answers: the item is a variation and its page shows a price range, a sale started or ended before the product was sent again, the page shows tax and the feed does not, the page shows another currency, or a cache served an old page. This page shows what a store prints in each case and how to tell which one you have.
What the issue is, in Merchant Center's words
Google's help page for the issue is titled "How to fix: Mismatched product price". Google's troubleshooter for price issues in Merchant Center lists five by name.
| Name in the troubleshooter | Kind | What Google's help says about it |
|---|---|---|
| "Mismatched value (page crawl) [price]" | Item-level disapproval | The price on the landing page differs from the price in the product data. The product may be disapproved, and mismatches may lead to an account suspension. |
| "Mismatched regional value (page crawl) [price]" | Item-level disapproval | The troubleshooter asks whether the price for a region matches the regional landing page. This page does not cover regional prices. |
| "Automatic item updates active [Price]" | Item-level warning | Google found a mismatch and changed the item's price to the one on the page. It still treats the mismatch as a critical error. |
| "Inaccurate prices (due to inconsistent pricing between the feed and the landing page)" | Account-level warning, or account-level preemptive item disapproval | Google's reviewers found mismatches across the account. Its help says you should have had an email with a date to fix them by. |
The help page describes the check itself in four points.
- What is compared. Google's crawler routinely fetches landing pages and compares the
priceattribute in the product data with the price on the page, or in the page's structured data where it has any. - What is read. The crawler reads the HTML the web server returns. A price passed in by JavaScript after the page has loaded triggers an error, and Google's landing page requirements treat what the page shows after its first load as final.
- How close. The price in the HTML has to match the price in the product data exactly.
- When. The mismatch was recorded at a date and time, which the notification carries. The product may match again by now, so look at its current status first.
A disapproved item is not shown in ads or in free listings, which are how a product appears at no cost on Google Search, the Shopping tab and other Google surfaces.
What automatic item updates are
Merchant Center has a feature it calls automations, or automatic item updates. Google's help describes it this way.
- What it changes. The price, sale price, availability and condition of an item, using what the crawler finds on the landing page. A product uploaded at 4 dollars whose page says 3 is shown at 3.
- Where it reads from. The page's structured data:
priceandpriceCurrencyon the offer, or inside apriceSpecification. Where a page has no structured data, or it is incomplete, Google falls back on what it calls advanced data extractors. - Whether it is on. It is on by default. The setting is under Products, on the Automations tab.
- What it is not. A replacement for regular updates of your product data. Google says automations are for occasional problems on a small share of products. Where a price changes more than once a day they may not work, and the product may be disapproved instead of updated. Google may also stop the updates when it finds too many mismatches.
So the warning "Automatic item updates active [Price]" means Google corrected the item this time. Its help page for the warning says such products are still treated as critical errors that can lead to account suspension. The cause is the same as for a disapproval, and so is the way to find it.
What a WooCommerce product page prints
What follows was read from a test store on WordPress's default theme, Twenty Twenty-Five, with WooCommerce and no other plugin. A test store shows what the store's page prints. It cannot show Merchant Center, so what Google does with each page is stated from its help pages and not from a test.
WooCommerce prints a product's price twice: as text a shopper reads, and in a block of structured data near the end of the page. WooCommerce schema markup covers the rest of that block.
| Product | Price in the page's HTML | Price in the structured data |
|---|---|---|
| Simple product at 40 dollars | $40.00 | An Offer with price 40.00 and priceCurrency USD |
| Variable product, variations at 30 and 45 dollars, at its own address | $30.00 – $45.00 | An AggregateOffer with lowPrice 30.00 and highPrice 45.00, and no price |
| The same product at the address of its 45 dollar variation | $30.00 – $45.00, with the variation selected in the form | An Offer with price 45.00 |
| Product at 20 dollars, on sale at 15 | $20.00 struck through, then $15.00 | An Offer with price 15.00, and 20.00 marked as the list price |
| The first product with a 10 percent tax, shown including tax | $44.00 | An Offer with price 44.00 |
1. A variable product whose variations differ in price
A feed has one item for each variation, each with its own price. The page is one page for all of them.
At the product's own address, the structured data is an AggregateOffer with the lowest and the highest price, and the visible price is the same range. No single price on that page matches a variation's.
WooCommerce gives each variation an address of its own: the product's address with the attributes in the query string, such as /product/linen-apron/?attribute_size=Large. On the test store, a request for that address got an Offer with that variation's price, 45.00, and the variation selected in the form. A comment in WooCommerce's source says why: a request that names every attribute of one variation gets that variation's exact price, to keep the landing page's structured data in step with the variation and avoid price mismatch disapprovals in Merchant Center. A request that does not pin down one variation gets the range.
The visible price is another matter. In the HTML the server sent for the variation's address, the price a shopper would read was still the range, $30.00 – $45.00. A script puts the variation's own price on the page after it loads. Google's help says its crawler reads the HTML the server returns, and asks that each variant in a feed have a link that loads with that variant already selected. For a page that displays a range, it says the price in the product data should be the cheapest value of the range. Whether the structured data alone settles the comparison is Google's to say, and its help does not say.
So for a variation, check which address the feed sends as the item's link. WooCommerce variations and SEO covers those addresses, their canonical link and what Google says about variants.
2. A sale price, and the day it ends
During a sale, the structured data's price is the sale price. The regular price is there too, as a second price marked ListPrice. Both halves of the page show the sale.
An offer always carries priceValidUntil. With no sale, or a sale with no end date, it is 31 December of the following year. During a sale that has an end date, it is that date.
A sale that has an end date ends on the page by itself. On the test store a product at 50 dollars was put on sale at 35 with an end a minute and a half ahead, and its page was read before and after.
| Before the end | After the end | |
|---|---|---|
| Visible price | $50.00 struck through, then $35.00 | $50.00 |
price in the structured data | 35.00 | 50.00 |
priceValidUntil | The day the sale ends | 31 December of the following year |
Nobody saved the product in between, and no scheduled task had run. The page changed because the time had passed. The price WooCommerce keeps in the database for the product still read 35 at that point. WooCommerce corrects that stored value with an action it schedules for the sale's end, and the page did not wait for it.
This is the cause Google's help lists first: a difference in time between an update on the website and an update of the product data. The page moves at the second a sale ends. The feed moves when the product is next sent. If the feed carries sale_price with dates of its own, Google's help says to check that the dates and their time zone are right.
3. Tax
WooCommerce has one setting for whether prices are shown with tax. It is under WooCommerce > Settings > Tax, named "Display prices in the shop", with the choices "Including tax" and "Excluding tax". The Tax tab is there only once "Enable taxes" is ticked under WooCommerce > Settings > General.
On the test store, with taxes enabled and a 10 percent rate for the store's own region:
| "Display prices in the shop" | Visible price | price in the structured data | valueAddedTaxIncluded |
|---|---|---|---|
| Excluding tax | $40.00 | 40.00 | false |
| Including tax | $44.00 | 44.00 | true |
The structured data follows the same setting as the visible price, so the page agrees with itself either way. The price stored for the product stayed 40 throughout, and a feed that sends 40 does not match a page that shows 44. Google's documentation on merchant listing markup does not mention valueAddedTaxIncluded, so do not count on that property to explain the difference.
What Merchant Center requires depends on the country the item is sold in. Its product data specification puts it in two lines.
| Country of sale | What the price attribute holds |
|---|---|
| United States and Canada | The price without any tax: no sales tax, GST, VAT or import tax |
| All other countries | The price including VAT or GST |
The landing page has to show that same price. So a store selling in the United States needs "Excluding tax" on the page and a price without tax in the feed. A store selling where tax is included needs "Including tax" on the page and the same in the feed.
One more setting changes a price shown with tax: "Default customer location", under WooCommerce > Settings > General. It decides where a visitor who has given no address is taken to be, and so which tax rate applies. On the test store, set to "Shop country/region", the page printed 44.00. Set to "No location by default", the same page printed 40.00, because no rate applied. The other two choices, "Geolocate" and "Geolocate (with page caching support)", work out the customer's current location, by WooCommerce's documentation, and calculate tax from it. The price then depends on where each visitor is, and a crawler is a visitor too. Google's rules for the price attribute say not to change a price by the visitor's location.
4. Currency
A currency switcher shows each visitor a price in one of several currencies. The test store has no such plugin, so this part is from Google's help alone.
- The landing page must show the price in the currency of the product data, to every visitor, wherever they are.
- Where a page displays more than one currency, the one in the product data must be the one shown most prominently.
- To sell in a country whose currency the site does not use, Google has a currency conversion feature of its own. The converted price does not have to appear on the page.
Google's help lists the risk as a cause in its own right: a crawler can be given a different price and currency from the ones shown to users. WooCommerce names the store's currency in the structured data as priceCurrency. Read it with the command below, and compare it with the currency a visitor in the target country sees and the one in the feed.
5. A cached page
A full-page cache keeps a finished copy of a product page and serves it until the copy is cleared or expires. A copy made during a sale still shows the sale price after the sale has ended, in the visible price and in the structured data. It also keeps the sale's end date in priceValidUntil, and Google's documentation on merchant listing markup says a listing may not display once that date is in the past.
To check, compare what the page serves with what the store holds, using the commands in the next section. If WooCommerce reports one price and the page serves another, a cache is between them. Clear the caching plugin, the host's cache and any CDN that stores whole pages, then read the page again. When a sale ends by the clock nothing is saved at that moment, so a cache that is cleared only when a product is saved keeps its old copy. How to speed up a WooCommerce store covers which pages of a store can be cached.
Find which one it is
Work on one disapproved product from start to finish. The commands need WP-CLI. How to use WP-CLI covers connecting and where to run them.
Step 1: Note what Merchant Center holds for the item
In Merchant Center, go to Products and select the Needs attention tab. Filter for the issue and open one product. Write down three things: the price and currency Merchant Center holds for it, the link it holds, and the time the mismatch was found. Google's troubleshooter calls the values Merchant Center holds the product's "Final Attributes".
Step 2: Open the link as a visitor
Open that exact link in a private window, so that you are not signed in to the store, and from the country the feed targets. Read the price a shopper sees. Note whether it is one price or a range, whether it includes tax, and which currency it is in.
Step 3: Read the price in the structured data
This prints the price fields from the page's structured data. Put the item's link in place of the address.
bashcurl -sL "https://example.com/product/your-product/" | grep -o '<script type="application/ld+json"[^>]*>[^<]*' | grep -Eo '"@type":"[A-Za-z]*Offer"|"(price|lowPrice|highPrice|priceCurrency|priceType|priceValidUntil|availability)":"[^"]*"|"valueAddedTaxIncluded":[a-z]+'Step 4: Read what it printed
For a simple product at 40 dollars the command prints this. The price is there twice because WooCommerce states it on the offer and again inside a
priceSpecification."@type":"AggregateOffer"with alowPriceand ahighPricemeans the page printed a range. A line withpriceTypemarks the regular price during a sale. Google's Rich Results Test shows the same fields without a terminal, and Google's help on mismatches points to it. The test reads the page as a visitor who is not signed in.text"@type":"Offer" "price":"40.00" "priceCurrency":"USD" "priceValidUntil":"2027-12-31" "availability":"https://schema.org/InStock" "price":"40.00" "priceCurrency":"USD"Step 5: Read what the store holds
This asks WooCommerce for the product. Put the product's ID in place of
123, and an administrator's username in place ofadmin: WooCommerce's commands need a user to run as.priceis the price now,on_salesays whether a sale is running, anddate_on_sale_tois when the page will change by itself. With tax switched on, this is the price as it was entered, before the display setting is applied.bashwp wc product get 123 --user=admin --fields=id,type,price,regular_price,sale_price,on_sale,date_on_sale_to,in_stockStep 6: For a variable product, list its variations
This prints each variation's price and its own address. Put the variable product's ID in place of
123.Compare the
permalinkof the disapproved variation with the link Merchant Center holds for it.bashwp wc product_variation list 123 --user=admin --fields=id,price,in_stock,permalinkStep 7: Read the settings that change a price
In order: the store's currency;
yesif taxes are enabled;yesif prices are entered with tax;inclorexclfor "Display prices in the shop"; and the default customer location, which isbasefor "Shop country/region",geolocationorgeolocation_ajaxfor the two "Geolocate" choices, and empty for "No location by default".bashwp option get woocommerce_currency wp option get woocommerce_calc_taxes wp option get woocommerce_prices_include_tax wp option get woocommerce_tax_display_shop wp option get woocommerce_default_customer_address
Now put the four prices side by side: Merchant Center's, the visible one, the one in the structured data, and the store's.
| What you find | The cause |
|---|---|
| The link is the product's own address, the page shows a range, and the feed holds one variation's price | The variation's link. See cause 1. |
| The page and the store agree with each other, and the feed holds an older price | Timing: a sale or a price change the feed has not caught up with. See cause 2. |
| The page's price is the feed's price plus or minus tax | The tax display setting against the country's rule. See cause 3. |
| The page's currency is not the feed's | Currency. See cause 4. |
| The store reports one price and the page serves another | A cached page. See cause 5. |
| The structured data and the visible price disagree with each other | Something other than WooCommerce is printing one of them: a theme, or a second plugin writing its own markup. |
| All four agree | The mismatch was found at an earlier time and has passed. Check the item's current status. |
How the feed gets its price
This depends on what sends your products to Google.
Google for WooCommerce is WooCommerce's own extension for this. Its documentation says the following.
- It has no feed file. It sends products to Merchant Center through Google's API, in background jobs scheduled on the store.
- It submits every product after setup, and again when its settings change.
- When a product is created or updated, that product is sent again by a background job. The change may take a while to appear in Merchant Center.
- Each simple product and each variation is an item. A variable product by itself is not.
- It sends the store's primary currency, and it does not support multi-currency extensions.
- A full sync can be started by hand from its connection test page, with the button "Sync All Products with Google Merchant Center".
The documentation does not say whether the price it sends includes tax, or which address it sends as a variation's link. Nor does it say what happens when a price changes with the clock, as at the end of a sale, with no one saving the product. Read the item's price and link in Merchant Center instead of assuming them.
Other plugins build a feed file. Google's help describes fetching product data from a file on a schedule you set, so the gap between the page and the feed can be as long as the time between two fetches. Read the plugin's own documentation for what it sends as the price, with or without tax, and how often.
After the fix
Fix the side that is wrong. If the page is right, send the product again so that the feed holds the page's price. If the feed is right, correct the page. Then Google's help gives two ways forward.
- Wait. Google's crawler comes back to disapproved products "over the next few hours or days", and a product whose price now matches is approved again.
- Request a website check. In Merchant Center you can say the issue is fixed and ask for a check. Google's help says this makes the review quicker than waiting, that it may take up to 12 hours, and that you cannot send another request during that time.
If you think Google is wrong, the same screen has "I disagree with the issue" and "Request review". Google's help says the number of reviews can be limited.
An account-level warning works differently. Google's help says a warned account can ask for a review before the deadline in the email, and that an account that fails a review after a preemptive disapproval waits 7 business days before it can ask again. Fix every affected product before asking.
Nobody outside Google decides when it looks again. What you control is that the page, its structured data and the feed say one price when it does.
Availability works the same way
Google makes the same comparison for stock. Its help page is titled "How to fix: Mismatched product availability", and it names the same common cause: a difference in time between an update on the website and an update of the product data. The command above prints the page's availability beside its price, so one reading covers both. WooCommerce out of stock and discontinued products and SEO covers what a store prints for each stock status, a variation's included.
When to get help
- Ask the feed plugin's support when the page is right and the feed keeps sending something else.
- Ask your host when the page serves an old price and you cannot find the cache that holds it.
- Hand it over when the visible price and the structured data disagree and you cannot find what prints the second one. WP Ministry looks at what a store's product pages tell a search engine about price and stock as part of a WordPress SEO audit, which starts with a free diagnosis. There is also a WooCommerce SEO service.
Common questions
Is WooCommerce's structured data the cause of the mismatch?
Usually not. On the test store the structured data and the visible price showed the same amount for a simple product, a product on sale and a product with tax, under each setting. They differed in one place, a variation's address, where the structured data had the variation's price and the HTML still showed the range. Look first at the gap between the page and the feed, and do not edit the structured data to match a feed: Google compares the feed with the visible price as well.
The price matches now. Why is the product still disapproved?
The mismatch was recorded at a moment in the past, and the disapproval stays until Google has looked at the page again. Google's help says its crawler rechecks disapproved products over the following hours or days. You can also request a website check.
Should I turn automatic item updates off?
Google leaves them on by default and describes them as a fix for occasional mismatches on a small share of products. It names one case for switching price updates off: a product page that shows several struck-through prices, where Google may pick the wrong one. They do not replace sending correct product data.
My variable product shows a price range. Will that get it disapproved?
It depends on which page the feed's link opens. Google's help asks that each variant in a feed have a link that loads with that variant selected. On the test store, a variation's own address gave that variation's price in the structured data, and the product's own address gave the range. Check which link your feed sends for each variation.
- ResourceWooCommerce sale readiness checklist: Black Friday or any big sale
- Error fixHow to fix WooCommerce payment gateway errors
- ResourceWooCommerce checkout is down: a runbook
- Cost guideWooCommerce maintenance cost: why a store costs more, and what the extra should buy
- Error fixHow to fix a WooCommerce checkout that is not working
- GuideWooCommerce variations and SEO: variation URLs, canonical links and the price in structured data

