Short answer. A WooCommerce feed that still shows yesterday’s price has one of four causes: the feed is a file written on a timer and the timer has not run since the change; the timer is WP-Cron, which only runs when someone visits the site; a page-cache plugin is serving an old copy of the feed URL; or the feed is fine and Merchant Center simply has not fetched it. Open the feed URL in a private window and compare it with the product: if the URL is current, the problem is on Google’s side of the fetch; if it is stale, it is one of the first three.
Why it matters more than it looks
A stale feed is not a cosmetic problem. Google crawls your product pages and compares what it finds with the feed; a price that changed in the shop and not in the feed is reported as “Mismatched value (page crawl) [price]”, and enough of those suspend the account. Stock that changed and did not reach the feed becomes the availability version of the same error. And a feed Google cannot fetch at all lets every product expire after 30 days, silently.
Five-minute diagnosis
1. Open the feed URL yourself, in a private browser window so no cookie or login changes what you see, and find a product you changed today. If the feed shows the new value, skip to cause four. If it shows the old one, continue.
2. Ask how the feed is made. Look at the plugin’s settings page. If it has a “last generated” time, a schedule, or a “regenerate now” button, the feed is a file written on a timer (causes one and two). If it has none of those and the feed is served from a URL that reads the database on each request, it is built live, and a stale copy points at a cache (cause three).
3. Add a throwaway query string to the feed URL (?nocache=1) and open it again. If the fresh URL shows the new price and the plain one does not, a cache sits in front of the feed. If both are stale, the file itself is old.
Cause one: a file built on a timer
Many feed plugins write the feed to a file under wp-content/uploads and regenerate it on a schedule, hourly or daily. Between runs the file is a snapshot. A price changed at 10:00 reaches Google at the next run, and if Google crawls the product page in between, it sees two prices for one product. The generated-file design is not wrong, but the schedule is the whole product: set it as short as the plugin allows, regenerate by hand after a bulk price change, and make sure the schedule actually runs, which is cause two.
The alternative is a feed with no timer. Our free plugin builds the feed at the moment the URL is requested, from the live catalogue, so what Google fetches is what the store says at that second. There is no file to be old.
Cause two: WP-Cron only runs when someone visits
WordPress has no clock of its own. The Plugin Handbook explains that WP-Cron works by checking, on every page load, whether a scheduled task is due, and that a task scheduled for 2 pm on a site with no visitors until 5 pm runs at 5 pm. A feed scheduled to regenerate hourly on a quiet store regenerates when the next visitor arrives, which on a small shop overnight can be many hours. Some hosts also disable WP-Cron and expect a system cron in its place.
The fix is a real clock: ask your host to call wp-cron.php on a schedule (most managed WordPress hosts do this already), or use a per-request feed that needs no cron at all.
Cause three: a page cache is serving an old copy
Page-caching plugins store the full response to a URL and serve it again without running PHP. That is exactly what a shop wants for product pages and exactly wrong for a feed, which must be fresh on every fetch. WooCommerce’s caching guidance tells you to exclude Cart, Checkout and My Account from the cache; a feed URL is not on that list, so nothing excludes it unless the feed plugin does or you do.
Check your caching plugin’s exclusion settings and add the feed URL path. Our plugin marks its response as not cacheable (the DONOTCACHEPAGE convention the common caching plugins honour) and closes any output buffer a caching plugin has opened before it writes, because we found a live store where a caching plugin turned the feed into an empty page; the fix was verified on a LiteSpeed host. If a CDN sits in front of the site, check its rules too: a rule that caches XML caches the feed.
Cause four: Merchant Center has not fetched it
If the URL is current and Google is not, the feed did its job and the fetch did not. In Merchant Center, open the data source and look at the last fetch time and status. A fetch can fail for the reasons in our guide to fetch failures (a blocked fetcher, a login page, a size limit); Google’s troubleshooting page lists the error messages. If the fetch succeeded, the schedule may be too slow for how often your prices move: set it to the most frequent option and press Fetch now after a big change. Products then take up to a day to update in the Needs attention view.
Keeping it fresh, permanently
Three settings, once: a feed with no timer (or a timer that runs on a real clock), the feed URL excluded from every cache between WordPress and Google, and a Merchant Center fetch schedule set as frequent as the plan allows. After that, the only way for Google to see an old price is for the shop to show one. The free feed check opens a sample of your product pages and compares their prices with the feed’s, which is the fastest way to see whether the three settings are holding.
Questions merchants ask
How often does Google fetch my feed?
On the schedule set on the data source in Merchant Center, and whenever you press Fetch now. A feed that is always current at the URL still only reaches Google when Google reads it, so set the schedule as frequent as your plan allows and re-fetch after a big price change.
The feed URL shows the right price but Merchant Center shows the old one. Which is stale?
Merchant Center. The feed is fine; Google has not fetched it since the change, or has fetched it and is still processing. Use Fetch now on the data source and allow up to a day for the product to update.
Could a CDN be caching the feed?
Yes, if a rule caches the feed path. Most CDNs do not cache dynamic responses by default, but a rule that caches everything under your domain, or a page rule for XML, will serve Google an old copy. Exclude the feed URL from CDN caching, or set its cache time to minutes.
Is a feed that is rebuilt on every request slow for a large catalogue?
It costs one database pass per fetch, which for a few thousand products is seconds. Google fetches once per schedule, not per shopper, so the cost is small. A catalogue of tens of thousands of products may prefer a generated file with a short schedule; the point is that the schedule exists and runs.
Sources
The WordPress Plugin Handbook on Cron (WP-Cron runs on page load); WooCommerce’s How to configure caching plugins; Google Merchant Center Help on troubleshooting a data source and the expiration date attribute; and the readme of FeedRobin Product Feed for WooCommerce. The page-cache failure is our own, found on a WooCommerce install running a caching plugin in September 2026.