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:
productImpression
productClick
viewProductDetails
addToCart
removeFromCart
cartUpdated
checkout
purchase
identifyCustomer
- Install the package
yarn add shopify-gtm-instrumentor
-
Enable "Enable Enhanced Ecommerce Features" in GTM for your Google Analytics Settings.
- Include the checkout-snippet.liquid in your checkout.liquid.
- Import the variables-and-triggers.json file into your GTM container to easily create all GTM DataLayer variables.
- 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.
Instantiate this package like:
const gtmEcomm = new ShopifyGtmInstrumentor({
currencyCode: 'EUR'
})
The constructor takes these options:
debug
- Iftrue
, emitsconsole.debug
lines with the pushed events.storeUrl
- Your 'https://mystore.myshopify.com' style Shopify URL. Defaults toprocess.env.SHOPIFY_URL
.storefrontToken
- A Storefront API token with permission to read products. Defaults toprocess.env.SHOPIFY_STOREFONT_TOKEN
.currencyCode
- Defaults toUSD
.disableEcommerceProperty
- Iftrue
, removes theecommerce
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.jsonenableCheckoutEcommerceProperty
- Iftrue
, addsecommerce
properties toCheckout
andPurchase
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:
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 keysel
- 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. Ifel
is provided andposition
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
}
]
}
}
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 theposition
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
}
]
}
}
}
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:
Used when products are added or removed from the cart.
gtmEcomm.addToCart(variantPayload, quantity)
gtmEcomm.removeFromCart(variantPayload, quantity)
variantPayload
- See abovequantity
- The quantity changed. So, if updating the quanity from 2 to 5, the value should be3
. If deleting a line item with a quantity of 2, you would useremoveProductFromCart
with a quantity of2
.
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
.
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 thewindow.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',
}
]
}
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:
"contact_information"
"shipping_method"
"payment_method"
"processing"
"thank_you"
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
}
]
}
}
}
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
}
]
}
}
}
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]',
}