Your Shopping campaigns were running fine, then traffic quietly fell off a cliff. You open Merchant Center and find a wave of products marked expired or expiring soon:
Status: Expired
Reason: Product expired 30 days after last update
Nothing was disapproved. You did not change anything. That is the whole problem. Google expires products that have not been refreshed in 30 days, and a feed that stopped updating, whether the schedule broke, a token expired, or an app silently failed, takes your whole catalog down with it on a rolling basis.
This post explains Google's expiration rule, the difference between the expiration_date attribute and the automatic 30-day expiry, and how to make sure your products never go stale again.
TL;DR
- Every product in Merchant Center expires 30 days after its last refresh. Products added or refreshed regularly never hit this. Products from a feed that stopped updating expire on a rolling 30-day basis.
- An expired product stops serving. Shopping campaigns that depend on it cannot run.
- Two separate clocks exist: the automatic 30-day expiry, and the optional
expiration_dateattribute you set yourself. Whichever comes first wins. - The fix is a reliable, recurring feed refresh. Manual one-time uploads are the most common cause of expiration.
- Products entered directly in Merchant Center (not via a feed) do not expire, but that is not how a real catalog should be managed.
What "expired" actually means
Google states the rule plainly in its product status and visibility documentation: all products expire from your Merchant Center account 30 days after the last refresh. A "refresh" is any successful processing of that product, whether from a scheduled feed fetch, a manual upload, an API update, or Google's own crawl of your structured data.
The expiration shows up in two related places:
- Product level: the product status reads
expired, and in the Content API product statuses thedestinationStatusesreflect that the product is no longer approved to serve. - Feed level: if the entire feed has not been fetched in over 30 days, the data source itself is marked expired, and every product it supplied expires with it.
There is also a separate, voluntary mechanism. The expiration_date [expiration_date] attribute lets you set an explicit expiry on a product. When you use it, Google honors whichever is sooner: the date you set, or 30 days after the last refresh. So an expiration_date of 14 days from now will expire the product in 14 days even though the 30-day clock has not run out.
Why Google expires products
The 30-day rule exists to keep the Shopping surface fresh and accurate. A feed that has not updated in a month is, from Google's perspective, untrustworthy. Prices may have changed, items may be out of stock, products may have been discontinued. Rather than serve a listing nobody is maintaining, Google retires it.
This is why expiration is silent and rolling. There is no policy violation and no disapproval, so it never appears in the Needs attention tab as something to "fix." It just gradually drains your active product count as the 30-day mark passes for batches of products that all stopped refreshing around the same time.
Four causes, ranked by frequency
Cause 1: A one-time manual upload that was never scheduled
By far the most common. A merchant uploads a CSV or feed file once to get products live, sees them approved, and moves on. Thirty days later, with no recurring fetch, the entire batch expires at once. The fix is to replace the manual upload with a scheduled fetch or an API-based sync that refreshes on a regular cadence.
Cause 2: A scheduled fetch that silently broke
A feed schedule exists but stopped working: the hosted file URL changed, the credentials expired, the SFTP path moved, or the app generating the feed errored without alerting anyone. Products keep serving for up to 30 days on their last good refresh, which is exactly why nobody notices until they start expiring.
The fix:
- In Merchant Center, open Data sources, select the feed, and check the last fetch timestamp and result.
- If the last fetch failed, read the error (bad URL, auth failure, file not found) and correct it.
- Trigger a manual fetch to confirm it succeeds, then confirm the schedule is active.
Cause 3: An OAuth token or API connection that lapsed
For API-driven syncs, an expired or revoked OAuth refresh token stops updates at the source. The connection looks connected but pushes nothing. Products coast for 30 days, then expire. The fix is to reauthorize the connection and confirm updates are flowing again.
Cause 4: An expiration_date attribute set too aggressively
Less common, but worth checking. If you set expiration_date on products (for time-limited inventory, for example) and the value is closer than 30 days out, products expire on that date regardless of refreshes. Confirm the attribute reflects real intent and is not a stale value carried over from an old feed.
How to verify and prevent it
- Check the feed's last successful fetch. In Data sources, the timestamp tells you whether refreshes are actually happening. Anything older than a few days on a daily schedule is a red flag.
- Set up a recurring refresh, not a one-time upload. Daily is a safe default for most catalogs. High-velocity inventory (frequent price or stock changes) benefits from more frequent syncs.
- Monitor the active product count. A steady or growing active count means refreshes are working. A slow decline over a few weeks is the signature of expiration creeping through a stalled feed.
- Re-push immediately if products already expired. A successful refresh reinstates expired products on the next processing cycle, assuming they are still otherwise valid.
What not to do
- Do not rely on a manual upload to keep products live. It guarantees expiration in 30 days. Schedule the refresh.
- Do not bump
expiration_datefar into the future to dodge the rule. The 30-day refresh clock still applies, so anexpiration_dateof next year does nothing if the feed stops updating. The refresh is what matters. - Do not re-add products by hand in Merchant Center to keep them from expiring. Manually added products do not expire, but managing a real catalog by hand is unsustainable and disconnects Merchant Center from your store's source of truth.
How SnowPipe handles this
Expiration is fundamentally a refresh-reliability problem, and that is the part SnowPipe is built to own. Instead of one-time uploads, SnowPipe runs scheduled syncs from your Shopify, WooCommerce, or BigCommerce catalog to Google through the Merchant API v1, so every product is refreshed on a recurring cadence and the 30-day clock never runs out.
Two design choices matter here. SnowPipe handles OAuth token refresh automatically, so a lapsed token does not silently stop updates (Cause 3 above). And when products are deleted in your store, SnowPipe's auto-removal flow removes them from Google deliberately, with a 20 percent safety threshold and a confirmation step, rather than letting them linger until they expire. Real-time webhook triggers can also push changes the moment a product updates in Shopify, on top of the scheduled baseline.
Frequently asked questions
Why do my Google Merchant Center products keep expiring?
Products expire 30 days after their last refresh. If your feed stopped updating, whether from a one-time manual upload, a broken schedule, or a lapsed API token, products expire on a rolling 30-day basis. A reliable recurring refresh prevents it.
What does "product expired 30 days after last update" mean?
It means Google has not received a refresh for that product in 30 days, so it retired the listing to keep the Shopping surface current. It is not a disapproval or a policy issue. Re-pushing the product reinstates it on the next processing cycle.
How do I stop products from expiring in Merchant Center?
Use a scheduled or API-based feed that refreshes regularly (daily is a safe default) instead of a one-time upload, and make sure the fetch is actually succeeding. Monitor the feed's last-fetch timestamp and your active product count.
Does the expiration_date attribute override the 30-day rule?
They work together, and whichever comes first wins. If you set expiration_date to a date sooner than 30 days out, the product expires on that date. If you set it further out, the 30-day refresh clock still applies, so a stalled feed still expires the product.
Do products added directly in Merchant Center expire?
No. Products entered manually in Merchant Center do not expire on the 30-day clock. Only products supplied by a data source do. Managing a full catalog by hand is not practical, though, so a reliable automated feed is the real solution.
Want your catalog to refresh on schedule so nothing ever expires?
Try SnowPipe free — connect your store and get scheduled syncs with automatic token refresh. Or, book a 15-min demo and I'll walk you through your specific setup.