How gift product data loads & caching
Why your Gift-with-Purchase widget can take a few minutes to reflect product changes, and how to push updates through sooner.
When you change a gift product in Shopify or in the campaign customizer, you expect the storefront widget to match right away. Usually it does within a few minutes — but not always instantly. This page explains how the Gift-with-Purchase (GWP) widget pulls gift product data, why a short cache sits between Shopify and what your shoppers see, and exactly how to force a refresh when you can't wait.
This is the "why" behind a gotcha you'll see referenced across the gift docs: gift product data is cached client-side, in the shopper's browser, for about 5 minutes. If you read nothing else, that's the number to remember.
Why this matters
You flip a gift product from Unlisted to Active, drop its price, swap the image, fix a translated title, or restock a sold-out variant — then you refresh the storefront and see the old value. Nothing is broken. The widget is showing data it already fetched a few minutes ago and held onto.
Knowing this saves you from chasing a "bug" that isn't one:
- You won't keep editing the product over and over thinking the change didn't save.
- You'll know when to simply wait, and when to force a refresh.
- You can give shoppers and teammates an accurate answer ("it'll update within ~5 minutes") instead of guessing.
The rest of this page sets those expectations precisely and gives you the levers to speed things up.
How gifts are loaded (plain English)
Normal storefront browsing — collection pages, search, "you may also like" listings — works by searching or listing your catalog. Shopify's listing/search results deliberately exclude unlisted products, so anything hidden from search simply never shows up in those places.
The GWP widget works differently. It doesn't search your catalog. It already knows exactly which products are gifts in your campaign, so it fetches each gift product directly by its ID — one targeted lookup per gift, by name, not a search.
That direct-by-ID approach is the reason an unlisted gift product can still appear in the widget: fetching a product by its specific ID reaches any product published to your Online Store sales channel, including ones hidden from search. A catalog search could never surface that same unlisted product.
Here is the contrast in one view:
| How products are found | Used by | Can it return Unlisted products? |
|---|---|---|
| Search / listing the catalog | Collection pages, search, recommendation listings | No — unlisted products are excluded |
| Direct lookup by product ID | The GWP gift widget | Yes — reaches any product on the sales channel |
A simple way to picture the GWP flow:
Your campaign already holds the gift product IDs
│
▼
Widget asks Shopify: "give me product 123, product 456" (by ID, not a search)
│
▼
Shopify returns each gift directly — including unlisted ones
│
▼
Result is cached client-side in the browser for ~5 minutes, then re-fetchedFor the full story on using search-hidden products as gifts, see Gift with Purchase: using unlisted products.
The ~5-minute cache
To keep the widget fast and avoid hammering Shopify on every page view, the storefront caches the gift product data it fetches in the browser's memory for about 5 minutes. This is a client-side, in-memory cache — not an HTTP or CDN cache — and it's keyed by the exact query string the widget sends, so each distinct query gets its own entry. During that window, the widget reuses what it already pulled instead of asking Shopify again. Once the window passes, the next load re-fetches fresh data.
That cache covers essentially everything the widget reads off a gift product. After you change any of the following in Shopify admin, the storefront can keep showing the previous value until the cache expires:
| What you changed on the gift product | Reflected on storefront after... |
|---|---|
| Status — Active vs Unlisted | ~5 min (next fetch after expiry) |
| Price | ~5 min |
| Title and translated titles | ~5 min |
| Product image | ~5 min |
| Variant availability / inventory (in stock vs sold out) | ~5 min |
| Whether Hide unlisted products filtering changes the result | ~5 min |
| Whether Hide out-of-stock filtering changes the result | ~5 min |
In other words: if a value lives on the Shopify product, expect the ~5-minute delay. The filtering toggles (Hide unlisted products, Hide out-of-stock) depend on the product's status and inventory, so a change to those filters only becomes visible once the underlying product data is re-fetched too.
The cache is per query, not per product. If you toggle a customizer setting that changes which kind of query the widget runs (for example, turning Hide unlisted products on or off), that's a different cached entry — see What updates immediately vs after the cache below. Don't assume one refresh clears everything at once.
What updates immediately vs after the cache
Not every change is subject to the 5-minute wait. The dividing line is where you made the change.
Changes you make to the campaign / GWP block in the customizer — layout, copy, colors, and toggles like Hide unlisted products or Hide out-of-stock — take effect as soon as the new settings reach the storefront. They aren't gated by the 5-minute product cache itself.
There's a subtlety, though: a filtering toggle can only act on product data that's already loaded. So if you turn Hide unlisted products on, the toggle applies right away, but whether a specific product counts as "unlisted" is judged against the product data the widget currently holds — which may still be up to ~5 minutes old.
Changes you make to the product in Shopify admin — status, price, title, image, inventory, translations — flow through the ~5-minute cache. Until the window expires (or you force a refresh), the widget keeps showing the data it last fetched.
This is the common case behind "I changed it in Shopify but the storefront still shows the old value."
The fastest way to push a Shopify product change through without waiting is to re-sync the campaign (covered next). Re-syncing is the recommended action whenever you've edited a gift in Shopify and need it live sooner than the cache would deliver on its own.
Recipe: a status change that depends on the filter
A common sequence makes the interaction concrete. Say a gift is Active and showing in the widget:
- You change it to Unlisted in Shopify admin. With Hide unlisted products OFF (the default), the gift still appears once the cache refreshes — direct-by-ID lookup reaches unlisted products too.
- You then turn Hide unlisted products ON in the customizer. Now the gift is filtered out — but only after the product data refreshes and the widget sees it as unlisted.
- Later you switch the product back to Active in Shopify. After the cache expires, it reappears regardless of the toggle, because the filter no longer matches it.
Every Shopify-side step in that sequence is subject to the ~5-minute window; the customizer toggle itself is not, but it can only judge "unlisted" against whatever product data is currently loaded.
Recipe: combining Hide unlisted and Hide out-of-stock
The two filters work independently, so the gifts a shopper sees are whatever survives both. Use this as a quick reference when a gift unexpectedly appears or disappears:
| Hide unlisted products | Hide out-of-stock | What shows (from Active, Unlisted, Out-of-stock gifts) |
|---|---|---|
| OFF | OFF | All three |
| ON | OFF | Active + Out-of-stock |
| OFF | ON | Active + Unlisted |
| ON | ON | Only Active |
Combining filters can empty the widget. If every gift in a campaign is unlisted and you turn Hide unlisted products ON, nothing is left to show and the widget renders an empty state. The same happens if every gift is sold out with Hide out-of-stock ON. That's expected behavior, not a failure — turn the filter off, set a gift to Active, or restock to bring gifts back.
Country & language context
Gift data isn't fetched once globally — it's fetched per market and per language, so each shopper sees prices and translated titles appropriate to where they are.
- Per country: the widget requests gift data in the shopper's country context, so a gift's price reflects that market's pricing.
- Per language: translated titles and descriptions are fetched for the active storefront language.
Because each country/language combination is fetched separately, each one is also cached separately. The practical consequence when you're testing:
Testing the same change across multiple markets or languages can show different freshness at the same moment. The US/English view might already show your update while the FR/French view still shows the old value, simply because their separate caches expired at different times. This is expected — give each market/language its own ~5-minute window, or force a refresh per context.
If a price or translated title looks wrong, first confirm you're viewing the market/language you actually edited, then check whether that specific context's cache has had time to refresh.
How to force a refresh
When you can't wait out the window, here are your options, from most reliable to simplest:
Re-sync the campaign (recommended)
Go to your campaign list, find the campaign, and re-sync it. This pushes the latest campaign and gift data out to the storefront, which is the fastest way to make a Shopify product edit appear without waiting the full ~5 minutes.
Re-sync after you've changed a gift's status, price, image, inventory, or translations in Shopify and need it live now.
Reload in a fresh / incognito window
Open the storefront in an incognito or private window and reload. This avoids stale data held by your normal browser session and gives you a clean read of what shoppers are currently served.
Wait out the ~5-minute window
If the change isn't urgent, just wait. After about 5 minutes the next storefront load re-fetches the gift data automatically and the update appears on its own — no action needed.
Remember the cache is split per country and per language. If you re-sync or reload to verify, do it for the specific market and language you edited. A refresh in one context does not refresh the others.
Troubleshooting
Most "the storefront still shows the old value" reports come down to the cache. Find your symptom below.
| You changed... | Likely cause | Do this |
|---|---|---|
| Status (Active ↔ Unlisted) | Cached product data still has the old status | Wait ~5 min, then reload. Re-sync the campaign to speed it up. Confirm Hide unlisted products matches what you intend. |
| Price | Cached, or you're viewing a different market | Wait ~5 min or re-sync. Confirm you're viewing the same country you edited — pricing is per market. |
| Image | Storefront cache plus your browser's own image cache | Wait ~5 min or re-sync, then hard-reload (incognito) to clear the browser's own image cache. |
| Inventory / availability (in stock ↔ sold out) | Cached availability hasn't refreshed yet | Wait ~5 min or re-sync. If you use Hide out-of-stock, the product appears/disappears only after the fresh inventory loads. |
| Translation (title/description) | Cached, or you're viewing a different language | Wait ~5 min or re-sync. Confirm you're viewing the same language you translated — translations are cached per language. |
Related pages
Using unlisted products as gifts
Why search-hidden products can still appear as gifts, and the Hide unlisted products toggle.
Gift variants & availability
How variant inventory and out-of-stock filtering affect which gifts show.
Gift product not showing
Diagnose a gift that won't appear in the widget.
Widget not showing
Fix the case where the GWP widget itself doesn't render.
