Warm tip: This article is reproduced from serverfault.com, please click

Shopify Product Variants in Google Tag Manager Using Javascript

发布于 2020-11-29 08:38:26

I'm using the Google Tag Manager Data Layer to add Structured Data to a Shopify Store. I ran out of space adding all the products so I'm trying to consolidate my tags. I can get all the variables I need in the Data Layer, I just need to know how to iterate them for the Offers section in the Structured Data.

I really just need to know how to convert this to Javascript to use in Google Tag Manager:

"offers": [
    {%- for variant in product.variants -%}
      {
        "@type" : "Offer",
        {%- if variant.sku != blank -%}
          "sku": {{ variant.sku | json }},
        {%- endif -%}
        "availability" : "http://schema.org/{% if product.available %}InStock{% else %}OutOfStock{% endif %}",
        "priceValidUntil" : {{'now' | date: '%Y-%m-%d' | json }},
        "price" : {{ variant.price | divided_by: 100.00 | json }},
        "priceCurrency" : {{ cart.currency.iso_code | json }},
        "url" : {{ shop.url | append: variant.url | json }}
      }{% unless forloop.last %},{% endunless %}
    {%- endfor -%}
  ]

I'm trying to iterate through Offers of Structured Data that I'm adding via Google Tag Manager. This is what I have right now:

<script>
(function()
{
var data = {
  "@context": "http://schema.org/",
  "@type": "Product",
  "@id": "{{TitanProductURL}}",
  "name": "{{TitanProductTitle}}",
  "url": "{{TitanProductURL}}",
  "image": [ "{{TitanProductImage}}"
    ],
  "description": "{{TitanProductDescription}}",
  "sku": "{{TitanSKU}}",
  "gtin12": "{{TitanBarcode}}",
  "brand": {
    "@type": "Thing",
    "name": "Titan Casket"
  },
  "offers": [],
"aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "{{TitanReviewRating}}",
    "bestRating": "5 star",
    "worstRating": "1 star",
    "ratingCount": "{{TitanReviewCount}}"
  }
}

  var productVariants = [{{TitanProductVariants}}];
  var productPrice = [{{TitanProductPrice}}];
  var i;
  for (i = 0; i < productVariants.length; i++) {
    data.offers.push({
        "@type" : "Offer",
        "sku": "{{TitanSKU}}",
        "availability" : "http://schema.org/InStock",
        "priceValidUntil" : "{{TitanDate}}",
        "price" : productPrice[i],
        "priceCurrency" : "USD",
        "url" : productVariants[i]
    });
  }
  
  var script = document.createElement('script');
  script.type = "application/ld+json";
  script.innerHTML = JSON.stringify(data);
  document.getElementsByTagName('head')[0].appendChild(script);
  })(document);
</script>

The TitanProductVariants and TitanProductPrice are Array's of each and when I Publish this tag, it shows all of the Arrays in one element, so instead of iterating through all the Variants, it shows all of them in every "url".

enter image description here

Would love any help!

UPDATE

I almost have it, but I'm running into 2 problems. This is my new code:

<script>
(function()
{
var data = {
    "@context": "http://schema.org/",
    "@type": "Product",
    "@id": "{{TitanProductURL}}",
    "name": "{{TitanProductTitle}}",
    "url": "{{TitanProductURL}}",
    "image": [ "{{TitanProductImage}}"
      ],
    "description": "{{TitanProductDescription}}",
    "sku": "{{TitanSKU}}",
    "gtin12": "{{TitanBarcode}}",
    "brand": {
      "@type": "Thing",
      "name": "Titan Casket"
    },
    "offers": [],
  "aggregateRating": {
      "@type": "AggregateRating",
      "ratingValue": "{{TitanReviewRating}}",
      "bestRating": "5 star",
      "worstRating": "1 star",
      "ratingCount": "{{TitanReviewCount}}"
    }
  }

  var variants = [{{TitanProductVariants}}];
  var prices = [{{TitanProductPrice}}];
  var len = variants.length;
  var text = "";
  for (i = 0; i < len; i++)
  {
  data.offers.push({
      "@type" : "Offer",
      "availability" : "http://schema.org/InStock",
      "priceValidUntil" : "{{TitanDate}}",
      "price" : text += prices[i]
      "priceCurrency" : "USD",
      "url" : text += variants[i]
    });
  }

  var script = document.createElement('script');
  script.type = "application/ld+json";
  script.innerHTML = JSON.stringify(data);
  document.getElementsByTagName('head')[0].appendChild(script);
  })(document);
</script>

The 2 problems are:

  1. Problem 1: The DataLayer Variables are pulling in Double Quotes around the entire array from Shopify so it thinks all the Variant URLs and All the Prices are 1 item. I can't figure out how to remove the Double Quotes.
  2. Problem 2: I manually added the Product Variant URLs to see if it would work. It does... sort of. On the first iteration, it adds the first URL. But on the second, it adds the first URL and the second URL and it keeps adding the next URL in line on each corresponding iteration. I just need it to add 1 URL per iteration.

UPDATE 2

The Google Tag Manager Variables {{TitanProductVariants}} and {{TitanProductPrice}} pull in data from the Data Layer in an Array. So, {{TitanProductVariants}} pulls in a list of URLs with an appended Variant ID (e.g. https://titancasket.com/products/titan-atlas-xl-silver-metal-oversize-casket?variant=35312157720744) and {{TitanProductPrice}} pulls in each price for each Variant.

I need to loop through each of these so that if there are 10 Variants, it'll have 10 "Offer" elements in Schema, each with the Variant URL and corresponding price. The output would look like this:

{
      "@type" : "Offer",
      "availability" : "http://schema.org/InStock",
      "priceValidUntil" : "2020-12-1",
      "price" : "1399.0",
      "priceCurrency" : "USD",
      "url" : "https://titancasket.com/products/titan-atlas-xl-silver-metal-oversize-casket?variant=35312157720744"
    },
{
      "@type" : "Offer",
      "availability" : "http://schema.org/InStock",
      "priceValidUntil" : "2020-12-1",
      "price" : "1499.0",
      "priceCurrency" : "USD",
      "url" : "https://titancasket.com/products/titan-atlas-xl-silver-metal-oversize-casket?variant=35312157720744"
    }

... and so on for each Variant URL.

Update 3

Here's how I'm pulling in data to Google Tag Manager:

<script>
   window.dataLayer = window.dataLayer || [];
   window.dataLayer.push({
      'gtm_product_url': {{ shop.url | append: product.url | json }},
      'gtm_product_title' : {{ product.title | json }},
      'gtm_product_image' : {{ product.featured_media | img_url: media_size | prepend: "https:" | json }},
      'gtm_product_description' : "{{ product.description | strip_html | strip_newlines | replace: '"', '' }}",
      'gtm_date' : "{{'now' | date: '%Y-%m-%d' }}",
      'gtm_sku' : "{{ current_variant.sku }}",
        'gtm_barcode' : "{{ current_variant.barcode }}",
      'gtm_review_rating': "{{ shop.metafields.judgeme.shop_reviews_rating }}",
      'gtm_review_count': "{{ shop.metafields.judgeme.shop_reviews_count }}",
      'gtm_product_price': "{%- for variant in product.variants -%}{{ variant.price | divided_by: 100.00}}{% unless forloop.last %},{% endunless %}{%- endfor -%}",
      'gtm_product_variants': "{%- for variant in product.variants -%}{{ shop.url | append: variant.url }}{% unless forloop.last %},{% endunless %}{%- endfor -%}"
   });

  </script>
Questioner
Kenny King
Viewed
0
HymnZzy 2020-12-02 12:58:16

Loop the variants directly from liquid.

{% for variant in product.variants %}
data.offers.push({
    "@type" : "Offer",
    "sku": "{{variant.sku}}",
    "availability" : "http://schema.org/InStock",
    "priceValidUntil" : "{{ 'now' | date: '%Y-%m-%d' }}",
    "price" : {{ variant.price }},
    "priceCurrency" : "USD",
    "url" : {{ shop.url | append: variant.url }}
})
{% endfor %}

If you are keen on using the javascript loop, try this.

var variants = {{ product.variants | json }};
for (let variants of variants){
  data.offers.push({
    "@type" : "Offer",
    "sku": variant.sku,
    "availability" : "http://schema.org/InStock",
    "priceValidUntil" : "{{ 'now' | date: '%Y-%m-%d' }}",
    "price" : variant.price,
    "priceCurrency" : "USD",
    "url" : "{{ shop.url }}"+variant.url
})

Update #2: Based on new information

var productVariants = {{TitanProductVariants}}.split(',');
var productPrice = {{TitanProductPrice}}.split(',');
var i;
for (i = 0; i < productVariants.length; i++) {
  data.offers.push({
      "@type" : "Offer",
      "sku": "{{TitanSKU}}",
      "availability" : "http://schema.org/InStock",
      "priceValidUntil" : "{{TitanDate}}",
      "price" : productPrice[i],
      "priceCurrency" : "USD",
      "url" : productVariants[i]
  });
}