Short answer. Shopify's built-in product markup does not emit shippingDetails or hasMerchantReturnPolicy, so on a stock theme Search Console reports both as missing. They are recommended fields, not required ones, and your products stay valid without them. But Google reads shipping and returns from four sources in a fixed order, and settings in Merchant Center or Search Console outrank anything you paste into your theme.
This finding has a strange property: the advice that clears the warning and the advice that changes what shoppers see are not the same advice. The usual advice is to paste a shipping block into your product JSON-LD. That is a real fix for a real symptom β and for most Shopify stores it is aimed at the system Google is least likely to be reading.
What Shopify actually puts inside your offer
Shopify generates product markup through the Liquid structured_data filter, and its documented output is short. Inside the offers object it emits exactly six properties:
"offers": {
"@id": "/products/crocodile-tears?variant=39888242344001#offer",
"@type": "Offer",
"availability": "http://schema.org/OutOfStock",
"price": "56.00",
"priceCurrency": "CAD",
"url": "https://β¦/products/crocodile-tears?variant=39888242344001"
}
There is no shippingDetails, no hasMerchantReturnPolicy, and no priceValidUntil. The fields are not missing because someone misconfigured the store β they are absent by construction on any theme using the built-in filter, whose documented output offers no option to add them. That is why the warning lands on stores that have never touched their theme code, and why it covers the whole catalogue rather than a handful of products.
Recommended, not required β so what does the warning cost you?
Google's merchant listing structured data documentation lists both fields as recommended properties of Offer. The required set is much smaller: name, image and offers on the product, and a price plus a currency inside the offer.
Search Console reflects that split in its layout. In the rich result reports, critical issues appear in a table called "Why items are invalid" and non-critical ones in a table called "Improve item appearance" β and Google's definition is explicit: "A valid item is an item that doesn't have any critical issues and can appear on Google as a rich result." So a product flagged only for these two fields is still valid, still eligible, still able to show as a rich result.
So the cost is narrower than the alarm suggests: you lose the delivery and returns annotations Google can attach to your listing β the ones sitting under a competitor's product and not under yours. That is a conversion problem, not a disappearance, and a different class of failure from a block Google cannot parse at all, which it discards outright along with everything inside it. We covered that one in "Unparsable structured data" in Search Console.
Want to know what your product markup is actually emitting today? We read the offer object on every product page in your catalog and list what is present, what is absent, and what contradicts your live page β read-only, no admin access, about 2 minutes. β free scan
Google reads shipping and returns from four places, in a fixed order
This is the part the pages answering this query tend to skip, and it is the reason the theme fix so often disappoints. Google's documentation for both return policy structured data and shipping policy structured data sets out an order of precedence, strongest first:
- Content API for Shopping account-level settings
- Settings in Merchant Center or Search Console
- Product-level merchant listing markup β the snippet you paste into your theme
- Organization-level markup
Google states the consequence directly: "if you provide both return policy markup on your site and return policy settings in Search Console, Google will only use the information provided in Search Console." The shipping documentation says the same about shipping. If your store is connected to Merchant Center β which the Google & YouTube channel requires β then level 2 is already occupied, and level 3 is the level you are editing.
That does not make the theme edit pointless: it clears the warning, it helps engines that read the page directly, and it is the only route open to a store with neither a Merchant Center account nor Search Console settings. But it explains a pattern that reads like a bug and is not one β the snippet goes in, the warning clears, and nothing about the listing changes.
Google's own recommendation is not the snippet everyone pastes
If you do go the markup route, Google recommends a different shape from the one in circulation. On the merchant listing page, for both fields, the guidance is the same: "We recommend you provide a global shipping policy for your business under Organization markup instead", and likewise for returns. A standard policy for the whole business belongs in Organization markup β ShippingService under hasShippingService, MerchantReturnPolicy for returns β while per-product Offer markup exists to override that standard policy for a product that genuinely differs. Google also notes that the per-Offer form supports a more limited set of properties than the Organization-level one.
Which means the common Shopify approach β a shipping block duplicated into every product page by a Liquid loop β is the exception form applied as the rule, using the weaker vocabulary, at the lowest priority level.
There is also a newer route, announced in Google's November 2025 post More ways to share your shipping and returns policies with Google: set the policies in Search Console itself, under Settings > Shopping > Shipping and returns. Its help page states that "You don't need to create a Merchant Center account to configure shipping and returns" β but also that "Shipping and return policies created or edited in Merchant Center won't be available in Search Console, and can only be managed in Merchant Center." Connect the Google & YouTube channel, and that route closes behind you.
The Shopify trap: only the General shipping profile syncs
If you resolve this in Merchant Center β the right answer for most Shopify stores β there is one Shopify-specific failure waiting underneath it, and it is documented by Shopify rather than by Google. From the Google & YouTube channel requirements: "Only shipping rates in your General shipping profile can sync to Google Merchant Center. If you use custom shipping profiles, then rates will sync incorrectly with Google Merchant Center and cause errors."
Custom shipping profiles are ordinary Shopify housekeeping β one for oversized items, one for a dropshipped range, one for a supplier with its own delivery times. The moment a product moves into one, the rate Google receives stops matching the rate the shopper is charged. From Shopify's side nothing is wrong: the rates are correct in the store, they are simply not the rates being sent.
One thing worth checking before you edit anything: Merchant Center can work out a return policy without you uploading one, and Google's return policy documentation describes the "For most items" annotation as the sign that it did. Your listings may already be showing returns information while Search Console still reports the field missing from your markup β this page's whole argument, visible in one symptom.
How to check your own store in 5 minutes
- Read your own markup. Open any product page, view source, find the JSON-LD block, and look inside
offers. Six properties and no shipping or returns means you are on the stock filter output. - Check which table the issue sits in. In Search Console, open the Merchant listings report and confirm the two fields appear under "Improve item appearance" and not under "Why items are invalid". If they are in the second table, something else is wrong and this article is not your problem.
- Find out which source is authoritative for you. Do you have a Merchant Center account connected via the Google & YouTube channel? Is there already a policy under Settings > Shopping > Shipping and returns in Search Console? Whichever exists outranks the markup on your page.
- Compare the rate Google has against the rate you charge. Open your Merchant Center shipping settings and check them against what a shopper actually pays at checkout for the same product and destination.
- Open Settings > Shipping and delivery in Shopify. Every product sitting in a custom profile rather than the General one is a rate Google is not receiving correctly.
The fix, depending on which system you are actually on
If you use the Google & YouTube channel, set shipping and returns in Merchant Center and treat that as the source of truth. Keep the rates Google needs in the General shipping profile, or set them manually in Merchant Center instead of importing β Shopify offers both, and manual is the safer choice once custom profiles exist. Markup in your theme on top of this is tidiness, not the fix.
If you have no Merchant Center account, use Settings > Shopping > Shipping and returns in Search Console. It outranks markup and it is far less fragile than theme code.
If you want the markup anyway β for engines that read the page directly, or because you have neither of the above β declare the standard policy once in Organization markup, sitewide, and reserve per-product Offer markup for products that genuinely deviate. Whatever you declare has to match what you actually charge. A hardcoded "free shipping" block on a store that charges for shipping is worse than the warning you started with: it puts a promise in front of the shopper that checkout will break.
Why this one comes back
Four sources, a documented order between them, and no screen anywhere that tells you which one Google used today. That is why this is not a task you complete. A theme update replaces the file holding your markup; a new supplier arrives and someone creates a custom shipping profile; someone edits the rates in Merchant Center and the store's own rates drift away from them. Each is routine work done correctly, and none of it produces a warning in Shopify.
It is also why we grade this one honestly rather than dramatically: our scan flags an offer carrying neither shippingDetails nor hasMerchantReturnPolicy as informational, not critical. A product with no shipping annotation is still selling; a product carrying a phantom noindex is not. The value in watching this one is not the alarm β it is knowing, without going to look, that today's answer is still last month's.
Next in this cluster
- priceValidUntil on Shopify: the other field the built-in filter leaves out
- Missing GTIN, MPN or brand: how Google throttles a listing without disapproving it
- "Unparsable structured data": when Google discards the whole block instead
- Every status in Search Console's Page indexing report, explained for Shopify
Not sure what your product markup is telling Google right now?
Scan my store for free