{"id":21525805,"url":"https://github.com/bkwld/shopify-gtm-instrumentor","last_synced_at":"2025-04-09T23:23:15.651Z","repository":{"id":50949498,"uuid":"357747790","full_name":"BKWLD/shopify-gtm-instrumentor","owner":"BKWLD","description":"Helpers for sending standardized dataLayer events from a Shopify site, inspired by GA Enhanced Ecommerce.","archived":false,"fork":false,"pushed_at":"2023-12-18T21:56:58.000Z","size":188,"stargazers_count":12,"open_issues_count":4,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-24T01:12:35.457Z","etag":null,"topics":["gtm","shopify"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BKWLD.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-04-14T02:22:40.000Z","updated_at":"2024-12-23T05:55:27.000Z","dependencies_parsed_at":"2023-10-11T20:47:15.581Z","dependency_job_id":null,"html_url":"https://github.com/BKWLD/shopify-gtm-instrumentor","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BKWLD%2Fshopify-gtm-instrumentor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BKWLD%2Fshopify-gtm-instrumentor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BKWLD%2Fshopify-gtm-instrumentor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BKWLD%2Fshopify-gtm-instrumentor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BKWLD","download_url":"https://codeload.github.com/BKWLD/shopify-gtm-instrumentor/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248126837,"owners_count":21052059,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gtm","shopify"],"created_at":"2024-11-24T01:38:31.255Z","updated_at":"2025-04-09T23:23:15.617Z","avatar_url":"https://github.com/BKWLD.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# shopify-gtm-instrumentor\n\nThis 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](https://developers.google.com/tag-manager/enhanced-ecommerce).\n\nIt expects that you'll be using [Shopify's own Enhanced Ecommerce support](https://help.shopify.com/en/manual/reports-and-analytics/google-analytics/google-analytics-setup#enhanced) wherever possible (like for Checkout events or the initial Product Detail impression on Shopify hosted product pages).\n\nThis package is designed to supplement that integration for other uses cases like:\n\n- Firing client side Product Detail Impressions when interacting with a variant selector\n- Firing Add / Remove from Cart events from headless ecommerce implementations\n- Making it easy to create Enhanced Ecommerce dataLayer objects for supported actions.\n\n*Methods*:\n\n- [`productImpression`](#product-impressions)\n- [`productClick`](#product-clicks)\n- [`viewProductDetails`](#product-detail-impressions)\n- [`addToCart`](#add--remove-from-cart)\n- [`removeFromCart`](#add--remove-from-cart)\n- [`cartUpdated`](#cart-updated)\n- [`checkout`](#checkout)\n- [`purchase`](#purchases)\n- [`identifyCustomer`](#customer-info)\n\n## Setup\n\n1. Install the package\n\n```\nyarn add shopify-gtm-instrumentor\n```\n\n2. Enable [Shopify's Enhanced Ecommerce support](https://help.shopify.com/en/manual/reports-and-analytics/google-analytics/google-analytics-setup#enhanced)\n\n3. Enable \"Enable Enhanced Ecommerce Features\" in GTM for your Google Analytics Settings.\n\n![](https://p-9WF55W9.t1.n0.cdn.getcloudapp.com/items/bLuAgLLl/2c0a0206-62f3-4c0c-a404-6df9698890ed.jpg?v=6adefdcd1403bc1101b8be17048238e4)\n\n4. Include the [checkout-snippet.liquid](./checkout-snippet.liquid) in your checkout.liquid.\n\n#### Optional\n\n- Import the [variables-and-triggers.json](./gtm-workspace-scaffold/variables-and-triggers.json) file into your GTM container to easily create all GTM DataLayer variables.\n\n![](https://p-9WF55W9.t1.n0.cdn.getcloudapp.com/items/DOuB6Wmq/ccf85884-1c74-4fa1-9a70-001cbbbb98dd.jpg?v=74e1d13c869f1c1c3c375486cb7d2960)\n\n#### Optional (GA4)\n\n- Set the `disableEcommerceProperty` option to true.\n- Import the [ga4.json](gtm-workspace-scaffold/ga4.json) file into your GTM container to create tags for firing GA4 ecommerce events.\n- Per [this article](https://www.lovesdata.com/blog/google-analytics-4-shopify) set `myshopify.com` as an \"Unwanted Referral\" in your data stream.\n\n## Usage\n\nInstantiate this package like:\n\n```js\nconst gtmEcomm = new ShopifyGtmInstrumentor({\n  currencyCode: 'EUR'\n})\n```\n\nThe constructor takes these options:\n\n- `debug` - If `true`, emits `console.debug` lines with the pushed events.\n- `storeUrl` - Your 'https://mystore.myshopify.com' style Shopify URL. Defaults to `process.env.SHOPIFY_URL`.\n- `storefrontToken` - A Storefront API token with permission to read products.  Defaults to `process.env.SHOPIFY_STOREFONT_TOKEN`.\n- `currencyCode` - Defaults to `USD`.\n- `disableEcommerceProperty` - If `true`, removes the `ecommerce` property from the object which is used by [UA Enhanced Commerce](https://developers.google.com/tag-manager/enhanced-ecommerce). You would enable this if you were using GA4 and want to use explicit tags, like those in [ga4-tags.json](./gtm-workspace-scaffold/ga4-tags.json)\n- `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.\n\nImplemented methods described below:\n\n#### [Product Impressions](https://developers.google.com/tag-manager/enhanced-ecommerce#product-impressions)\n\nUsed any time a product is displayed, like a product card.\n\n```js\ngtmEcomm.productImpression(variantPayload, {\n  el: null, // DOM Element\n  list: null, // String\n  position: null, // String\n})\n```\n\n- `variantPayload` - Either:\n  - A Shopify numeric id, in which case the full variant is looked up via the Storefront API\n  - A Shopify `gid://shopify/ProductVariant/###` style id, which will also be looked up via Storefront API\n  - A [Shopify ProductVariant object](https://shopify.dev/docs/storefront-api/reference/products/productvariant) with `product` property.  _Not recommended since it requires particular fields to be present._\n\n- `options` - Supports the following keys\n  - `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.\n  - `list` - Optional name of the list or collection to which the product belongs.\n  - `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.\n\nPushes an object to the dataLayer that looks like:\n\n```js\n{\n  event: 'Product Impression',\n  firstOccurance: true,\n  sku: 'sku-abc',\n  variantId: '123',\n  variantTitle: 'Black',\n  variantImage: 'https://cdn.shopify.com/s/files/...',\n  variantUrl: 'https://www.shop.com/product/great-t-shirt?variant=123',\n  price: 18.99,\n  compareAtPrice: 20.99,\n  productId: '456',\n  productTitle: 'Great T-Shirt',\n  productVariantTitle: 'Great T-Shirt - Black',\n  productType: 'Shirts',\n  productVendor: 'Bukwild',\n  productUrl: 'https://www.shop.com/product/great-t-shirt',\n  ecommerce: {\n    impressions: [\n      {\n        id: 'sku-abc',\n        name: 'Great T-Shirt - Black',\n        brand: 'Bukwild',\n        category: 'Shirts',\n        variant: 'Black',\n        price: 18.99,\n        list: 'Shirts Collection',\n        position: 3\n      }\n    ]\n  }\n}\n```\n\n\n#### [Product Clicks](https://developers.google.com/tag-manager/enhanced-ecommerce#product-clicks)\n\n```js\ngtmEcomm.productClick(variantPayload, options)\n```\n\nUsed when a user clicks on a product, like to go to it's detail view.\n\n- `variantPayload` - Described above\n\n- `options` - Supports the following keys:\n  - `el` - Optional DOM Element. If supplied, will be used to calulate the `position` by comparing the element's index relative it's parent.\n  - `list` - Optional name of the list or collection to which the product belongs.\n  - `position` - Optional position in a list or collection, 1-based.\n  - `clickEvent` - Optionally pass the click event object here to wait to change page until the event has been pushed.\n\nPushes an object to the dataLayer that looks like:\n\n```js\n{\n  event: 'Product Click',\n  firstOccurance: true,\n  sku: 'sku-abc',\n  variantId: '123',\n  variantTitle: 'Black',\n  variantImage: 'https://cdn.shopify.com/s/files/...',\n  variantUrl: 'https://www.shop.com/product/great-t-shirt?variant=123',\n  price: 18.99,\n  compareAtPrice: 20.99,\n  productId: '456',\n  productTitle: 'Great T-Shirt',\n  productVariantTitle: 'Great T-Shirt - Black',\n  productType: 'Shirts',\n  productVendor: 'Bukwild',\n  productUrl: 'https://www.shop.com/product/great-t-shirt',\n  ecommerce: {\n    click: {\n      actionField: { list: 'Shirts Collection'},\n      products: [\n        {\n          id: 'sku-abc',\n          name: 'Great T-Shirt - Black',\n          brand: 'Bukwild',\n          category: 'Shirts',\n          variant: 'Black',\n          price: 18.99,\n          position: 3\n        }\n      ]\n    }\n  }\n}\n```\n\n\n#### [Product Detail Impressions](https://developers.google.com/tag-manager/enhanced-ecommerce#details)\n\nUsed on product detail pages whenever the variant changes.\n\n```js\ngtmEcomm.viewProductDetails(variantPayload)\n```\n\n- `variantPayload` - See above\n\nPushes an object to the dataLayer that looks like:\n\n```js\n{\n  event: 'View Product Details',\n  firstOccurance: true,\n  sku: 'sku-abc',\n  variantId: '123',\n  variantTitle: 'Black',\n  variantImage: 'https://cdn.shopify.com/s/files/...',\n  variantUrl: 'https://www.shop.com/product/great-t-shirt?variant=123',\n  price: 18.99,\n  compareAtPrice: 20.99,\n  productId: '456',\n  productTitle: 'Great T-Shirt',\n  productVariantTitle: 'Great T-Shirt - Black',\n  productType: 'Shirts',\n  productVendor: 'Bukwild',\n  productUrl: 'https://www.shop.com/product/great-t-shirt',\n  ecommerce: {\n    detail: {\n      products: [\n        {\n          id: 'sku-abc',\n          name: 'Great T-Shirt - Black',\n          brand: 'Bukwild',\n          category: 'Shirts',\n          variant: 'Black',\n          price: 18.99\n        }\n      ]\n    }\n  }\n}\n```\n\nThe `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:\n\n![](https://p-9WF55W9.t1.n0.cdn.getcloudapp.com/items/jkuLeNJ7/e26dc5b9-fea3-4c81-b80f-666e12571f7f.jpg?v=f198b8de6a95af66c4789f1bc44ffdfa)\n\n#### [Add / Remove from Cart](https://developers.google.com/tag-manager/enhanced-ecommerce#cart)\n\nUsed when products are added or removed from the cart.\n\n```js\ngtmEcomm.addToCart(variantPayload, quantity)\ngtmEcomm.removeFromCart(variantPayload, quantity)\n```\n\n- `variantPayload` - See above\n- `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`.\n\nPushes an object to the dataLayer that looks like:\n\n```js\n{\n  event: 'Add to Cart',\n  firstOccurance: true,\n  quantity: 1,\n  sku: 'sku-abc',\n  variantId: '123',\n  variantTitle: 'Black',\n  variantImage: 'https://cdn.shopify.com/s/files/...',\n  variantUrl: 'https://www.shop.com/product/great-t-shirt?variant=123',\n  price: 18.99,\n  compareAtPrice: 20.99,\n  productId: '456',\n  productTitle: 'Great T-Shirt',\n  productVariantTitle: 'Great T-Shirt - Black',\n  productType: 'Shirts',\n  productVendor: 'Bukwild',\n  productUrl: 'https://www.shop.com/product/great-t-shirt',\n  ecommerce: {\n    add: {\n      currencyCode: 'USD',\n      products: [\n        {\n          id: 'sku-abc',\n          name: 'Great T-Shirt - Black',\n          brand: 'Bukwild',\n          category: 'Shirts',\n          variant: 'Black',\n          price: 18.99,\n          quantity: 1\n        }\n      ]\n    }\n  }\n}\n```\n\n_or_ like this\n\n```js\n{\n  event: 'Remove from Cart',\n  firstOccurance: true,\n  quantity: 1,\n  sku: 'sku-abc',\n  variantId: '123',\n  variantTitle: 'Black',\n  variantImage: 'https://cdn.shopify.com/s/files/...',\n  variantUrl: 'https://www.shop.com/product/great-t-shirt?variant=123',\n  price: 18.99,\n  compareAtPrice: 20.99,\n  productId: '456',\n  productTitle: 'Great T-Shirt',\n  productVariantTitle: 'Great T-Shirt - Black',\n  productType: 'Shirts',\n  productVendor: 'Bukwild',\n  productUrl: 'https://www.shop.com/product/great-t-shirt',\n  ecommerce: {\n    remove: {\n      currencyCode: 'USD',\n      products: [\n        {\n          id: 'sku-abc',\n          name: 'Great T-Shirt - Black',\n          brand: 'Bukwild',\n          category: 'Shirts',\n          variant: 'Black',\n          price: 18.99,\n          quantity: 1\n        }\n      ]\n    }\n  }\n}\n```\n\nSee above for info on `firstOccurance`.\n\n\n### Cart Updated\n\nUsed to send the current checkout / cart state to GTM.  This is not an explicit Enhanced Ecommerce event but many GTM want this data.\n\n```js\ngtmEcomm.cartUpdated(checkoutOrCartPayload)\n```\n\n- `checkoutOrCartPayload` - Either a [Cart](https://shopify.dev/api/storefront/reference/cart/cart) or [Checkout](https://shopify.dev/api/storefront/reference/checkouts/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).\n\nPushes an object to the dataLayer that looks like:\n\n```js\n{\n  event: 'Cart Updated',\n  firstOccurance: true,\n  checkoutId: '789',\n  checkoutUrl: 'https://www.shop.com/.../checkouts/...',\n  subtotalPrice: 18.99,\n  totalPrice: 18.99,\n  lineItems: [\n    {\n      lineItemId: '456',\n      quantity: 1,\n      sku: 'sku-abc',\n      variantId: '123',\n      variantTitle: 'Black',\n      variantImage: 'https://cdn.shopify.com/s/files/...',\n      variantUrl: 'https://www.shop.com/product/great-t-shirt?variant=123',\n      price: 18.99,\n      compareAtPrice: 20.99,\n      productId: '456',\n      productTitle: 'Great T-Shirt',\n      productVariantTitle: 'Great T-Shirt - Black',\n      productType: 'Shirts',\n      productVendor: 'Bukwild',\n      productUrl: 'https://www.shop.com/product/great-t-shirt',\n    }\n  ]\n}\n```\n\n### [Checkout](https://developers.google.com/tag-manager/enhanced-ecommerce#checkout)\n\nThis would be triggered by each step of the checkout, like:\n\n```js\nif (window.Shopify \u0026\u0026 window.Shopify.Checkout) {\n  gtmEcomm.checkout(window.CHECKOUT_FOR_GTM_INSTRUMENTOR,\n    window.Shopify.Checkout.step)\n}\n```\n\n_Currently_, `window.Shopify.Checkout.step` resolves to:\n\n1. `\"contact_information\"`\n2. `\"shipping_method\"`\n3. `\"payment_method\"`\n4. `\"processing\"`\n5. `\"thank_you\"`\n6. `undefined` (becomes undefined on reload / order page)\n\nThe `CHECKOUT_FOR_GTM_INSTRUMENTOR` array is created by [checkout-snippet.liquid](./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.\n\nThis 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.\n\n```js\n{\n  event: 'Checkout',\n  firstOccurance: true,\n  checkoutStep: `contact_information`\n  checkoutId: '789',\n  checkoutUrl: 'https://www.shop.com/.../checkouts/...',\n  subtotalPrice: 18.99,\n  totalPrice: 18.99,\n  lineItems: [\n    {\n      lineItemId: '456',\n      quantity: 1,\n      sku: 'sku-abc',\n      variantId: '123',\n      variantTitle: 'Black',\n      variantImage: 'https://cdn.shopify.com/s/files/...',\n      variantUrl: 'https://www.shop.com/product/great-t-shirt?variant=123',\n      price: 18.99,\n      compareAtPrice: 20.99,\n      productId: '456',\n      productTitle: 'Great T-Shirt',\n      productVariantTitle: 'Great T-Shirt - Black',\n      productType: 'Shirts',\n      productVendor: 'Bukwild',\n      productUrl: 'https://www.shop.com/product/great-t-shirt',\n    }\n  ]\n}\n```\n\nIf `enableCheckoutEcommerceProperty` was set to `true`, the dataLayer will also include:\n\n```js\n{\n  ecommerce: {\n    checkout: {\n      actionField: {\n        step: 'contact_information'\n      },\n      products: [\n        {\n          id: 'sku-abc',\n          name: 'Great T-Shirt - Black',\n          brand: 'Bukwild',\n          category: 'Shirts',\n          variant: 'Black',\n          price: 18.99,\n          quantity: 1\n        }\n      ]\n    }\n  }\n}\n```\n\n\n#### [Purchases](https://developers.google.com/tag-manager/enhanced-ecommerce#purchases)\n\nShould be triggered on the thank you page after checkout.\n\n```js\nif (window.Shopify \u0026\u0026\n  window.Shopify.Checkout \u0026\u0026\n  window.Shopify.Checkout.step == 'thank_you') {\n  gtmEcomm.purchase(window.CHECKOUT_FOR_GTM_INSTRUMENTOR)\n}\n```\n\nLike Checkout, this isn't intended to replace Shopify's Enhannced Ecommerce support. It creates a payload like:\n\n```js\n{\n  event: 'Purchase',\n  firstOccurance: true,\n  checkoutId: '789',\n  checkoutUrl: 'https://www.shop.com/.../checkouts/...',\n  subtotalPrice: 18.99,\n  totalPrice: 18.99,\n  lineItems: [\n    {\n      lineItemId: '456',\n      quantity: 1,\n      sku: 'sku-abc',\n      variantId: '123',\n      variantTitle: 'Black',\n      variantImage: 'https://cdn.shopify.com/s/files/...',\n      variantUrl: 'https://www.shop.com/product/great-t-shirt?variant=123',\n      price: 18.99,\n      compareAtPrice: 20.99,\n      productId: '456',\n      productTitle: 'Great T-Shirt',\n      productVariantTitle: 'Great T-Shirt - Black',\n      productType: 'Shirts',\n      productVendor: 'Bukwild',\n      productUrl: 'https://www.shop.com/product/great-t-shirt',\n    }\n  ]\n}\n```\n\nIf `enableCheckoutEcommerceProperty` was set to `true`, the dataLayer will also include:\n\n```js\n{\n  ecommerce: {\n    purchase: {\n      actionField: {\n        id: ''\n        revenue: 18.99,\n        tax: 0.00,\n        shipping: 0.00,\n        coupon: 'one,two'\n      },\n      products: [\n        {\n          id: 'sku-abc',\n          name: 'Great T-Shirt - Black',\n          brand: 'Bukwild',\n          category: 'Shirts',\n          variant: 'Black',\n          price: 18.99,\n          quantity: 1\n        }\n      ]\n    }\n  }\n}\n```\n\n\n## Customer Info\nUsed to send the customer info to GTM. This is not an explicit Enhanced Ecommerce event but many GTM tags want this data.\n\n```js\ngtmEcomm.identifyCustomer(customer)\n```\n\n- `customer` - An object that contains customer email and id, like:\n```js\n{\n  id: '1234'\n  zip: '90210',\n  email: 'abcd@test.com',\n\n}\n```\n\nPushes an object to the dataLayer that looks like:\n\n```js\n{\n  event: 'Identify Customer',\n  customerId: '1234'\n  customerZip: '90210',\n  customerEmail: 'abcd@test.com',\n}\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbkwld%2Fshopify-gtm-instrumentor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbkwld%2Fshopify-gtm-instrumentor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbkwld%2Fshopify-gtm-instrumentor/lists"}