Adding Structured Data to Shopify for Google Merchant & Facebook (JSON-LD)

Adding Structured Data to Shopify for Google Merchant (JSON-LD)

If you have received errors or warnings regarding missing or invalid data for prices, condition, availability, etc… Then the code below will solve this issue. Simply copy the code and paste it inside your product.liquid file using the latest JSON-LD technology. Also supports variants, while keeping the first selected product as the first iteration. Meaning if you have multiple variants such as colors, and if the second color is preselected based on the URL, then the second variant will be first listed in the structured data, followed by the other variants. This is done to follow the Google Merchant Center guidelines and while keeping SEO integrity.

This tutorial no longer supports the old Microdata technology as JSON-LD is a lot faster to read for Google Bots.

This code now also supports id’s for Facebook, so you can import product data using structured data.


Important :
It is required you remove all your old structured data coding, to avoid conflicts. If you do not know how to do this, you can ask for my help using the contact form below
<!-- Copyright FeedArmy 2019 Version 2.31 -->
{% assign fa_current_variant = product.selected_or_first_available_variant %}
{% assign fa_variant_count = product.variants | size %}
{% assign fa_count = 0 %}
<script type="application/ld+json" data-creator_name="FeedArmy">
{
  "@context": "http://schema.org/",
  "@type": "Product",
  "name": "{{ product.title | strip_html | escape }}",
  "url": "{{ shop.url }}{{ product.url }}",
  {% if product.variants.first.sku != blank %}
    "sku": "{{ product.variants.first.sku }}",
  {% else %}
    "sku": "{{ product.variants.first.id }}",
  {% endif %}
  {% if product.variants.first.barcode.size == 12 %}
    "gtin12": {{ product.variants.first.barcode }},
  {% endif %}
  {% if product.variants.first.barcode.size == 13 %}
    "gtin13": {{ product.variants.first.barcode }},
  {% endif %}
  {% if product.variants.first.barcode.size == 14 %}
    "gtin14": {{ product.variants.first.barcode }},
  {% endif %}
    "productID": "{{ product.id }}",
  "brand": {
    "@type": "Thing",
    "name": "{{ product.vendor | escape }}"
  },
  "description": "{{ product.description | strip_html | escape | strip_newlines }}",
  "image": "https:{{ product.featured_image.src | img_url: 'grande' }}",
  {% if product.variants %}
  {% assign fa_count = fa_count | plus: 1 %}
    "offers": {% if product.variants.size > 1 %}[{% endif %}
      {
        "@type" : "Offer",
        "priceCurrency": "{{ shop.currency }}",
        "price": "{{ fa_current_variant.price | money_without_currency  | strip_html | remove: ',' }}",
        "itemCondition" : "http://schema.org/NewCondition",
        "availability" : "http://schema.org/{% if product.available %}InStock{% else %}OutOfStock{% endif %}",
        "url" : "{{ shop.url }}{{ fa_current_variant.url }}",


            {% if fa_current_variant.image %}
              {% assign variant_image_size = fa_current_variant.image.width | append: 'x' %}
              "image": "https:{{ fa_current_variant.image.src | img_url: variant_image_size }}",
            {% else %}
              "image": "https:{{ product.featured_image.src | img_url: 'grande' }}",
            {% endif %}
            {% if fa_current_variant.title != 'Default Title' %}
              "name" : "{{ product.title | strip_html | escape }} - {{ fa_current_variant.title | escape }}",
            {% else %}
              "name" : "{{ product.title | strip_html | escape }}",
            {% endif %}
            {% if fa_current_variant.barcode.size == 12 %}
              "gtin12": {{ fa_current_variant.barcode }},
            {% endif %}
            {% if fa_current_variant.barcode.size == 13 %}
              "gtin13": {{ fa_current_variant.barcode }},
            {% endif %}
            {% if fa_current_variant.barcode.size == 14 %}
              "gtin14": {{ fa_current_variant.barcode }},
            {% endif %}
            {% if fa_current_variant.sku != blank %}
              "sku": "{{ fa_current_variant.sku }}",
            {% else %}
              "sku": "{{ fa_current_variant.id }}",
            {% endif %}
            {% if product.description != blank %}
            "description" : "{{ product.description | strip_html | escape | strip_newlines }}",
            {% endif %}
          "priceValidUntil": "{{ 'now' | date: '%s' | plus: 31536000 | date: '%Y-%m-%d' | uri_encode | replace:'+','%20' }}"

      }{% if product.variants.size != 1 %},{% endif %}

      {% for variant in product.variants %}
      {% assign fa_count = fa_count | plus: 1 %}
      {% if variant != product.selected_or_first_available_variant %}
        {
          "@type" : "Offer",
          "priceCurrency": "{{ shop.currency }}",
          "price": "{{ variant.price | money_without_currency  | strip_html | remove: ',' }}",
          "itemCondition" : "http://schema.org/NewCondition",
          "availability" : "http://schema.org/{% if variant.available %}InStock{% else %}OutOfStock{% endif %}",
          "url" : "{{ shop.url }}{{ variant.url }}",


              {% if variant.image %}
                {% assign variant_image_size = variant.image.width | append: 'x' %}
                "image": "http:{{ variant.image.src | img_url: variant_image_size }}",
              {% else %}
                "image": "https:{{ product.featured_image.src | img_url: 'grande' }}",
              {% endif %}
              {% if variant.title != 'Default Title' %}
                "name" : "{{ product.title | strip_html | escape }} - {{ variant.title | escape }}",
              {% else %}
                "name" : "{{ product.title | strip_html | escape }}",
              {% endif %}
              {% if variant.barcode.size == 12 %}
                "gtin12": {{ variant.barcode }},
              {% endif %}
              {% if variant.barcode.size == 13 %}
                "gtin13": {{ variant.barcode }},
              {% endif %}
              {% if variant.barcode.size == 14 %}
                "gtin14": {{ variant.barcode }},
              {% endif %}
              {% if variant.sku != blank %}
                "sku": "{{ variant.sku }}",
              {% else %}
                "sku": "{{ variant.id }}",
              {% endif %}
              {% if product.description != blank %}
              "description" : "{{ product.description | strip_html | escape | strip_newlines }}",
              {% endif %}
              "priceValidUntil": "{{ 'now' | date: '%s' | plus: 31536000 | date: '%Y-%m-%d' | uri_encode | replace:'+','%20' }}"
          }

          {% if fa_count <= fa_variant_count %}
         	{% unless forloop.last %},{% endunless %}
          {% endif %}

          {% endif %}





      {% endfor %}
    {% if product.variants.size > 1 %}]{% endif %}

    {% if product.metafields.spr.reviews %}
    ,"aggregateRating": {
     "@type": "AggregateRating",
     "ratingValue": {{ product.metafields.spr.reviews | split: 'ratingValue" content="' | last | split: '"' | first | plus: 0 }},
     "ratingCount": {{ product.metafields.spr.reviews | split: 'reviewCount" content="' | last | split: '"' | first | plus: 0 }}
    }
    {% endif %}
  {% endif %}
}
</script>
<!-- Copyright FeedArmy 2019 Version 2.31 -->

Once the new coding has been added, it will take Google Merchant Center several weeks to a month before the warnings inside your diagnostic panel disappear. The reason it takes so long is that Google does not check every page every day, but over a span of 30 days.

Here is a step by step guide on how to paste the code in your products.liquid file.

Step 1

Login to your Shopify Admin Panel

Shopify Login

Step 2

Open up the theme editor

shopify how to go to edit themes

Step 3

In the top right corner click on actions. A menu will appear and click on Edit Code

Edit Shopify Theme Code

Step 4

Click on Templates > product.liquid

Shopify Product Liquid File

Step 5

Depending on how your theme is built, the recommended place to paste the code us underneath the last include, this should be very near to the top. If you have any headers included, definitely after this line. Due to so many different themes, I can not explain exactly where to place it. However, it should be inserted within the first 10 lines of code. Check that you did not break anything by checking the preview results of your product landing page.

Step 6

Verify that you have done it correctly by checking the page with Google’s Structured Data Testing Tool

And also check Facebook’s data testing tool.

You will see 1 error

  • The review field is recommended. Please provide a value if available.
    • This can’t be added, and should be added by the review app you are using.

The aggregatedReviews in this script only extract data for the default Shopify Review system, if you have other review systems such as yotpo, then please contact me at the bottom of this article for a custom installation.
Google Structured Data Testing Result

Tip

If you want the ability to edit your titles for Google Shopping but do not want to change the website, why not use FeedArmy for publishing your products to Google Shopping. You can also export variants and use import rules or manually edit data!

Need Help?

Changelog Structured Data for Shopify

Fixed issue where out of stock products would create an extra leading comma if only 2 product variants exist
  • Added the parent title to the variant title
  • Fixed issue where if the first available product was out of stock, it no longer loaded partial data.
  • Restructured the offer container, to avoid Either 'offers', 'review' or 'aggregateRating' should be specified errors.
  • Added brand, description and pricevaliduntil to individual variants.
  • Added productID for Facebook catalog support
  • Added product id if the sku is not assigned in Shopify
  • Fixed variant availability