What OfferShippingDetails is
Per Schema.org v30.0, OfferShippingDetails 'represents information about shipping destinations.' Multiple OfferShippingDetails objects can attach to one Offer to represent different rates, costs, and delivery times across destinations. Inheritance: Thing > Intangible > StructuredValue > OfferShippingDetails. Key properties: shippingRate (MonetaryAmount or ShippingRateSettings), shippingDestination (DefinedRegion), deliveryTime (ShippingDeliveryTime), doesNotShip (Boolean), shippingOrigin (DefinedRegion).
What Google documents, and the AI Overviews claim
Google's merchant shipping policy documentation splits shipping in two. Standard shipping for the business goes in a ShippingService nested under Organization with hasShippingService, on a single page; you don't need it on every page. A product with non-standard shipping gets OfferShippingDetails directly under its Offer, which supports a subset of the Organization-level properties and overrides the standard policy for that product. Some SEO publications go further and say Google AI Overviews demands shippingDetails on every product. No Google documentation says that, so this page doesn't repeat it.
OfferShippingDetails fields
The properties Google requires for the shipping details enhancement and Schema.org defines: shippingRate (a MonetaryAmount with value and currency; Schema.org also allows ShippingRateSettings, but Google's Offer-level documentation types the rate as MonetaryAmount), shippingDestination (a DefinedRegion with addressCountry — ISO 3166-1 alpha-2 — and optionally addressRegion or postalCode ranges), deliveryTime (a ShippingDeliveryTime with handlingTime QuantitativeValue and transitTime QuantitativeValue, both expressed in days).
JSON-LD example — OfferShippingDetails inside Offer
The block below shows shippingDetails inside the Offer sub-object of a Shopify Product block: the product-level form, for a product whose shipping differs from the store standard or for a store that doesn't publish a store-wide policy. Hard-coded US-only with $0 shipping and 0–1 day handling + 2–5 day transit. Adjust per the merchant's actual Shopify shipping zone configuration. Store-wide shipping uses a ShippingService under Organization instead; the Shopify schema generator's policies output shows that shape.
Mapping Shopify shipping zones to OfferShippingDetails
Shopify exposes shipping configuration at Settings > Shipping and delivery > Shipping (Shipping zones, with countries per zone and rates per zone). For accurate schema, each zone should map to one OfferShippingDetails sub-object — one for US, one for Canada, one for International. The shippingRate per OfferShippingDetails comes from the cheapest standard rate per zone (the rate most relevant for the structured data). Flat-rate stores can hard-code one object; multi-zone stores hard-code one object per zone from the values in Settings > Shipping and delivery, and update the markup whenever a rate changes. For many zones, the Organization-level ShippingService is easier to maintain, because it's written once rather than on every product.
Validation
Rich Results Test against a PDP with shippingDetails should report Product detected under Merchant listings, the Offer and its OfferShippingDetails parsed, zero errors. If deliveryTime, shippingDestination or shippingRate is missing, the shipping details enhancement can't use the object. An Organization-level ShippingService is tested separately: the Rich Results Test lists Shipping policies as a supported type. If you also set shipping in Merchant Center, those settings take precedence over the markup, so keep the two in agreement.
Shopify gotchas on shippingDetails
Four gotchas. First: hard-coding shippingRate value 0 on a store with paid shipping — the markup is structurally valid but misrepresents the actual cost to shoppers. Use the merchant's real rate. Second: emitting shippingDestination as a single country on a multi-country store, leaving other regions unrepresented. Third: omitting deliveryTime, which Google requires for the shipping details enhancement. Fourth: using fractions for handlingTime / transitTime (handlingTime minValue: 0.5). Schema.org accepts any number, but Google requires non-negative whole numbers of days.