Make a row for every offer and destination you sell: the variant, the country, whether you ship there, the rate, handling days, transit days, the return window, who pays for returns, and any exception such as final sale or open box. Store-wide policies can stay store-wide. But anything that differs for one product, one size or one country has to be written on that offer, because nothing else will carry it.
In 1,620 Shopify catalog results, 1,589 records linked to a store-wide refund policy. No variant object had a field for shipping cost, delivery time or return window. Only 31 descriptions stated a delivery time in prose.
What the catalog record carried
On October 26, 2026 we saved 162 searches from Shopify’s agent catalog, 10 results each, all from one unpersonalized context. Each result came back with its first variant. Here’s what those variants carried about shipping and returns:
| What we looked for | Where it was | Results (of 1,620) |
|---|---|---|
| Link to a refund policy | Store-level seller link | 1,589 |
| Link to a shipping policy | Store-level seller link | 1,535 |
| Shipping cost, delivery time or return window | Variant field | None; the variant has no such field |
| A stated shipping, handling or delivery time | Description text | 31 |
| “Final sale” or “no returns” | Description text | 5 |
So for nearly every product, the only offer-level shipping or returns facts sit in the description, and few descriptions state them. Everything else sits behind a link to a page that covers the whole store. Shopify’s documentation points the same way. Its agent discovery files carry store policies, and its Agentic listing insights score “shop policy completeness” for shipping, returns and refund policies. In the pages we read, Shopify documents no shipping or returns field for an individual offer (checked on 2026-10-27).
The exception that the store-wide link hides
The clearest case was an open-box pair of heated insoles, position 6 for “heated insoles rechargeable for ice fishing”. Its description says:
Because of the deep discount, this is a final sale. This product is not eligible for refunds or exchanges and is not covered by our warranty.
The record also carried the store’s standard refund-policy link, the same kind of link as nearly every other result. An agent that reads the link and skips the description could tell a shopper the insoles are returnable. We didn’t open that store’s refund policy, so we can’t say whether it mentions open-box items. The point is that the exception lived in one place only, the description, and the generic link pointed somewhere else.
Four other descriptions carried the same kind of exception: a clearance pet carrier (“final sale and not eligible for return or exchange”), a matcha whisk, a set of knitting needles and a runner’s gift box. Each is a per-offer rule that a store-wide policy can’t express.
Three passport holders, three promises
Destination is where offer-level facts matter most. Here are three listings from the search “rfid blocking passport holder for family of four”. All three were priced in USD in our snapshot. The shipping facts come from each description, mapped to the fields a shopper needs:
| Field | Position 4 | Position 5 | Position 8 |
|---|---|---|---|
| Destinations named | Australia and New Zealand | U.S. | Worldwide, “AUS, NZ, UK, USA & CAN” |
| Rate | Free tracked shipping (AU and NZ) | Free on orders over $99; cost below that not stated | Free |
| Handling and transit | 7–10 business days (AU and NZ) | Processed in 1–2 business days; delivery 2–5 business days after dispatch | About 24 hours to pack; up to 7–15 business days for delivery |
| Returns | “30-Day Returns” | “30-day no-questions-asked return policy” | 14-day money-back guarantee if the order arrives damaged, doesn’t arrive or isn’t as described |
Read it as a US shopper and the gaps show:
- Position 4 prices in USD but names only Australian and New Zealand shipping. US shipping cost and time are unknown from the record. That doesn’t mean the store won’t ship to the US. It means the listing doesn’t say.
- Position 5 has the most complete block, but its $69.90 first variant sits below the $99 free-shipping line, and the cost under $99 isn’t stated.
- Position 8 looks like it offers returns. Read closely, its 14 days covers damaged, lost or misdescribed orders, which isn’t the same as a change-of-mind return window.
None of these listings is wrong. Each answers a different question, and none answers “Can I get this in Ohio by Friday, and send it back if it doesn’t fit?”
The policy-to-offer mapping template
The template has one row per offer × destination. An offer is a specific variant at a specific price, which is also how Schema.org frames it: a ProductGroup isn’t offered for sale itself; its variant products are. The template is our proposal, and no platform requires this exact layout.
The fields
| Field | What to record | Google markup (offer level) | OpenAI product feed |
|---|---|---|---|
| Offer | Variant, SKU, condition (new, open box) | Offer, itemCondition | Item and variant fields |
| Destination | Country, plus region or postal codes if they differ | shippingDestination (two-letter country) | Country in a shipping representation your integration accepts (confirm setup; an omitted shipping_price means unknown, not free) |
| Ships here? | Yes, or an explicit no | Not on the offer-level list we read; Schema.org has doesNotShip | Not documented |
| Rate | Amount and currency, or free | shippingRate (currency must match the offer) | shipping_price; omitted means unknown, not free |
| Handling days | Minimum to maximum, in business days | deliveryTime.handlingTime | Not part of the supported tuple |
| Transit days | Minimum to maximum, in business days | deliveryTime.transitTime | Not part of the supported tuple |
| Return policy | Window, not permitted, or unlimited | returnPolicyCategory | accepts_returns (true or false) |
| Return window | Days, and when the clock starts | merchantReturnDays | return_deadline_in_days |
| Return cost | Free, customer pays, or a fixed fee | returnFees, returnShippingFeesAmount | Not documented as a field |
| Exceptions | Final sale, open box, custom, oversized | A separate return policy on that Offer | accepts_returns=false for final sale |
| Source and check date | Which policy page and when you last checked | — | return_policy URL |
Two rules make the template work:
- Write “no” explicitly. If you don’t ship to Canada, make a Canada row that says “doesn’t ship”. In OpenAI’s feed, a missing shipping price means unknown, not free. An unwritten destination is a question, and a careful agent won’t guess the answer.
- Every exception gets its own row. Final sale, open box, made to order, and items with different shipping (oversized, freight) can’t hide in a store-wide policy.
A filled example
Here’s the template for a labelled hypothetical store selling a travel wallet in two conditions. The rates and windows are invented for the example.
| Offer and destination | Shipping | Returns | Source, checked |
|---|---|---|---|
| Wallet, new · United States | $5.00, free over $60; handling 1–2 days; transit 3–6 business days | 30 days from delivery; customer pays return shipping | /policies/shipping, /policies/refund · 2026-10-27 |
| Wallet, new · Canada | $12.00; handling 1–2 days; transit 5–10 business days | 30 days from delivery; customer pays return shipping | Same · 2026-10-27 |
| Wallet, new · Australia | Doesn’t ship | — | Same · 2026-10-27 |
| Wallet, open box · United States | $5.00; handling 1–2 days; transit 3–6 business days | Final sale: not returnable, no warranty | Product description · 2026-10-27 |
The open-box row is the reason the template exists. The same wallet has two return rules, and only an offer-level row keeps them apart.
Where each platform takes these facts
Checked on 2026-10-27; re-check before acting.
| Route | Store-wide | Per offer | Conditions |
|---|---|---|---|
| Google Search markup | ShippingService and MerchantReturnPolicy under Organization | shippingDetails and hasMerchantReturnPolicy under Offer, which support fewer properties | Merchant Center and Search Console settings take precedence over markup |
| Google Merchant Center | Account shipping and return settings | Offer-level shipping overrides account level; Store Quality asks for both cost and transit time | Store Quality badges depend on more than these fields |
| Google UCP checkout | Return policies defined in Merchant Center; must include return cost, return window and a policy link | return_policy_label to limit a policy to some products, or a returns attribute per product |
Final-sale and special-shipping items are ineligible; select merchants only. Markets conflict across Google’s pages (one names the US, Canada and Australia; onboarding says the US first) |
| OpenAI product feed | return_policy URL |
shipping_price or a shipping tuple; accepts_returns; return_deadline_in_days |
Shipping representation depends on your integration setup |
| Shopify agent catalog | Seller links to refund and shipping policies; policies in /agents.md | No offer-level field documented; the description carries it | Policy completeness appears in Agentic listing insights |
Precedence matters on Google. Its order, strongest first, is the Content API for Shopping, then settings in Merchant Center or Search Console, then product-level merchant listing markup, then organization-level markup. If your Merchant Center settings say 30 days and your product markup says final sale, check which one Google is using before you assume the markup wins. Google’s merchant listing page also says that when both organization-level and product-level return markup exist, it defaults to the product-level policy. That’s the markup-only case, below Merchant Center settings.
If your feed price and page price disagree, see product feed price mismatches. Shipping costs have the same problem, because the total is what the shopper pays. For the markup itself, see product schema markup. For the checkout routes, see Google UCP checkout and the ChatGPT product feed.
Put the exceptions in the text
Until a platform carries offer-level policy fields all the way to the agent, the description is the one place every route reads. Keep it short and specific:
Ships to the US and Canada only. US: $5.00 (free over $60), dispatched in 1–2 business days, arrives in 3–6 business days. Returns: 30 days from delivery; you pay return shipping. This open-box unit is final sale.
That paragraph answers the constraint a shopper is most likely to state: where it can go, how fast, and whether it can come back. To test one product against a shopper’s full brief, use constraint coverage.
How we checked
On October 27 we reopened 162 saved Shopify agent-catalog responses from October 26, 2026, each an unpersonalized search returning the top 10 results (1,620 result occurrences, first variant only). A script counted the seller link types on each first variant and listed the variant’s fields. A second script searched each description for shipping, handling and delivery times, return windows, and final-sale or no-return wording. We reviewed the 35 delivery-time matches by hand and removed 4 false positives, such as battery runtimes. We then read the passport-holder and heated-insole descriptions in full. We didn’t open any linked policy page or product page, and we’ve withheld store names and contact details. Official pages were read on October 27, 2026.
Your next step
List every offer you sell that breaks your standard policy: open box, clearance, custom, oversized, or a country you don’t ship to. Give each one a row in the template. Write the exception into that product’s description, and set it as an offer-level policy in each feed or markup route you use. Then re-check your Merchant Center settings so they don’t override what you just wrote.