Skip to content

Instantly share code, notes, and snippets.

@blanklob
Created July 1, 2023 23:40
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save blanklob/35f290c2428aef51a56593cca34553c8 to your computer and use it in GitHub Desktop.
Save blanklob/35f290c2428aef51a56593cca34553c8 to your computer and use it in GitHub Desktop.
Google Analytics 4 Shopify Custom Pixel
// Step 1. Add and initialize your third-party JavaScript pixel (make sure to exclude HTML)
// Replace with you GA4 Tag
const TAG_ID = 'G-XXXXXXXXXX';
const script = document.createElement('script');
script.setAttribute('src', `https://www.googletagmanager.com/gtag/js?id=${TAG_ID}`);
script.setAttribute('async', '');
document.head.appendChild(script);
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', TAG_ID);
// Step 2. Subscribe to customer events using the analytics.subscribe() API
const sendGAEvent = (eventName, eventData) => {
gtag("event", eventName, eventData);
};
const createItemData = (product) => {
return {
item_id: product.sku,
item_name: product.product.title,
item_variant: product.title,
currency: product.price.currencyCode,
item_brand: product.product.vendor,
price: product.price.amount,
};
};
const createLineItemsData = (lineItems) => {
return lineItems.map((item) => {
return {
item_id: item.variant.sku,
item_name: item.title,
item_variant: item?.variant.title,
currency: item.variant.price.currencyCode,
item_brand: item.variant.product.vendor,
price: item.variant.price.amount,
quantity: item.quantity,
};
});
};
analytics.subscribe("search_submitted", (event) => {
const { query } = event.data.searchResult;
sendGAEvent("search", { search_term: query });
sendGAEvent("view_search_results", { search_term: query, items: [] });
});
analytics.subscribe("collection_viewed", (event) => {
const { id, title } = event.data.collection;
sendGAEvent("view_item_list", { item_list_id: id, item_list_name: title, items: [] });
});
analytics.subscribe("product_added_to_cart", (event) => {
const { cartLine } = event.data;
const totalPrice = cartLine.merchandise.price.amount * cartLine.quantity;
const itemData = createItemData(cartLine.merchandise.product);
sendGAEvent("add_to_cart", {
currency: cartLine.merchandise.price.currencyCode,
value: totalPrice.toFixed(2),
items: [Object.assign(itemData, { quantity: cartLine.quantity })],
});
});
analytics.subscribe("product_viewed", (event) => {
const { productVariant } = event.data;
const itemData = createItemData(productVariant);
sendGAEvent("view_item", {
currency: productVariant.price.currencyCode,
value: productVariant.price.amount,
items: [itemData],
});
});
analytics.subscribe("checkout_started", (event) => {
const checkoutData = ga4CheckoutEvents(event);
sendGAEvent("begin_checkout", checkoutData);
});
analytics.subscribe("payment_info_submitted", (event) => {
const checkoutData = ga4CheckoutEvents(event);
sendGAEvent("add_payment_info", checkoutData);
});
analytics.subscribe("checkout_completed", (event) => {
const checkoutData = ga4CheckoutEvents(event);
const { checkout } = event.data;
checkoutData.transaction_id = checkout.order?.id || checkout.token;
checkoutData.shipping = checkout.shippingLine?.price.amount || checkout.shipping_line?.price.amount || 0;
checkoutData.tax = checkout.totalTax?.amount || 0;
sendGAEvent("purchase", checkoutData);
});
function ga4CheckoutEvents(event) {
const { checkout } = event.data;
const lineItems = createLineItemsData(checkout.lineItems);
return {
currency: checkout.totalPrice.currencyCode,
value: checkout.totalPrice.amount,
items: lineItems,
};
}
@blanklob
Copy link
Author

blanklob commented Jul 1, 2023

This a refactored version of the original one create by Kevin Dees in his blog:

@capatina
Copy link

capatina commented Nov 24, 2023

Hey @blanklob, pretty good script. You should add that the customer event pixel doesn't send decent page view data to GA4 (https://help.shopify.com/en/manual/promoting-marketing/pixels/custom-pixels/gtm-tutorial). Best to do the following:

  • disable default page view tracking:
    gtag('config', TAG_ID, {'send_page_view': false});

  • send page view data with custom event instead:

analytics.subscribe("page_viewed", event => {
  gtag("event", "page_view", {
    page_location: event.context.window.location.href,
    page_title: event.context.document.title,
    language: event.context.navigator.language,
    page_encoding: event.context.document.characterSet,
    user_agent:  event.context.navigator.userAgent,
    client_id: event.clientId
  });
});

reference: https://developers.google.com/tag-platform/gtagjs/reference/events#page_view

@capatina
Copy link

capatina commented Nov 24, 2023

Also worth noting is that "enhanced conversions" don't work. You can add outbound link tracking via custom event, but it's easier to disable all of it in GA4 like so:

image

@capatina
Copy link

also disable here for a big pagespeed boost:
image

@luukfiets
Copy link

@blanklob

For line 59 I'm wondering if there is a difference between look at cartline.cost.totalAmount.amount instead of cartLine.merchandise.price.amount * cartLine.quantity. It seems that with the first option, no calculation is needed. I'm not sure if it gives back the same price. I'm happy to hear so if you have an idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment