npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

shopify-gtm-instrumentor

v1.6.0

Published

Helpers for sending standardized dataLayer events from a Shopify site

Downloads

373

Readme

shopify-gtm-instrumentor

This package contains helper methods for sending standardized dataLayer events from Shopify to GTM. The API is modeled after the Enhanced Ecommerce Data Types and Actions.

It expects that you'll be using Shopify's own Enhanced Ecommerce support wherever possible (like for Checkout events or the initial Product Detail impression on Shopify hosted product pages).

This package is designed to supplement that integration for other uses cases like:

  • Firing client side Product Detail Impressions when interacting with a variant selector
  • Firing Add / Remove from Cart events from headless ecommerce implementations
  • Making it easy to create Enhanced Ecommerce dataLayer objects for supported actions.

Methods:

Setup

  1. Install the package
yarn add shopify-gtm-instrumentor
  1. Enable Shopify's Enhanced Ecommerce support

  2. Enable "Enable Enhanced Ecommerce Features" in GTM for your Google Analytics Settings.

  1. Include the checkout-snippet.liquid in your checkout.liquid.

Optional

Optional (GA4)

  • Set the disableEcommerceProperty option to true.
  • Import the ga4.json file into your GTM container to create tags for firing GA4 ecommerce events.
  • Per this article set myshopify.com as an "Unwanted Referral" in your data stream.

Usage

Instantiate this package like:

const gtmEcomm = new ShopifyGtmInstrumentor({
  currencyCode: 'EUR'
})

The constructor takes these options:

  • debug - If true, emits console.debug lines with the pushed events.
  • storeUrl - Your 'https://mystore.myshopify.com' style Shopify URL. Defaults to process.env.SHOPIFY_URL.
  • storefrontToken - A Storefront API token with permission to read products. Defaults to process.env.SHOPIFY_STOREFONT_TOKEN.
  • currencyCode - Defaults to USD.
  • disableEcommerceProperty - If true, removes the ecommerce property from the object which is used by UA Enhanced Commerce. You would enable this if you were using GA4 and want to use explicit tags, like those in ga4-tags.json
  • enableCheckoutEcommerceProperty - If true, adds ecommerce properties to Checkout and Purchase events. This is diabled by default because it's expected that you'd use Shopify's Google Analytics integration for this. However, if you are only using GA4 you may want to use this to support 3rd party GTM Tags that are expecting this property to exist.

Implemented methods described below:

Product Impressions

Used any time a product is displayed, like a product card.

gtmEcomm.productImpression(variantPayload, {
  el: null, // DOM Element
  list: null, // String
  position: null, // String
})
  • variantPayload - Either:

    • A Shopify numeric id, in which case the full variant is looked up via the Storefront API
    • A Shopify gid://shopify/ProductVariant/### style id, which will also be looked up via Storefront API
    • A Shopify ProductVariant object with product property. Not recommended since it requires particular fields to be present.
  • options - Supports the following keys

    • el - Optional DOM Element. If supplied, an IntersectionObserver will be attached to the element that triggers the event only once (and only once) the element has entered the viewport.
    • list - Optional name of the list or collection to which the product belongs.
    • position - Optional position in a list or collection. If el is provided and position is undefined, defaults to the index of the element relative to it's parent. 1-based.

Pushes an object to the dataLayer that looks like:

{
  event: 'Product Impression',
  firstOccurance: true,
  sku: 'sku-abc',
  variantId: '123',
  variantTitle: 'Black',
  variantImage: 'https://cdn.shopify.com/s/files/...',
  variantUrl: 'https://www.shop.com/product/great-t-shirt?variant=123',
  price: 18.99,
  compareAtPrice: 20.99,
  productId: '456',
  productTitle: 'Great T-Shirt',
  productVariantTitle: 'Great T-Shirt - Black',
  productType: 'Shirts',
  productVendor: 'Bukwild',
  productUrl: 'https://www.shop.com/product/great-t-shirt',
  ecommerce: {
    impressions: [
      {
        id: 'sku-abc',
        name: 'Great T-Shirt - Black',
        brand: 'Bukwild',
        category: 'Shirts',
        variant: 'Black',
        price: 18.99,
        list: 'Shirts Collection',
        position: 3
      }
    ]
  }
}

Product Clicks

gtmEcomm.productClick(variantPayload, options)

Used when a user clicks on a product, like to go to it's detail view.

  • variantPayload - Described above

  • options - Supports the following keys:

    • el - Optional DOM Element. If supplied, will be used to calulate the position by comparing the element's index relative it's parent.
    • list - Optional name of the list or collection to which the product belongs.
    • position - Optional position in a list or collection, 1-based.
    • clickEvent - Optionally pass the click event object here to wait to change page until the event has been pushed.

Pushes an object to the dataLayer that looks like:

{
  event: 'Product Click',
  firstOccurance: true,
  sku: 'sku-abc',
  variantId: '123',
  variantTitle: 'Black',
  variantImage: 'https://cdn.shopify.com/s/files/...',
  variantUrl: 'https://www.shop.com/product/great-t-shirt?variant=123',
  price: 18.99,
  compareAtPrice: 20.99,
  productId: '456',
  productTitle: 'Great T-Shirt',
  productVariantTitle: 'Great T-Shirt - Black',
  productType: 'Shirts',
  productVendor: 'Bukwild',
  productUrl: 'https://www.shop.com/product/great-t-shirt',
  ecommerce: {
    click: {
      actionField: { list: 'Shirts Collection'},
      products: [
        {
          id: 'sku-abc',
          name: 'Great T-Shirt - Black',
          brand: 'Bukwild',
          category: 'Shirts',
          variant: 'Black',
          price: 18.99,
          position: 3
        }
      ]
    }
  }
}

Product Detail Impressions

Used on product detail pages whenever the variant changes.

gtmEcomm.viewProductDetails(variantPayload)
  • variantPayload - See above

Pushes an object to the dataLayer that looks like:

{
  event: 'View Product Details',
  firstOccurance: true,
  sku: 'sku-abc',
  variantId: '123',
  variantTitle: 'Black',
  variantImage: 'https://cdn.shopify.com/s/files/...',
  variantUrl: 'https://www.shop.com/product/great-t-shirt?variant=123',
  price: 18.99,
  compareAtPrice: 20.99,
  productId: '456',
  productTitle: 'Great T-Shirt',
  productVariantTitle: 'Great T-Shirt - Black',
  productType: 'Shirts',
  productVendor: 'Bukwild',
  productUrl: 'https://www.shop.com/product/great-t-shirt',
  ecommerce: {
    detail: {
      products: [
        {
          id: 'sku-abc',
          name: 'Great T-Shirt - Black',
          brand: 'Bukwild',
          category: 'Shirts',
          variant: 'Black',
          price: 18.99
        }
      ]
    }
  }
}

The firstOccurance property will be true the first time this method is called in a given request and false for the remainder. You would use this when a product detail page is served by Shopify and the Shopify Enhanced Ecommerce integration will be firing the inital event but you will be firing additional events as a user interacts with a variant selector. For example:

Add / Remove from Cart

Used when products are added or removed from the cart.

gtmEcomm.addToCart(variantPayload, quantity)
gtmEcomm.removeFromCart(variantPayload, quantity)
  • variantPayload - See above
  • quantity - The quantity changed. So, if updating the quanity from 2 to 5, the value should be 3. If deleting a line item with a quantity of 2, you would use removeProductFromCart with a quantity of 2.

Pushes an object to the dataLayer that looks like:

{
  event: 'Add to Cart',
  firstOccurance: true,
  quantity: 1,
  sku: 'sku-abc',
  variantId: '123',
  variantTitle: 'Black',
  variantImage: 'https://cdn.shopify.com/s/files/...',
  variantUrl: 'https://www.shop.com/product/great-t-shirt?variant=123',
  price: 18.99,
  compareAtPrice: 20.99,
  productId: '456',
  productTitle: 'Great T-Shirt',
  productVariantTitle: 'Great T-Shirt - Black',
  productType: 'Shirts',
  productVendor: 'Bukwild',
  productUrl: 'https://www.shop.com/product/great-t-shirt',
  ecommerce: {
    add: {
      currencyCode: 'USD',
      products: [
        {
          id: 'sku-abc',
          name: 'Great T-Shirt - Black',
          brand: 'Bukwild',
          category: 'Shirts',
          variant: 'Black',
          price: 18.99,
          quantity: 1
        }
      ]
    }
  }
}

or like this

{
  event: 'Remove from Cart',
  firstOccurance: true,
  quantity: 1,
  sku: 'sku-abc',
  variantId: '123',
  variantTitle: 'Black',
  variantImage: 'https://cdn.shopify.com/s/files/...',
  variantUrl: 'https://www.shop.com/product/great-t-shirt?variant=123',
  price: 18.99,
  compareAtPrice: 20.99,
  productId: '456',
  productTitle: 'Great T-Shirt',
  productVariantTitle: 'Great T-Shirt - Black',
  productType: 'Shirts',
  productVendor: 'Bukwild',
  productUrl: 'https://www.shop.com/product/great-t-shirt',
  ecommerce: {
    remove: {
      currencyCode: 'USD',
      products: [
        {
          id: 'sku-abc',
          name: 'Great T-Shirt - Black',
          brand: 'Bukwild',
          category: 'Shirts',
          variant: 'Black',
          price: 18.99,
          quantity: 1
        }
      ]
    }
  }
}

See above for info on firstOccurance.

Cart Updated

Used to send the current checkout / cart state to GTM. This is not an explicit Enhanced Ecommerce event but many GTM want this data.

gtmEcomm.cartUpdated(checkoutOrCartPayload)
  • checkoutOrCartPayload - Either a Cart or Checkout ID that can be resolved by the Storefront API (recommended) or an object that is formed to look like one (like the window.CHECKOUT_LINE_ITEMS object, described below).

Pushes an object to the dataLayer that looks like:

{
  event: 'Cart Updated',
  firstOccurance: true,
  checkoutId: '789',
  checkoutUrl: 'https://www.shop.com/.../checkouts/...',
  subtotalPrice: 18.99,
  totalPrice: 18.99,
  lineItems: [
    {
      lineItemId: '456',
      quantity: 1,
      sku: 'sku-abc',
      variantId: '123',
      variantTitle: 'Black',
      variantImage: 'https://cdn.shopify.com/s/files/...',
      variantUrl: 'https://www.shop.com/product/great-t-shirt?variant=123',
      price: 18.99,
      compareAtPrice: 20.99,
      productId: '456',
      productTitle: 'Great T-Shirt',
      productVariantTitle: 'Great T-Shirt - Black',
      productType: 'Shirts',
      productVendor: 'Bukwild',
      productUrl: 'https://www.shop.com/product/great-t-shirt',
    }
  ]
}

Checkout

This would be triggered by each step of the checkout, like:

if (window.Shopify && window.Shopify.Checkout) {
  gtmEcomm.checkout(window.CHECKOUT_FOR_GTM_INSTRUMENTOR,
    window.Shopify.Checkout.step)
}

Currently, window.Shopify.Checkout.step resolves to:

  1. "contact_information"
  2. "shipping_method"
  3. "payment_method"
  4. "processing"
  5. "thank_you"
  6. undefined (becomes undefined on reload / order page)

The CHECKOUT_FOR_GTM_INSTRUMENTOR array is created by checkout-snippet.liquid. We can't use the Storefront API for this because Shopify destroys the cart object on checkout so we can't use the cart data for purchase events.

This isn't designed to trigger the Enhanced Ecommerce purchase action; we're expecting Shopify's Enhanced Ecommerce integration to fire this. Instead, this event is designed to be useful for firing other conversion type tags from GTM.

{
  event: 'Checkout',
  firstOccurance: true,
  checkoutStep: `contact_information`
  checkoutId: '789',
  checkoutUrl: 'https://www.shop.com/.../checkouts/...',
  subtotalPrice: 18.99,
  totalPrice: 18.99,
  lineItems: [
    {
      lineItemId: '456',
      quantity: 1,
      sku: 'sku-abc',
      variantId: '123',
      variantTitle: 'Black',
      variantImage: 'https://cdn.shopify.com/s/files/...',
      variantUrl: 'https://www.shop.com/product/great-t-shirt?variant=123',
      price: 18.99,
      compareAtPrice: 20.99,
      productId: '456',
      productTitle: 'Great T-Shirt',
      productVariantTitle: 'Great T-Shirt - Black',
      productType: 'Shirts',
      productVendor: 'Bukwild',
      productUrl: 'https://www.shop.com/product/great-t-shirt',
    }
  ]
}

If enableCheckoutEcommerceProperty was set to true, the dataLayer will also include:

{
  ecommerce: {
    checkout: {
      actionField: {
        step: 'contact_information'
      },
      products: [
        {
          id: 'sku-abc',
          name: 'Great T-Shirt - Black',
          brand: 'Bukwild',
          category: 'Shirts',
          variant: 'Black',
          price: 18.99,
          quantity: 1
        }
      ]
    }
  }
}

Purchases

Should be triggered on the thank you page after checkout.

if (window.Shopify &&
  window.Shopify.Checkout &&
  window.Shopify.Checkout.step == 'thank_you') {
  gtmEcomm.purchase(window.CHECKOUT_FOR_GTM_INSTRUMENTOR)
}

Like Checkout, this isn't intended to replace Shopify's Enhannced Ecommerce support. It creates a payload like:

{
  event: 'Purchase',
  firstOccurance: true,
  checkoutId: '789',
  checkoutUrl: 'https://www.shop.com/.../checkouts/...',
  subtotalPrice: 18.99,
  totalPrice: 18.99,
  lineItems: [
    {
      lineItemId: '456',
      quantity: 1,
      sku: 'sku-abc',
      variantId: '123',
      variantTitle: 'Black',
      variantImage: 'https://cdn.shopify.com/s/files/...',
      variantUrl: 'https://www.shop.com/product/great-t-shirt?variant=123',
      price: 18.99,
      compareAtPrice: 20.99,
      productId: '456',
      productTitle: 'Great T-Shirt',
      productVariantTitle: 'Great T-Shirt - Black',
      productType: 'Shirts',
      productVendor: 'Bukwild',
      productUrl: 'https://www.shop.com/product/great-t-shirt',
    }
  ]
}

If enableCheckoutEcommerceProperty was set to true, the dataLayer will also include:

{
  ecommerce: {
    purchase: {
      actionField: {
        id: ''
        revenue: 18.99,
        tax: 0.00,
        shipping: 0.00,
        coupon: 'one,two'
      },
      products: [
        {
          id: 'sku-abc',
          name: 'Great T-Shirt - Black',
          brand: 'Bukwild',
          category: 'Shirts',
          variant: 'Black',
          price: 18.99,
          quantity: 1
        }
      ]
    }
  }
}

Customer Info

Used to send the customer info to GTM. This is not an explicit Enhanced Ecommerce event but many GTM tags want this data.

gtmEcomm.identifyCustomer(customer)
  • customer - An object that contains customer email and id, like:
{
  id: '1234'
  zip: '90210',
  email: '[email protected]',

}

Pushes an object to the dataLayer that looks like:

{
  event: 'Identify Customer',
  customerId: '1234'
  customerZip: '90210',
  customerEmail: '[email protected]',
}