Skip to content

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 troubleshooterKindWhat Google's help says about it
"Mismatched value (page crawl) [price]"Item-level disapprovalThe 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 disapprovalThe 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 warningGoogle 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 disapprovalGoogle'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 price attribute 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: price and priceCurrency on the offer, or inside a priceSpecification. 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.

ProductPrice in the page's HTMLPrice in the structured data
Simple product at 40 dollars$40.00An Offer with price 40.00 and priceCurrency USD
Variable product, variations at 30 and 45 dollars, at its own address$30.00 – $45.00An 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 formAn Offer with price 45.00
Product at 20 dollars, on sale at 15$20.00 struck through, then $15.00An 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.00An 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 endAfter the end
Visible price$50.00 struck through, then $35.00$50.00
price in the structured data35.0050.00
priceValidUntilThe day the sale ends31 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 priceprice in the structured datavalueAddedTaxIncluded
Excluding tax$40.0040.00false
Including tax$44.0044.00true

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 saleWhat the price attribute holds
United States and CanadaThe price without any tax: no sales tax, GST, VAT or import tax
All other countriesThe 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.

  1. 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".

  2. 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.

  3. 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.

    bash
    curl -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]+'
  4. 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 a lowPrice and a highPrice means the page printed a range. A line with priceType marks 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"
  5. 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 of admin: WooCommerce's commands need a user to run as.

    price is the price now, on_sale says whether a sale is running, and date_on_sale_to is 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.

    bash
    wp wc product get 123 --user=admin --fields=id,type,price,regular_price,sale_price,on_sale,date_on_sale_to,in_stock
  6. Step 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 permalink of the disapproved variation with the link Merchant Center holds for it.

    bash
    wp wc product_variation list 123 --user=admin --fields=id,price,in_stock,permalink
  7. Step 7: Read the settings that change a price

    In order: the store's currency; yes if taxes are enabled; yes if prices are entered with tax; incl or excl for "Display prices in the shop"; and the default customer location, which is base for "Shop country/region", geolocation or geolocation_ajax for the two "Geolocate" choices, and empty for "No location by default".

    bash
    wp 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 findThe cause
The link is the product's own address, the page shows a range, and the feed holds one variation's priceThe variation's link. See cause 1.
The page and the store agree with each other, and the feed holds an older priceTiming: 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 taxThe tax display setting against the country's rule. See cause 3.
The page's currency is not the feed'sCurrency. See cause 4.
The store reports one price and the page serves anotherA cached page. See cause 5.
The structured data and the visible price disagree with each otherSomething other than WooCommerce is printing one of them: a theme, or a second plugin writing its own markup.
All four agreeThe 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.

More on this subject

SEO audit, done for you

SEO audit is $249. A written audit, each finding with its source, and up to 2 hours of fixes done and tested again. It starts with a free diagnosis.