Liquid/Schema Help: Mapping Custom Shipping/Return Metafields to Google's Structured Data

I am trying to get my custom Shipping and Return Metafields to be recognized by Google for Rich Results/Google Shopping, but the structured data is failing the validation test.

I need the correct Liquid snippet to successfully map my metafields to the necessary Google Schema properties.

Details of the Issue

Goal: Add Shipping Details and Return Policy to my product’s JSON-LD Schema, and functions for all my product.

Code Location: I understand the code needs to be placed in the right block, but need to know if it should be put in main-product.liquid file? And the exact position is?

Failure: When I try to add the code myself, it fails Google’s Rich Results Test instantly, confirming the structure is incorrect.

Request for Code Could an experienced developer please provide the correct Liquid code snippet required to map the metafields to the JSON-LD?

Thank you in advance!

2 Likes

Hey pal @Steve2025 !

Google doesn’t read metafields directly, it only reads the final JSON-LD. So you need to inject your metafields inside the existing Product schema, not in a separate script.

Where to put it:

  • Go to Online Store → Themes → … → Edit code
  • Search for: type="application/ld+json" and "@type": "Product"
  • In most themes this is in a snippet (e.g. snippets/product-schema.liquid) or at the bottom of main-product.liquid.
  • You want to edit that existing Product JSON-LD block and add shipping/returns inside the "offers" object.

Key points:

  • Replace custom.shipping_details / custom.return_policy_url with your actual metafield namespace + key.
  • Keep everything dynamic wrapped in | json to avoid invalid JSON.
  • Don’t create a separate partial schema with only shippingDetails, keep it inside the main Product schema.

After saving, run the page through Google’s Rich Results Test again; if it still fails, it’s almost always a missing/extra comma or a wrong metafield handle.

Hope this helps!

Previously, themes included liquid code for structured metadata:

Starting with Dawn version 15 the themes are switching towards use of the built-in filter:

If you need to add more info, you can either switch back to the older code, or extend the new one.

Luckily, built-in filter uses IDs so you can reference them.

Here is an example of code output by the built-in filter:

[
  {
    "@context": "http:\/\/schema.org\/",
    "@id": "\/products\/absolut-vodka-700ml#product",
    "@type": "ProductGroup",
    "brand": {
      "@type": "Brand",
      "name": "SPIRITISM"
    },
    "description": "The Absolut Recycled",
    "hasVariant": [
      {
        "@id": "\/products\/absolut-vodka-700ml?variant=31297174437942#variant",
        "@type": "Product",
        "image": "https:\/\/bbkmarket.myshopify.com\/cdn\/shop\/products\/27720-2.png?v=1747407357\u0026width=1920",
        "name": "Absolut Vodka 700mL - Original",
        "offers": {
          "@id": "\/products\/absolut-vodka-700ml?variant=31297174437942#offer",
          "@type": "Offer",
          "availability": "http:\/\/schema.org\/InStock",
          "price": "29.93",
          "priceCurrency": "AUD",
          "url": "https:\/\/bbkmarket.myshopify.com\/products\/absolut-vodka-700ml?variant=31297174437942"
        },
        "sku": "Original SKU"
      }
    ],
    "name": "Absolut Vodka 700mL",
    "productGroupID": "4360466268214",
    "url": "https:\/\/bbkmarket.myshopify.com\/products\/absolut-vodka-700ml"
  },
  {
    "@context": "http:\/\/schema.org\/",
    "@id": "\/products\/absolut-vodka-700ml?variant=31297174437942#offer",
    "@type": "Offer",
    "shippingDetails": {
      "@id": "#shipping_policy"
    }
  },
  {
    "@context": "https://schema.org/",
    "@type": "OfferShippingDetails",
    "@id": "#shipping_policy",
    "shippingRate": {
      "@type": "MonetaryAmount",
      "value": 2.99,
      "currency": "USD"
    },
    "shippingDestination": {
      "@type": "DefinedRegion",
      "addressCountry": "US"
    },
    "deliveryTime": {
      "@type": "ShippingDeliveryTime",
      "handlingTime": {
        "@type": "QuantitativeValue",
        "minValue": 0,
        "maxValue": 1,
        "unitCode": "DAY"
      },
      "transitTime": {
        "@type": "QuantitativeValue",
        "minValue": 1,
        "maxValue": 5,
        "unitCode": "DAY"
      }
    }
  }
]

So you should be able to add your info like below.
Of course, the actual code for OfferShippingDetails you need to construct yourself.
Here it is referenced, but you can obviously inline it too.

Also, you can use “Custom liquid” section added to the product template, no need to edit theme code for this.

<!-- extend built-in product structured data with shipping info -->
<script type="application/ld+json">
[
 {% for v in product.variants %}
  {
    "@context": "http:\/\/schema.org\/",
    "@id": {{ v.url | append: '#offer' | json }},
    "@type": "Offer",
    "shippingDetails": {
      "@id": "#shipping_policy"
    }
  } {% unless forloop.last %},{% endunless %}
 {% endfor %}
]
</script>
<!-- since shipping is the same, can reference single object -->
<script type="application/ld+json">
  {
    "@context": "https://schema.org/",
    "@type": "OfferShippingDetails",
    "@id": "#shipping_policy",
    "shippingRate": {
      "@type": "MonetaryAmount",
      "value": 2.99,
      "currency": "USD"
    },
    "shippingDestination": {
      "@type": "DefinedRegion",
      "addressCountry": "US"
    },
    "deliveryTime": {
      "@type": "ShippingDeliveryTime",
      "handlingTime": {
        "@type": "QuantitativeValue",
        "minValue": 0,
        "maxValue": 1,
        "unitCode": "DAY"
      },
      "transitTime": {
        "@type": "QuantitativeValue",
        "minValue": 1,
        "maxValue": 5,
        "unitCode": "DAY"
      }
    }
  }
</script>

Resulting code validates properly:

Contact me if you need help implementing it in your store.


if my post is helpful, please like it ♡ and mark as a solution -- this will help others find it