Introduction
In the digital world, where each click, scroll and any interaction is data that could provide useful insights to optimize your store, data management skill be a critical skill that unlock the potential. Google Tag Manager (GTM) playing the role of the core point of focus where the website tags are being taken care of, becomes a must-have tool for website owners due to it’s tracking and analyzing capabilities on user behaviour.
Although the right interface of your GTM is crucial, building an efficient data layer with relevant parameter information is the foundation of the whole process. Forget everything you knew about data collection and eCommerce Analytics and welcome to the ultimate GTM Data Layer for Shopify, the new solution that has been introduced to help you simplify data collection and supercharge your online store Analytics.
GTM Data Layer
Using the GTM Data Layer as a conductor between your site and different tracking instruments, it becomes easy to transfer the data and enables better analysis. As online seller institutions such as Shopify become more popular, it becomes clear that the GTM (Growth-Driven Marketing) strategy serves as the crux of one’s marketing plan that helps with enhancing user experience and marketing campaigns.
How to use GTM Data Layer for Shopify:
- To place the Google Tag Manager tracking code, go to theme edit, after <head> tag in theme.liquid file.
- Inside the snippets folder, create a new file and name it ultimate-datalayer. Copy the whole code from ultimate-datalayer.liquid folder of this repo to sinppet file ultimate-datalayer.liquid.
- In the theme.liquid file below your Google Tag Manager tracking code insert ultimate-datalayer.liquid file as {% render ‘ultimate-datalayer’ %}
Install Data Layer 1st call code on Shopify
Login into Shopify admin panel:
Online Store—-> Themes —-> Actions —-> Edit Code —-> Layout —-> theme.liquid (File) —->
> Put the Data Layer call code directly below the ending </head> tag
Within the theme.liquid layout, place this include snippet {% include ‘ultimate-datalayer’ %} right before the closing tag
Alla page: {% include ‘ultimate-datalayer’ %}
- From the shopify admin dashboard go to Settings >> Checkout (Scroll down) >> Additional scripts Copy all code from checkout.liquid from this repository to the Additional scripts field. Replace the example GTM example tracking ID 000-00000 with the real GTM tracking ID.
GTM Data Layer Code for Shopify
<script>
/**
* Author: Debashree Dutta
* Email: clientw41@gmail.com
* Linkedin: https://www.linkedin.com/in/digital-debashree-dutta/
* Website : https://www.digitaldebashreedutta.com
* Version: 2.1
* Last Update: 17 Feb 2024
*/
(function() {
class Ultimate_Shopify_DataLayer {
constructor() {
window.dataLayer = window.dataLayer || [];
// use a prefix of events name
this.eventPrefix = '';
//Keep the value false to get non-formatted product ID
this.formattedItemId = true;
// data schema
this.dataSchema = {
ecommerce: {
show: true
},
dynamicRemarketing: {
show: false,
business_vertical: 'retail'
}
}
// add to wishlist selectors
this.addToWishListSelectors = {
'addWishListIcon': '',
'gridItemSelector': '',
'productLinkSelector': 'a[href*="/products/"]'
}
// quick view selectors
this.quickViewSelector = {
'quickViewElement': '',
'gridItemSelector': '',
'productLinkSelector': 'a[href*="/products/"]'
}
// mini cart button selector
this.miniCartButton = [
'a[href="/cart"]',
];
this.miniCartAppersOn = 'click';
// begin checkout buttons/links selectors
this.beginCheckoutButtons = [
'input[name="checkout"]',
'button[name="checkout"]',
'a[href="/checkout"]',
'.additional-checkout-buttons',
];
// direct checkout button selector
this.shopifyDirectCheckoutButton = [
'.shopify-payment-button'
]
//Keep the value true if Add to Cart redirects to the cart page
this.isAddToCartRedirect = false;
// keep the value false if cart items increment/decrement/remove refresh page
this.isAjaxCartIncrementDecrement = true;
// Caution: Do not modify anything below this line, as it may result in it not functioning correctly.
this.cart = {{ cart | json }}
this.countryCode = "{{ shop.address.country_code }}";
this.collectData();
this.storeURL = "{{ shop.secure_url }}";
localStorage.setItem('shopCountryCode', this.countryCode);
}
updateCart() {
fetch("/cart.js")
.then((response) => response.json())
.then((data) => {
this.cart = data;
});
}
debounce(delay) {
let timeoutId;
return function(func) {
const context = this;
const args = arguments;
clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
func.apply(context, args);
}, delay);
};
}
collectData() {
this.customerData();
this.ajaxRequestData();
this.searchPageData();
this.miniCartData();
this.beginCheckoutData();
{% if template contains 'cart' %}
this.viewCartPageData();
{% endif %}
{% if template contains 'product' %}
this.productSinglePage();
{% endif %}
{% if template contains 'collection' %}
this.collectionsPageData();
{% endif %}
this.addToWishListData();
this.quickViewData();
this.formData();
this.phoneClickData();
this.emailClickData();
}
//logged in customer data
customerData() {
const currentUser = {};
{% if customer %}
currentUser.id = {{ customer.id }};
currentUser.first_name = "{{ customer.first_name }}";
currentUser.last_name = "{{ customer.last_name }}";
currentUser.full_name = "{{ customer.name }}";
currentUser.email = "{{ customer.email }}";
currentUser.phone = "{{ customer.default_address.phone }}";
{% if customer.default_address %}
currentUser.address = {
address_summary: "{{ customer.default_address.summary }}",
address1: "{{ customer.default_address.address1 }}",
address2: "{{ customer.default_address.address2 }}",
city: "{{ customer.default_address.city }}",
street: "{{ customer.default_address.street }}",
zip_code: "{{ customer.default_address.zip }}",
company: "{{ customer.default_address.company }}",
country: "{{ customer.default_address.country.name }}",
country_code: "{{ customer.default_address.country_code }}",
province: "{{ customer.default_address.province }}"
};
{% endif %}
{% endif %}
if (currentUser.email) {
currentUser.hash_email = "{{ customer.email | sha256 }}"
}
if (currentUser.phone) {
currentUser.hash_phone = "{{ customer.phone | sha256 }}"
}
window.dataLayer = window.dataLayer || [];
dataLayer.push({
customer: currentUser
});
}
// add_to_cart, remove_from_cart, search
ajaxRequestData() {
const self = this;
// handle non-ajax add to cart
if(this.isAddToCartRedirect) {
document.addEventListener('submit', function(event) {
const addToCartForm = event.target.closest('form[action="/cart/add"]');
if(addToCartForm) {
event.preventDefault();
const formData = new FormData(addToCartForm);
fetch(window.Shopify.routes.root + 'cart/add.js', {
method: 'POST',
body: formData
})
.then(response => {
window.location.href = "{{ routes.cart_url }}";
})
.catch((error) => {
console.error('Error:', error);
});
}
});
}
// fetch
let originalFetch = window.fetch;
let debounce = this.debounce(800);
window.fetch = function () {
return originalFetch.apply(this, arguments).then((response) => {
if (response.ok) {
let cloneResponse = response.clone();
let requestURL = arguments[0];
if(/.*\/search\/?.*\?.*q=.+/.test(requestURL) && !requestURL.includes('&requestFrom=uldt')) {
const queryString = requestURL.split('?')[1];
const urlParams = new URLSearchParams(queryString);
const search_term = urlParams.get("q");
debounce(function() {
fetch(`${self.storeURL}/search/suggest.json?q=${search_term}&resources[type]=product&requestFrom=uldt`)
.then(res => res.json())
.then(function(data) {
const products = data.resources.results.products;
if(products.length) {
const fetchRequests = products.map(product =>
fetch(`${self.storeURL}/${product.url.split('?')[0]}.js`)
.then(response => response.json())
.catch(error => console.error('Error fetching:', error))
);
Promise.all(fetchRequests)
.then(products => {
const items = products.map((product) => {
return {
product_id: product.id,
product_title: product.title,
variant_id: product.variants[0].id,
variant_title: product.variants[0].title,
vendor: product.vendor,
total_discount: 0,
final_price: product.price_min,
product_type: product.type,
quantity: 1
}
});
self.ecommerceDataLayer('search', {search_term, items});
})
}else {
self.ecommerceDataLayer('search', {search_term, items: []});
}
});
});
}
else if (requestURL.includes("/cart/add")) {
cloneResponse.text().then((text) => {
let data = JSON.parse(text);
if(data.items && Array.isArray(data.items)) {
data.items.forEach(function(item) {
self.ecommerceDataLayer('add_to_cart', {items: [item]});
})
} else {
self.ecommerceDataLayer('add_to_cart', {items: [data]});
}
self.updateCart();
});
}else if(requestURL.includes("/cart/change") || requestURL.includes("/cart/update")) {
cloneResponse.text().then((text) => {
let newCart = JSON.parse(text);
let newCartItems = newCart.items;
let oldCartItems = self.cart.items;
for(let i = 0; i < oldCartItems.length; i++) {
let item = oldCartItems[i];
let newItem = newCartItems.find(newItems => newItems.id === item.id);
if(newItem) {
if(newItem.quantity > item.quantity) {
// cart item increment
let quantity = (newItem.quantity - item.quantity);
let updatedItem = {...item, quantity}
self.ecommerceDataLayer('add_to_cart', {items: [updatedItem]});
self.updateCart();
}else if(newItem.quantity < item.quantity) {
// cart item decrement
let quantity = (item.quantity - newItem.quantity);
let updatedItem = {...item, quantity}
self.ecommerceDataLayer('remove_from_cart', {items: [updatedItem]});
self.updateCart();
}
}else {
self.ecommerceDataLayer('remove_from_cart', {items: [item]});
self.updateCart();
}
}
});
}
}
return response;
});
}
// end fetch
//xhr
var origXMLHttpRequest = XMLHttpRequest;
XMLHttpRequest = function() {
var requestURL;
var xhr = new origXMLHttpRequest();
var origOpen = xhr.open;
var origSend = xhr.send;
// Override the `open` function.
xhr.open = function(method, url) {
requestURL = url;
return origOpen.apply(this, arguments);
};
xhr.send = function() {
// Only proceed if the request URL matches what we're looking for.
if (requestURL.includes("/cart/add") || requestURL.includes("/cart/change") || /.*\/search\/?.*\?.*q=.+/.test(requestURL)) {
xhr.addEventListener('load', function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 400) {
if(/.*\/search\/?.*\?.*q=.+/.test(requestURL) && !requestURL.includes('&requestFrom=uldt')) {
const queryString = requestURL.split('?')[1];
const urlParams = new URLSearchParams(queryString);
const search_term = urlParams.get("q");
debounce(function() {
fetch(`${self.storeURL}/search/suggest.json?q=${search_term}&resources[type]=product&requestFrom=uldt`)
.then(res => res.json())
.then(function(data) {
const products = data.resources.results.products;
if(products.length) {
const fetchRequests = products.map(product =>
fetch(`${self.storeURL}/${product.url.split('?')[0]}.js`)
.then(response => response.json())
.catch(error => console.error('Error fetching:', error))
);
Promise.all(fetchRequests)
.then(products => {
const items = products.map((product) => {
return {
product_id: product.id,
product_title: product.title,
variant_id: product.variants[0].id,
variant_title: product.variants[0].title,
vendor: product.vendor,
total_discount: 0,
final_price: product.price_min,
product_type: product.type,
quantity: 1
}
});
self.ecommerceDataLayer('search', {search_term, items});
})
}else {
self.ecommerceDataLayer('search', {search_term, items: []});
}
});
});
}
else if(requestURL.includes("/cart/add")) {
const data = JSON.parse(xhr.responseText);
if(data.items && Array.isArray(data.items)) {
data.items.forEach(function(item) {
self.ecommerceDataLayer('add_to_cart', {items: [item]});
})
} else {
self.ecommerceDataLayer('add_to_cart', {items: [data]});
}
self.updateCart();
}else if(requestURL.includes("/cart/change")) {
const newCart = JSON.parse(xhr.responseText);
const newCartItems = newCart.items;
let oldCartItems = self.cart.items;
for(let i = 0; i < oldCartItems.length; i++) {
let item = oldCartItems[i];
let newItem = newCartItems.find(newItems => newItems.id === item.id);
if(newItem) {
if(newItem.quantity > item.quantity) {
// cart item increment
let quantity = (newItem.quantity - item.quantity);
let updatedItem = {...item, quantity}
self.ecommerceDataLayer('add_to_cart', {items: [updatedItem]});
self.updateCart();
}else if(newItem.quantity < item.quantity) {
// cart item decrement
let quantity = (item.quantity - newItem.quantity);
let updatedItem = {...item, quantity}
self.ecommerceDataLayer('remove_from_cart', {items: [updatedItem]});
self.updateCart();
}
}else {
self.ecommerceDataLayer('remove_from_cart', {items: [item]});
self.updateCart();
}
}
}
}
}
});
}
return origSend.apply(this, arguments);
};
return xhr;
};
//end xhr
}
// search event from search page
searchPageData() {
const self = this;
let pageUrl = window.location.href;
if(/.+\/search\?.*\&?q=.+/.test(pageUrl)) {
const queryString = pageUrl.split('?')[1];
const urlParams = new URLSearchParams(queryString);
const search_term = urlParams.get("q");
fetch(`{{ shop.secure_url }}/search/suggest.json?q=${search_term}&resources[type]=product&requestFrom=uldt`)
.then(res => res.json())
.then(function(data) {
const products = data.resources.results.products;
if(products.length) {
const fetchRequests = products.map(product =>
fetch(`${self.storeURL}/${product.url.split('?')[0]}.js`)
.then(response => response.json())
.catch(error => console.error('Error fetching:', error))
);
Promise.all(fetchRequests)
.then(products => {
const items = products.map((product) => {
return {
product_id: product.id,
product_title: product.title,
variant_id: product.variants[0].id,
variant_title: product.variants[0].title,
vendor: product.vendor,
total_discount: 0,
final_price: product.price_min,
product_type: product.type,
quantity: 1
}
});
self.ecommerceDataLayer('search', {search_term, items});
});
}else {
self.ecommerceDataLayer('search', {search_term, items: []});
}
});
}
}
// view_cart
miniCartData() {
if(this.miniCartButton.length) {
let self = this;
if(this.miniCartAppersOn === 'hover') {
this.miniCartAppersOn = 'mouseenter';
}
this.miniCartButton.forEach((selector) => {
let miniCartButtons = document.querySelectorAll(selector);
miniCartButtons.forEach((miniCartButton) => {
miniCartButton.addEventListener(self.miniCartAppersOn, () => {
self.ecommerceDataLayer('view_cart', self.cart);
});
})
});
}
}
// begin_checkout
beginCheckoutData() {
let self = this;
document.addEventListener('pointerdown', () => {
let targetElement = event.target.closest(self.beginCheckoutButtons.join(', '));
if(targetElement) {
self.ecommerceDataLayer('begin_checkout', self.cart);
}
});
}
// view_cart, add_to_cart, remove_from_cart
viewCartPageData() {
this.ecommerceDataLayer('view_cart', this.cart);
//if cart quantity chagne reload page
if(!this.isAjaxCartIncrementDecrement) {
const self = this;
document.addEventListener('pointerdown', (event) => {
const target = event.target.closest('a[href*="/cart/change?"]');
if(target) {
const linkUrl = target.getAttribute('href');
const queryString = linkUrl.split("?")[1];
const urlParams = new URLSearchParams(queryString);
const newQuantity = urlParams.get("quantity");
const line = urlParams.get("line");
const cart_id = urlParams.get("id");
if(newQuantity && (line || cart_id)) {
let item = line ? {...self.cart.items[line - 1]} : self.cart.items.find(item => item.key === cart_id);
let event = 'add_to_cart';
if(newQuantity < item.quantity) {
event = 'remove_from_cart';
}
let quantity = Math.abs(newQuantity - item.quantity);
item['quantity'] = quantity;
self.ecommerceDataLayer(event, {items: [item]});
}
}
});
}
}
productSinglePage() {
{% if template contains 'product' %}
const item = {
product_id: {{ product.id | json }},
variant_id: {{ product.selected_or_first_available_variant.id }},
product_title: {{ product.title | json }},
line_level_total_discount: 0,
vendor: {{ product.vendor | json }},
sku: {{ product.sku | json }},
product_type: {{ product.type | json }},
item_list_id: {{ product.collections[0].id | json }},
item_list_name: {{ product.collections[0].title | json }},
{% if product.selected_or_first_available_variant.title != "Default Title" %}
variant_title: {{ product.selected_or_first_available_variant.title | json }},
{% endif %}
final_price: {{ product.selected_or_first_available_variant.price }},
quantity: 1
};
const variants = {{ product.variants | json }}
this.ecommerceDataLayer('view_item', {items: [item]});
if(this.shopifyDirectCheckoutButton.length) {
let self = this;
document.addEventListener('pointerdown', (event) => {
let target = event.target;
let checkoutButton = event.target.closest(this.shopifyDirectCheckoutButton.join(', '));
if(checkoutButton && (variants || self.quickViewVariants)) {
let checkoutForm = checkoutButton.closest('form[action*="/cart/add"]');
if(checkoutForm) {
let variant_id = null;
let varientInput = checkoutForm.querySelector('input[name="id"]');
let varientIdFromURL = new URLSearchParams(window.location.search).get('variant');
let firstVarientId = item.variant_id;
if(varientInput) {
variant_id = parseInt(varientInput.value);
}else if(varientIdFromURL) {
variant_id = varientIdFromURL;
}else if(firstVarientId) {
variant_id = firstVarientId;
}
if(variant_id) {
variant_id = parseInt(variant_id);
let quantity = 1;
let quantitySelector = checkoutForm.getAttribute('id');
if(quantitySelector) {
let quentityInput = document.querySelector('input[name="quantity"][form="'+quantitySelector+'"]');
if(quentityInput) {
quantity = +quentityInput.value;
}
}
if(variant_id) {
let variant = variants.find(item => item.id === +variant_id);
if(variant && item) {
variant_id
item['variant_id'] = variant_id;
item['variant_title'] = variant.title;
item['final_price'] = variant.price;
item['quantity'] = quantity;
self.ecommerceDataLayer('add_to_cart', {items: [item]});
self.ecommerceDataLayer('begin_checkout', {items: [item]});
}else if(self.quickViewedItem) {
let variant = self.quickViewVariants.find(item => item.id === +variant_id);
if(variant) {
self.quickViewedItem['variant_id'] = variant_id;
self.quickViewedItem['variant_title'] = variant.title;
self.quickViewedItem['final_price'] = parseFloat(variant.price) * 100;
self.quickViewedItem['quantity'] = quantity;
self.ecommerceDataLayer('add_to_cart', {items: [self.quickViewedItem]});
self.ecommerceDataLayer('begin_checkout', {items: [self.quickViewedItem]});
}
}
}
}
}
}
});
}
{% endif %}
}
collectionsPageData() {
var ecommerce = {
'items': [
{% for product in collection.products %}
{
'product_id': {{ product.id | json }},
'variant_id': {{ product.selected_or_first_available_variant.id | json }},
'vendor': {{ product.vendor | json }},
'total_discount': 0,
'variant_title': {{ product.selected_or_first_available_variant.title | json }},
'product_title': {{ product.title | json }},
'final_price': Number({{ product.price }}),
'product_type': {{ product.type | json }},
'item_list_id': {{ collection.id | json }},
'item_list_name': {{ collection.title | json }},
'quantity': 1
},
{% endfor %}
]
};
ecommerce['item_list_id'] = {{ collection.id | json }}
ecommerce['item_list_name'] = {{ collection.title | json }}
this.ecommerceDataLayer('view_item_list', ecommerce);
}
// add to wishlist
addToWishListData() {
if(this.addToWishListSelectors && this.addToWishListSelectors.addWishListIcon) {
const self = this;
document.addEventListener('pointerdown', (event) => {
let target = event.target;
if(target.closest(self.addToWishListSelectors.addWishListIcon)) {
let pageULR = window.location.href.replace(/\?.+/, '');
let requestURL = undefined;
if(/\/products\/[^/]+$/.test(pageULR)) {
requestURL = pageULR;
} else if(self.addToWishListSelectors.gridItemSelector && self.addToWishListSelectors.productLinkSelector) {
let itemElement = target.closest(self.addToWishListSelectors.gridItemSelector);
if(itemElement) {
let linkElement = itemElement.querySelector(self.addToWishListSelectors.productLinkSelector);
if(linkElement) {
let link = linkElement.getAttribute('href').replace(/\?.+/g, '');
if(link && /\/products\/[^/]+$/.test(link)) {
requestURL = link;
}
}
}
}
if(requestURL) {
fetch(requestURL + '.json')
.then(res => res.json())
.then(result => {
let data = result.product;
if(data) {
let dataLayerData = {
product_id: data.id,
variant_id: data.variants[0].id,
product_title: data.title,
quantity: 1,
final_price: parseFloat(data.variants[0].price) * 100,
total_discount: 0,
product_type: data.product_type,
vendor: data.vendor,
variant_title: (data.variants[0].title !== 'Default Title') ? data.variants[0].title : undefined,
sku: data.variants[0].sku,
}
self.ecommerceDataLayer('add_to_wishlist', {items: [dataLayerData]});
}
});
}
}
});
}
}
quickViewData() {
if(this.quickViewSelector.quickViewElement && this.quickViewSelector.gridItemSelector && this.quickViewSelector.productLinkSelector) {
const self = this;
document.addEventListener('pointerdown', (event) => {
let target = event.target;
if(target.closest(self.quickViewSelector.quickViewElement)) {
let requestURL = undefined;
let itemElement = target.closest(this.quickViewSelector.gridItemSelector );
if(itemElement) {
let linkElement = itemElement.querySelector(self.quickViewSelector.productLinkSelector);
if(linkElement) {
let link = linkElement.getAttribute('href').replace(/\?.+/g, '');
if(link && /\/products\/[^/]+$/.test(link)) {
requestURL = link;
}
}
}
if(requestURL) {
fetch(requestURL + '.json')
.then(res => res.json())
.then(result => {
let data = result.product;
if(data) {
let dataLayerData = {
product_id: data.id,
variant_id: data.variants[0].id,
product_title: data.title,
quantity: 1,
final_price: parseFloat(data.variants[0].price) * 100,
total_discount: 0,
product_type: data.product_type,
vendor: data.vendor,
variant_title: (data.variants[0].title !== 'Default Title') ? data.variants[0].title : undefined,
sku: data.variants[0].sku,
}
self.ecommerceDataLayer('view_item', {items: [dataLayerData]});
self.quickViewVariants = data.variants;
self.quickViewedItem = dataLayerData;
}
});
}
}
});
{% unless template contains 'product' %}
if(this.shopifyDirectCheckoutButton.length) {
let self = this;
document.addEventListener('pointerdown', (event) => {
let target = event.target;
let checkoutButton = event.target.closest(this.shopifyDirectCheckoutButton.join(', '));
if(self.quickViewVariants && self.quickViewedItem && self.quickViewVariants.length && checkoutButton) {
let checkoutForm = checkoutButton.closest('form[action*="/cart/add"]');
if(checkoutForm) {
let quantity = 1;
let varientInput = checkoutForm.querySelector('input[name="id"]');
let quantitySelector = checkoutForm.getAttribute('id');
if(quantitySelector) {
let quentityInput = document.querySelector('input[name="quantity"][form="'+quantitySelector+'"]');
if(quentityInput) {
quantity = +quentityInput.value;
}
}
if(varientInput) {
let variant_id = parseInt(varientInput.value);
if(variant_id) {
const variant = self.quickViewVariants.find(item => item.id === +variant_id);
if(variant && self.quickViewedItem) {
self.quickViewedItem['variant_id'] = variant_id;
self.quickViewedItem['variant_title'] = variant.title;
self.quickViewedItem['final_price'] = parseFloat(variant.price) * 100;
self.quickViewedItem['quantity'] = quantity;
self.ecommerceDataLayer('add_to_cart', {items: [self.quickViewedItem]});
self.ecommerceDataLayer('begin_checkout', {items: [self.quickViewedItem]});
}
}
}
}
}
});
}
{% endunless %}
}
}
// all ecommerce events
ecommerceDataLayer(event, data) {
const self = this;
dataLayer.push({ 'ecommerce': null });
const dataLayerData = {
"event": this.eventPrefix + event,
'ecommerce': {
'currency': this.cart.currency,
'items': data.items.map((item, index) => {
const dataLayerItem = {
'index': index,
'item_id': this.formattedItemId ? `shopify_${this.countryCode}_${item.product_id}_${item.variant_id}` : item.product_id.toString(),
'product_id': item.product_id.toString(),
'variant_id': item.variant_id.toString(),
'item_name': item.product_title,
'quantity': item.quantity,
'price': +((item.final_price / 100).toFixed(2)),
'discount': item.total_discount ? +((item.total_discount / 100).toFixed(2)) : 0
}
if(item.product_type) {
dataLayerItem['item_category'] = item.product_type;
}
if(item.vendor) {
dataLayerItem['item_brand'] = item.vendor;
}
if(item.variant_title && item.variant_title !== 'Default Title') {
dataLayerItem['item_variant'] = item.variant_title;
}
if(item.sku) {
dataLayerItem['sku'] = item.sku;
}
if(item.item_list_name) {
dataLayerItem['item_list_name'] = item.item_list_name;
}
if(item.item_list_id) {
dataLayerItem['item_list_id'] = item.item_list_id.toString()
}
return dataLayerItem;
})
}
}
if(data.total_price !== undefined) {
dataLayerData['ecommerce']['value'] = +((data.total_price / 100).toFixed(2));
} else {
dataLayerData['ecommerce']['value'] = +(dataLayerData['ecommerce']['items'].reduce((total, item) => total + (item.price * item.quantity), 0)).toFixed(2);
}
if(data.item_list_id) {
dataLayerData['ecommerce']['item_list_id'] = data.item_list_id;
}
if(data.item_list_name) {
dataLayerData['ecommerce']['item_list_name'] = data.item_list_name;
}
if(data.search_term) {
dataLayerData['search_term'] = data.search_term;
}
if(self.dataSchema.dynamicRemarketing && self.dataSchema.dynamicRemarketing.show) {
dataLayer.push({ 'dynamicRemarketing': null });
dataLayerData['dynamicRemarketing'] = {
value: dataLayerData.ecommerce.value,
items: dataLayerData.ecommerce.items.map(item => ({id: item.item_id, google_business_vertical: self.dataSchema.dynamicRemarketing.business_vertical}))
}
}
if(!self.dataSchema.ecommerce || !self.dataSchema.ecommerce.show) {
delete dataLayerData['ecommerce'];
}
dataLayer.push(dataLayerData);
}
// contact form submit & newsletters signup
formData() {
const self = this;
document.addEventListener('submit', function(event) {
let targetForm = event.target.closest('form[action^="/contact"]');
if(targetForm) {
const formData = {
form_location: window.location.href,
form_id: targetForm.getAttribute('id'),
form_classes: targetForm.getAttribute('class')
};
let formType = targetForm.querySelector('input[name="form_type"]');
let inputs = targetForm.querySelectorAll("input:not([type=hidden]):not([type=submit]), textarea, select");
inputs.forEach(function(input) {
var inputName = input.name;
var inputValue = input.value;
if (inputName && inputValue) {
var matches = inputName.match(/\[(.*?)\]/);
if (matches && matches.length > 1) {
var fieldName = matches[1];
formData[fieldName] = input.value;
}
}
});
if(formType && formType.value === 'customer') {
dataLayer.push({ event: self.eventPrefix + 'newsletter_signup', ...formData});
} else if(formType && formType.value === 'contact') {
dataLayer.push({ event: self.eventPrefix + 'contact_form_submit', ...formData});
}
}
});
}
// phone_number_click event
phoneClickData() {
const self = this;
document.addEventListener('click', function(event) {
let target = event.target.closest('a[href^="tel:"]');
if(target) {
let phone_number = target.getAttribute('href').replace('tel:', '');
dataLayer.push({
event: self.eventPrefix + 'phone_number_click',
page_location: window.location.href,
link_classes: target.getAttribute('class'),
link_id: target.getAttribute('id'),
phone_number
})
}
});
}
// email_click event
emailClickData() {
const self = this;
document.addEventListener('click', function(event) {
let target = event.target.closest('a[href^="mailto:"]');
if(target) {
let email_address = target.getAttribute('href').replace('mailto:', '');
dataLayer.push({
event: self.eventPrefix + 'email_click',
page_location: window.location.href,
link_classes: target.getAttribute('class'),
link_id: target.getAttribute('id'),
email_address
})
}
});
}
}
// end Ultimate_Shopify_DataLayer
document.addEventListener('DOMContentLoaded', function() {
try{
new Ultimate_Shopify_DataLayer();
}catch(error) {
console.log(error);
}
});
})();
</script>
Events Included
Ultimate Shopify GTM – Our Data Layer for Converting Information to Events is facilitated by a multitude of occurence to convey diverse customer interactions. Some of the key events tracked include:Some of the key events tracked include:
- view_item: To view a specific product or record any thoughts on that.
- view_item_list: A customer can see a number of offered items.
- add_to_cart: click on “add to cart” of the product.
- remove_from_cart: If an item is dropped from the cart of the shopper.
- view_cart: Couple of days later, I click on the shopping cart icon and I get to see the real deal about what’s inside the cart after I have spent a week shopping:
- begin_checkout: The buyers work on the checkout process.
- add_to_wishlist: Adding an item to the ‘want’ list.
- purchase: Completing a purchase.
- newsletter_signup: Subscribing emails.
- search: Discuss the efficiency of Google, starting with research on its website.
- phone_number_click: Scrolling thru the listing of them.
- email_click: After clicking one of the email addresses.
GTM Data Layer Check Out web pixel Code for Shopify
const event_prefix = '';
const formattedItemId = true;
const gclidWithPageLocation = true;
const GTM_container_url = 'https://www.googletagmanager.com';
const GTM_container_id = 'GTM-00000000';
let storeCountryCode = window.localStorage.getItem('shopCountryCode');
storeCountryCode = storeCountryCode || 'US';
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
//checkout pages event
if(/.+\/checkouts?\/.*/.test(window.location.href)) {
// tag manager
(function(w, d, s, l, i) {
w[l] = w[l] || [];
w[l].push({
'gtm.start': new Date().getTime(),
event: 'gtm.js'
});
var f = d.getElementsByTagName(s)[0],
j = d.createElement(s),
dl = l != 'dataLayer' ? '&l=' + l : '';
j.async = true;
j.src = GTM_container_url + '/gtm.js?id=' + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', GTM_container_id);
analytics.subscribe('page_viewed', (event) => {
const eventData = {
event: event_prefix + 'page_view',
page_location: getPageLocation(event),
}
window.dataLayer.push(eventData);
eventLog('page_view', eventData);
});
// end tag manager
// DataLayer Events
analytics.subscribe('payment_info_submitted', (event) => ecommerceDataLayer('add_payment_info', event));
analytics.subscribe('checkout_shipping_info_submitted', (event) => ecommerceDataLayer('add_shipping_info', event));
analytics.subscribe('checkout_completed', (event) => ecommerceDataLayer('purchase', event));
}
function eventLog(eventName, eventData) {
const css1 = 'background: red; color: #fff; font-size: normal; border-radius: 3px 0 0 3px; padding: 3px 4px;';
const css2 = 'background-color: blue; color: #fff; font-size: normal; border-radius: 0 3px 3px 0; padding: 3px 4px;';
console.log(
'%cGTM DataLayer Event:%c' + event_prefix + eventName, css1, css2, eventData
);
}
function getPageLocation(event) {
let pageLocation = event.context.document.location.href;
if(gclidWithPageLocation) {
const name = '_gcl_aw';
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) {
const gclidCookie = parts.pop().split(';').shift();
const gclidParts = gclidCookie.split('.');
const gclid = gclidParts[gclidParts.length - 1];
pageLocation = pageLocation.includes('?') ? `${pageLocation}&gclid=${gclid}` : `${pageLocation}?gclid=${gclid}`;
}
}
return pageLocation;
}
async function sha256Hash(value) {
const encoder = new TextEncoder();
const data = encoder.encode(value);
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashedValue = hashArray.map(byte => ('00' + byte.toString(16)).slice(-2)).join('');
return hashedValue;
}
async function ecommerceDataLayer(gtm_event_name, event) {
let hash_email;
let hash_phone;
const phone = event.data?.checkout?.phone;
const email = event.data?.checkout?.email;
if (phone) {
hash_phone = await sha256Hash(phone);
}
if (email) {
hash_email = await sha256Hash(email);
}
const customerInfo = {
customer: {
first_name: event.data?.checkout?.billingAddress?.firstName || event.data?.checkout?.shippingAddress?.firstName,
last_name: event.data?.checkout?.billingAddress?.lastName || event.data?.checkout?.shippingAddress?.lastName,
email: email,
hash_email: hash_email,
phone: phone,
hash_phone: hash_phone,
address: event.data?.checkout?.shippingAddress
}
}
dataLayer.push(customerInfo);
const dataLayerInfo = {
event: event_prefix + gtm_event_name,
page_location: getPageLocation(event),
ecommerce: {
transaction_id: event.data?.checkout?.order?.id,
value: event.data?.checkout?.totalPrice?.amount,
tax: event.data?.checkout?.totalTax?.amount,
shipping: event.data?.checkout?.shippingLine?.price?.amount,
currency: event.data?.checkout?.currencyCode,
coupon: (event.data?.checkout?.discountApplications || []).map(discount => discount.title).join(','),
items: (event.data?.checkout?.lineItems || []).map(item => ({
item_id: formattedItemId ? 'shopify_' + storeCountryCode + '_' + (item.variant?.product?.id || '') + '_' + (item.variant?.id || '') : item.variant?.product?.id,
product_id: item.variant?.product?.id,
variant_id: item.variant?.id,
sku: item.variant?.sku,
item_name: item.title,
coupon: item.discountAllocations?.discountApplication?.title,
discount: item.discountAllocations?.amount?.amount,
item_variant: item.variant?.title,
price: item.variant?.price?.amount,
quantity: item.quantity,
item_brand: item.variant?.product?.vendor,
item_category: item.variant?.product?.type
}))
}
}
dataLayer.push({
ecommerce: null
});
dataLayer.push(dataLayerInfo);
eventLog(gtm_event_name, Object.assign({}, dataLayerInfo, customerInfo));
}
Event Parameters
Every event comes with i/o parameters, which serve as a yardstick to measuring the behavior of the customers.These parameters include:
- currency: What sort of money will be exchanged in this case?
- value: What is being paid for.
- transaction_id: Unique ID or hashes of the transactions.
- coupon: The coupon ecais par vis-à-vis de la transaction.
- shipping: The shipping cost.
- vat: The value-added tax.
- items: List of the items that are bought.
- item_list_name: – Items the list is called.
- item_list_id: The identifier ID of the item list.

Features and Benefits of GTM Data Layer for Shopify
The Ultimate GTM Data Layer for Shopify offers several features and benefits to enhance your tracking capabilities:The Ultimate GTM Data Layer for Shopify offers several features and benefits to enhance your tracking capabilities:
- Comprehensive Event Tracking: Besides standard events such as an item’s Quick View, and Mini Cart tracking, shopping pages, and Shopify Checkout are also monitored in detail.
Ajax Response Tracking: Ajax response is used to monitor the events and thereby the data collection is performed with precise details without unforeseen discrepancies between the figures. - Error Handling: To avoid JavaScript errors, ES6 Object Oriented Way is implemented in dealing with it in a fine manner with error handling as can easily be observed.
- Lightweight and Efficient: The solution doesn’t depend on jQuery or any third-party scripts which are added to the web page so it is fast performing and secure website as well.
Conclusion
Today, the e-commerce realm is extremely dynamic and the decisive factor in it is the data analytics. adapted the Ultimate GTM Data Layer for Shopify, works as the tool that can bring your business powerful with the high-level tracking capability, it turns you can trace the behavior of customers, optimize marketing strategies, and attain growth. The solution is feature-rich, and integrates seamlessly with current e-commerce platforms, to satisfy the dynamic needs of various modern e-commerce businesses. Take your brand’s tracking to the next level with our Shopify app and unleash the full power!
To get update information follow my social media.
To get our service click here
Related Articles

I am Service Provider of Digital Marketing . I am confident that my professional skills, expertise and
experience make me the ideal candidate for this role. As a SEO,Shopify Store and Ads Expert, I bring specialized knowledge in:
📊 Google Analytics🏷️ Google Tag Manager🎯 Google Search Console Set Up 🔝 Google Top Ranking Strategies📊Web Analytics🔍 On Page SEO🔗 Off Page SEO🔧 Technical SEO📑 Google Indexing📢 Google & Facebook Ads📈 Social Media Marketing🎥 YouTube Promotion📑Shopify Store create
Here you will find also honest reviews about recommended software tools and other digital marketing tools which will give you new abilities, knowledge and skills in your internet marketing strategies and Improve your online profits.