Shipping and returns in structured data: OfferShippingDetails and MerchantReturnPolicy
Copy-ready JSON-LD for delivery tiers and return windows in the US, Canada, UK, EU and Australia, at store level and product level, and how to keep it consistent.
By the ConversionVector teamUpdated 13 min read
Contents
Direct answer: Put delivery and returns in structured data in two places. Store-wide: on your delivery and returns pages, nest a ShippingService (via hasShippingService) and a MerchantReturnPolicy (via hasMerchantReturnPolicy) under your Organization, as Google recommends. Per product: on each product page, add a compact shippingDetails (OfferShippingDetails) and hasMerchantReturnPolicy on the Offer, so an agent reading only that page gets the delivery cost, delivery time and return window. Give each destination country its own conditions in the currency the shopper pays in, mark up at least 14 days for UK and EU returns, and keep markup, Merchant Center, feeds and policy pages identical.
This guide is for developers, SEO leads and ecommerce managers at retailers selling in the US, Canada, the UK, the EU and Australia. It covers why delivery and returns markup matters to agents, where it goes, three copy-ready examples, the consumer-law points to reflect, how to keep every source consistent and how to test.
Last verified: 1 November 2026 against Google Search Central's shipping policy, return policy and merchant listing documentation, schema.org, Google Merchant Center help, OpenAI's product feed specification, UK and EU consumer legislation and the ACCC. Google updates these pages often, so check the linked versions before you ship changes.
Why this matters for agents
When an assistant compares two shops selling the same product, delivery cost, delivery time and returns terms are often what separates them. Most retailers publish these only as prose. In the Agent Commerce Index Q4 2026, 206 of 225 scored retailers (92%) did not state a shipping cost in structured data and 189 (84%) did not have returns terms in structured data. They were the third and fourth most common failures in the Index. For the rest of the product markup (price, identifiers, variants), see Product structured data for AI agents.
An agent can try to read your delivery page, but prose is ambiguous ("free delivery on most orders over 50, excluding some areas"). Structured data states the same thing as numbers, currencies and countries. Our Agent Conversion Score specification (v0.6) tests delivery and returns with these checks:
| Check | What it tests |
|---|---|
| OFF-04 | Shipping cost stated in structured data |
| OFF-05 | Delivery time stated on the product page |
| OFF-06 | Returns terms in structured data |
| LEG-09 | Shipping or delivery policy page is discoverable |
| LEG-10 | Returns policy page is discoverable |
| TRU-02 | Policy pages linked from product pages |
Store level or product level?
Google's documentation describes two layers (shipping policy, return policy, merchant listing):
| Store-wide policy | Product override | |
|---|---|---|
| Type | ShippingService under Organization via hasShippingService; MerchantReturnPolicy under Organization via hasMerchantReturnPolicy | OfferShippingDetails under Offer via shippingDetails; MerchantReturnPolicy under Offer via hasMerchantReturnPolicy |
| Where | "a single page on your site that describes the shipping policy of your business" (and likewise for returns) | Product pages where the product's policy differs, or where you have no store-wide policy |
| Properties | The full set: order-value, weight and item-count tiers, cut-off times, business days, seasonal overrides, separate change-of-mind and faulty-item fees | "a subset of the properties supported for organization-level" policies |
Google says of the store-wide policy: "You don't need to include it on every page of your site." It also lets an Offer point to the store-wide policy by @id alone, for example "hasMerchantReturnPolicy": { "@id": "https://example.com/returns#policy" }. That works for Google, which crawls your whole site and joins the pieces. An agent answering a shopper's question may fetch only the product page, and an @id on its own tells it nothing about the cost or the window.
Our recommendation is to do both: the full policy on the policy pages, and a compact Offer-level version on each product page stating the rate, delivery time and return window that apply to that product. Google treats product-level markup as stronger than Organization-level markup, so the two must match. This is our reading of how page-fetching agents work, not a documented requirement of any assistant.
Example 1: a store-wide shipping policy (US and Canada)
A US store. Standard delivery is free on US orders of $50 or more, otherwise $4.95. Canada pays a flat rate in Canadian dollars. Express is US only. Orders are dispatched Monday to Friday, with a 2pm Eastern Standard Time cut-off. Place this on your delivery page.
{
"@context": "https://schema.org",
"@type": "OnlineStore",
"@id": "https://www.example.com/#organization",
"name": "Example Outdoor",
"url": "https://www.example.com",
"hasShippingService": [
{
"@type": "ShippingService",
"@id": "https://www.example.com/delivery#standard",
"name": "Standard delivery",
"fulfillmentType": "https://schema.org/FulfillmentTypeDelivery",
"handlingTime": {
"@type": "ServicePeriod",
"cutoffTime": "14:00:00-05:00",
"businessDays": ["https://schema.org/Monday", "https://schema.org/Tuesday", "https://schema.org/Wednesday", "https://schema.org/Thursday", "https://schema.org/Friday"],
"duration": { "@type": "QuantitativeValue", "minValue": 0, "maxValue": 1, "unitCode": "DAY" }
},
"shippingConditions": [
{
"@type": "ShippingConditions",
"shippingDestination": { "@type": "DefinedRegion", "addressCountry": "US" },
"orderValue": { "@type": "MonetaryAmount", "minValue": 0, "maxValue": 49.99, "currency": "USD" },
"shippingRate": { "@type": "MonetaryAmount", "value": 4.95, "currency": "USD" },
"transitTime": {
"@type": "ServicePeriod",
"duration": { "@type": "QuantitativeValue", "minValue": 3, "maxValue": 5, "unitCode": "DAY" }
}
},
{
"@type": "ShippingConditions",
"shippingDestination": { "@type": "DefinedRegion", "addressCountry": "US" },
"orderValue": { "@type": "MonetaryAmount", "minValue": 50, "currency": "USD" },
"shippingRate": { "@type": "MonetaryAmount", "value": 0, "currency": "USD" },
"transitTime": {
"@type": "ServicePeriod",
"duration": { "@type": "QuantitativeValue", "minValue": 3, "maxValue": 5, "unitCode": "DAY" }
}
},
{
"@type": "ShippingConditions",
"shippingDestination": { "@type": "DefinedRegion", "addressCountry": "CA" },
"shippingRate": { "@type": "MonetaryAmount", "value": 12.95, "currency": "CAD" },
"transitTime": {
"@type": "ServicePeriod",
"duration": { "@type": "QuantitativeValue", "minValue": 5, "maxValue": 8, "unitCode": "DAY" }
}
}
]
},
{
"@type": "ShippingService",
"@id": "https://www.example.com/delivery#express",
"name": "Express delivery",
"shippingConditions": [
{
"@type": "ShippingConditions",
"shippingDestination": { "@type": "DefinedRegion", "addressCountry": "US" },
"shippingRate": { "@type": "MonetaryAmount", "value": 14.95, "currency": "USD" },
"transitTime": {
"@type": "ServicePeriod",
"duration": { "@type": "QuantitativeValue", "minValue": 1, "maxValue": 2, "unitCode": "DAY" }
}
}
]
}
]
}
Points to note, all from Google's shipping policy documentation:
- Tiers by order value.
orderValuewithminValueandmaxValuedefines each band. Give at least one of the two: a missingminValuedefaults to 0 and a missingmaxValueto infinity. - Free delivery is a
shippingRatevalueof0. - Overlapping conditions. If more than one condition applies, Google uses the lowest shipping cost; if the costs are the same, the fastest shipping speed.
- No destination means the conditions apply "to all shipping destinations worldwide", so always set
shippingDestination. - Regions and postcodes. For
addressRegion, "Google Search only supports the US, Australia, and Japan". Postal codes are supported for Australia, Canada and the US. Don't give both in one region. - Cut-off time uses ISO 8601 with a UTC offset. Orders after the cut-off add a day to the delivery estimate. A fixed offset does not follow daylight saving, so update it when the clocks change if that matters to your estimate.
- Countries or baskets you don't serve. Set
doesNotShiptotrueon the conditions concerned. - Seasonal rates such as a Christmas cut-off can use
seasonalOverrideon the conditions to limit when they apply.
Example 2: a store-wide returns policy (UK, EU and Australia)
A UK store. Change-of-mind returns are accepted for 30 days in the UK and the EU, with £3.95 or €4.50 return postage deducted, and faulty items come back free. Australian change-of-mind returns go to a local address and the shopper arranges postage. Place this on your returns page.
{
"@context": "https://schema.org",
"@type": "OnlineStore",
"@id": "https://www.example.co.uk/#organization",
"name": "Example Outdoor",
"url": "https://www.example.co.uk",
"hasMerchantReturnPolicy": [
{
"@type": "MerchantReturnPolicy",
"@id": "https://www.example.co.uk/returns#gb",
"applicableCountry": "GB",
"returnPolicyCountry": "GB",
"returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
"merchantReturnDays": 30,
"returnMethod": ["https://schema.org/ReturnByMail", "https://schema.org/ReturnInStore"],
"refundType": "https://schema.org/FullRefund",
"itemCondition": "https://schema.org/NewCondition",
"returnLabelSource": "https://schema.org/ReturnLabelDownloadAndPrint",
"customerRemorseReturnFees": "https://schema.org/ReturnShippingFees",
"customerRemorseReturnShippingFeesAmount": { "@type": "MonetaryAmount", "value": 3.95, "currency": "GBP" },
"itemDefectReturnFees": "https://schema.org/FreeReturn",
"merchantReturnLink": "https://www.example.co.uk/returns"
},
{
"@type": "MerchantReturnPolicy",
"@id": "https://www.example.co.uk/returns#eu",
"applicableCountry": ["IE", "FR", "DE", "NL", "BE", "ES", "IT"],
"returnPolicyCountry": "GB",
"returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
"merchantReturnDays": 30,
"returnMethod": "https://schema.org/ReturnByMail",
"refundType": "https://schema.org/FullRefund",
"customerRemorseReturnFees": "https://schema.org/ReturnShippingFees",
"customerRemorseReturnShippingFeesAmount": { "@type": "MonetaryAmount", "value": 4.50, "currency": "EUR" },
"itemDefectReturnFees": "https://schema.org/FreeReturn",
"merchantReturnLink": "https://www.example.co.uk/returns"
},
{
"@type": "MerchantReturnPolicy",
"@id": "https://www.example.co.uk/returns#au",
"applicableCountry": "AU",
"returnPolicyCountry": "AU",
"returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
"merchantReturnDays": 30,
"returnMethod": "https://schema.org/ReturnByMail",
"customerRemorseReturnFees": "https://schema.org/ReturnFeesCustomerResponsibility",
"itemDefectReturnFees": "https://schema.org/FreeReturn",
"merchantReturnLink": "https://www.example.co.uk/returns"
}
]
}
Points to note, from Google's return policy documentation:
- Required: either
applicableCountryplusreturnPolicyCategory(andmerchantReturnDaysfor a finite window), ormerchantReturnLink. Give both where you can. applicableCountryis where the product is sold and returned from, up to 50 countries.returnPolicyCountryis where the item has to be sent, which can be a different country.merchantReturnDaysis "the number of days from the delivery date that a product can be returned".- Fees.
FreeReturn,ReturnFeesCustomerResponsibility(the shopper arranges and pays for the return) orReturnShippingFeeswith a non-zeroreturnShippingFeesAmount. Split change-of-mind and faulty-item fees withcustomerRemorseReturnFeesanditemDefectReturnFees. - Seasonal changes such as an extended Christmas window use
returnPolicySeasonalOverridewith a start date, end date and the window that applies. - Restocking fees use
restockingFee: a number for a percentage of the price paid, or aMonetaryAmountfor a fixed fee.
Example 3: the compact product-level version
On each product page, nest the facts that apply to that product inside the Offer. This uses the subset Google supports at product level (merchant listing documentation), and it is what a page-fetching agent sees.
"offers": {
"@type": "Offer",
"price": 149.00,
"priceCurrency": "GBP",
"availability": "https://schema.org/InStock",
"shippingDetails": {
"@type": "OfferShippingDetails",
"shippingRate": { "@type": "MonetaryAmount", "value": 0, "currency": "GBP" },
"shippingDestination": { "@type": "DefinedRegion", "addressCountry": "GB" },
"deliveryTime": {
"@type": "ShippingDeliveryTime",
"handlingTime": { "@type": "QuantitativeValue", "minValue": 0, "maxValue": 1, "unitCode": "DAY" },
"transitTime": { "@type": "QuantitativeValue", "minValue": 1, "maxValue": 3, "unitCode": "DAY" }
}
},
"hasMerchantReturnPolicy": {
"@type": "MerchantReturnPolicy",
"applicableCountry": "GB",
"returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
"merchantReturnDays": 30,
"returnMethod": "https://schema.org/ReturnByMail",
"returnFees": "https://schema.org/ReturnShippingFees",
"returnShippingFeesAmount": { "@type": "MonetaryAmount", "value": 3.95, "currency": "GBP" }
}
}
Note the different shape. At product level, delivery time sits in deliveryTime as a ShippingDeliveryTime, with handlingTime and transitTime as QuantitativeValue whole numbers of days. At store level it is a ServicePeriod with a duration. Do not mix the two.
Google's product-level rules worth knowing:
- One rate per block. "You can only specify one shippingRate per OfferShippingDetails property." For standard and express, or several countries, use an array of
OfferShippingDetails. - Same currency as the offer. The shipping rate's currency "must be the same as the currency of the offer". If the page serves a different currency per country, serve the matching block with each version rather than listing every currency on every page.
- One delivery time. Don't provide more than one
deliveryTimeper block. - Product-level returns win over store-wide returns. "If you provide both organization-level and product-level return policy markup, Google defaults to the product-level return policy."
Market rules to reflect in your markup
Markup describes your policy. It cannot make a policy lawful. These are the points that change what you should mark up. This is a simplified summary, not legal advice.
| Market | What to reflect | Source |
|---|---|---|
| UK | For most distance sales of goods, the consumer can cancel until the end of 14 days after the day the goods arrive, then has 14 days from telling you to send them back. The consumer pays the direct cost of returning goods only if you said so beforehand. Narrow exceptions include personalised and perishable goods, and unsealed hygiene items | Consumer Contracts Regulations 2013, regs. 28, 30 and 35 |
| EU | The Consumer Rights Directive gives a 14-day withdrawal period from delivery for distance contracts, then 14 days to send the goods back. The consumer bears only the direct cost of return, and only if informed beforehand | Directive 2011/83/EU, Articles 9 and 14 |
| Australia | A business does not have to refund a change of mind, but if it has a change-of-mind policy it must follow it. Faulty goods are covered by the consumer guarantees, and the ACCC warns against statements such as "no refunds on sale items", time limits on returning faulty goods, and restocking or delivery fees on faulty returns | ACCC: repair, replace, refund, cancel; ACCC sweep, 4 February 2025 |
| US and Canada | Return windows are set mainly by your own policy, subject to state and provincial rules. State the window, fees and method clearly | Your published policy |
In practice:
- UK and EU: set
merchantReturnDaysto at least 14 for change-of-mind returns. If you offer longer (30, 60 or 100 days), mark up the longer window. Only show a return postage fee if your terms tell the shopper they pay it. - Faulty items: use
itemDefectReturnFeesFreeReturnwhere you cover faulty-goods returns. In the UK, a trader repairing or replacing faulty goods must "bear any necessary costs incurred in doing so (including in particular the cost of any labour, materials or postage)" (Consumer Rights Act 2015, s. 23), and the ACCC says Australian businesses must reimburse reasonable return costs for faulty products. - Australia: treat your
merchantReturnDaysas the change-of-mind window and say on the page that it does not limit rights for faulty goods. - Restocking fees: apply
restockingFeeonly to change-of-mind returns, never to faulty ones.
Keep every source saying the same thing
Google and agents can read the same policy from several places. Google's merchant listing documentation gives the order of precedence, from strongest to weakest:
- Product-level feeds submitted in Merchant Center
- Settings in the Content API for Shopping
- Settings in Merchant Center or Search Console
- Product-level merchant listing markup
- Organization-level markup
So "if you provide both shipping policy markup on your site and shipping policy settings in Search Console, Google will only use the information provided in Search Console" (Google), and the same applies to returns. Merchant Center's own return policy help asks you to "Confirm that the return policies are consistent in Merchant Center and across your website", and Google verifies each policy before using it. If you want Google's agentic checkout, Merchant Center return policies are not optional: Google's UCP guide says "You must define your return policies in Merchant Center, as it is a Merchant of Record requirement and will be referenced on the checkout screen."
Other channels have their own fields:
| Concept | Google Merchant Center | OpenAI product feed | Structured data |
|---|---|---|---|
| Shipping cost | Shipping settings or the shipping attribute | shipping_price ("Omitted or empty means unknown, not free shipping") | shippingRate |
| Accepts returns | Return policy settings or the returns attribute | accepts_returns | returnPolicyCategory |
| Return window | Return window in settings | return_deadline_in_days | merchantReturnDays |
| Policy URL | Return policy URL in settings | return_policy | merchantReturnLink |
Sources: OpenAI Products specification, Google UCP Merchant Center guide, Merchant Center shipping attribute. OpenAI's spec adds that a return policy URL "does not set or override" accepts_returns, so send the field as well as the link. For the feed side, see Product feeds for AI shopping.
Generate all of these from one policy record, so a change to your returns window updates the policy page, the markup, Merchant Center and every feed together.
How to test
- Validate syntax with Google's Rich Results Test and the Schema Markup Validator.
- Check what an agent receives. Fetch a product page without a browser (for example with
curl) and confirm the JSON-LD withshippingDetailsandhasMerchantReturnPolicyis in the server response, not injected by a tag manager after load. - Compare with the page. Rates, windows and fees in the markup must match the visible delivery and returns text, and what your checkout charges.
- Compare with Merchant Center and your feeds. Same window, same fees, same countries.
- Run the free score, which checks OFF-04, OFF-05 and OFF-06 on your own product pages.
Common mistakes
- Prose only. One of the most common failures in the Index. An agent cannot compare what it has to guess, and a delivery cost it cannot see is a reason to pick another shop (see agent checkout friction).
- No destination country. Without
shippingDestination, Google reads store-wide conditions as worldwide. - One USD block for Canada. Give each country the currency the shopper pays in, and at product level match the offer's currency.
- A 7-day window for UK or EU change-of-mind returns. Shorter than the statutory 14 days.
- An
@idreference and nothing else on the product page. Fine for Google, empty for an agent that reads only that page. - Markup that disagrees with Merchant Center. Google uses the stronger source; other agents may read the weaker one. Both should say the same.
- Injecting policy markup with a tag manager. Page-fetching agents never see it.
- Mixing store-level and product-level shapes.
ServicePeriodbelongs at store level,ShippingDeliveryTimeat product level.
Sources
- Google Search Central, Merchant shipping policy (ShippingService) structured data, last updated 8 September 2026, read 1 November 2026
- Google Search Central, Merchant return policy (MerchantReturnPolicy) structured data, last updated 8 September 2026, read 1 November 2026
- Google Search Central, Merchant listing (Product, Offer) structured data, last updated 8 September 2026, read 1 November 2026
- schema.org, ShippingService, OfferShippingDetails and MerchantReturnPolicy, read 1 November 2026
- Google for Developers, UCP: Merchant Center setup, read 1 November 2026
- Google Merchant Center Help, Shipping attribute and Set up your return policies for Shopping ads and free listings, read 1 November 2026
- OpenAI, Products specification, read 1 November 2026
- legislation.gov.uk, Consumer Contracts (Information, Cancellation and Additional Charges) Regulations 2013, regs. 28, 30 and 35, and Consumer Rights Act 2015, s. 23, read 1 November 2026
- EUR-Lex, Directive 2011/83/EU on consumer rights, Articles 9 and 14, read 1 November 2026
- ACCC, Repair, replace, refund, cancel and ACCC sweep uncovers concerning online shopping return policies (4 February 2025), read 1 November 2026
- ConversionVector, Agent Commerce Index Q4 2026 (CC BY 4.0) and Agent Conversion Score specification v0.6
Questions
- Should shipping and returns go on the Organization or the Offer?
- Google recommends a store-wide policy under Organization (ShippingService via hasShippingService, MerchantReturnPolicy via hasMerchantReturnPolicy) on one policy page, with Offer-level markup only where a product differs. Because an agent answering a shopper may read only the product page, we also recommend a compact Offer-level shippingDetails and hasMerchantReturnPolicy on each product page, generated from the same policy record so the two never disagree.
- How do I mark up the UK and EU 14-day cancellation right?
- For UK and EU countries, use returnPolicyCategory MerchantReturnFiniteReturnWindow with merchantReturnDays of at least 14, and applicableCountry set to the countries concerned. The law gives most distance buyers 14 days from delivery to cancel, then 14 days from cancelling to send the goods back. If your commercial window is longer, mark up the longer window. This is not legal advice.
- What if Merchant Center and my markup disagree?
- Google uses an order of precedence, from strongest to weakest: product-level feeds in Merchant Center, Content API settings, settings in Merchant Center or Search Console, product-level markup, then Organization-level markup. Other agents may read only your page, so a mismatch means different readers get different answers. Keep every source identical.
- How do I mark up free shipping over a threshold?
- At store level, use a ShippingService with two ShippingConditions per destination: one with an orderValue range below the threshold and the paid rate, and one from the threshold upwards with a shippingRate value of 0. At product level, Google allows one shippingRate per OfferShippingDetails, so give the rate that applies to that product bought on its own.
- How do I mark up a final-sale product?
- Add an Offer-level hasMerchantReturnPolicy with returnPolicyCategory MerchantReturnNotPermitted, and say so on the product page. Check the law first: in the UK and EU the 14-day cancellation right still covers most goods bought at a distance, with narrow exceptions such as personalised or perishable items, and in Australia the ACCC says statements like 'no refunds on sale items' can mislead about rights for faulty goods.
Published . Last updated . More in Structured data and product feeds and the guide library.
Related guides
- Structured data and product feeds
Product structured data for AI shopping agents: the complete JSON-LD guide
Valid JSON-LD for Product, Offer, AggregateRating, MerchantReturnPolicy, OfferShippingDetails and ProductGroup, and how AI shopping agents use it.
Updated · 16 min read
- Structured data and product feeds
Product feeds for AI shopping: ChatGPT, Google AI Mode, Copilot and Perplexity
How your catalogue reaches ChatGPT, Google AI Mode and Gemini, Microsoft Copilot and Perplexity in October 2026: feed routes, markets and a feed checklist.
Updated · 13 min read
- Agent checkout
Can an AI agent buy from your shop? Removing checkout friction for agents
Where AI agents stall between product page and payment, what the Agent Commerce Index found, and a ranked agent checkout audit you can run yourself.
Updated · 12 min read