Shopify Events

Tag Manager Web Container

Make sure to have a GA4 Event Tag, with the event name coming from the {{ Event }}, and sends the Ecommerce settings from the dataLayer.

Trigger on event name regex match of:

(add_payment_info|add_shipping_info|add_to_cart|add_to_wishlist|begin_checkout|purchase|refund|remove_from_cart|select_item|select_promotion|view_cart|view_item|view_item_list|view_promotion)

Shopify Settings GA4

In the customer events, just copy and paste this code with the correct info:

;(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 = 'https://{{ METRICS_URL }}/gtm.js?id=' + i + dl
  f.parentNode.insertBefore(j, f)
})(window, document, 'script', 'dataLayer', '{{ WEB_CONTAINER_ID }}')

analytics.subscribe("page_viewed", ({ id }) => {
  dataLayer.push({ event: "page_view", event_id: id });
});

function ensureVariant(line) {
  return line.variant != null;
}
function mapVariant(variant, index) {
  return {
    item_id: variant.product.id,
    item_name: variant.product.title,
    index,
    item_category: variant.product.type,
    item_variant: variant.title,
    price: variant.price.amount,
  };
}
function mapLineItem(line, index) {
  return {
    ...mapVariant(line.variant, index),
    index,
    coupon: line.discountAllocations[0]?.discountApplication.allocationMethod,
    discount: line.discountAllocations[0]?.amount.amount,
    quantity: line.quantity,
  };
}
analytics.subscribe("cart_viewed", ({ id, data: { cart } }) => {
  if (cart) {
    dataLayer.push({ ecommerce: null });
    dataLayer.push({
      event: "view_cart",
      event_id: id,
      ecommerce: {
        currency: cart.cost.totalAmount.currencyCode,
        value: cart.cost.totalAmount.amount,
        items: cart.lines.map((line, index) => ({
          item_id: line.merchandise.product.id,
          item_name: line.merchandise.product.title,
          index,
          item_category: line.merchandise.product.type,
          item_variant: line.merchandise.title,
          price: line.merchandise.price.amount,
          quantity: line.quantity,
        })),
      },
    });
  }
});
analytics.subscribe(
  "checkout_address_info_submitted",
  ({ id, data: { checkout } }) => {
    dataLayer.push({ ecommerce: null });
    dataLayer.push({
      event: "add_shipping_info",
      event_id: id,
      ecommerce: {
        coupon: checkout.discountApplications[0]?.title,
        currency: checkout.currencyCode,
        value: checkout.subtotalPrice.amount,
        items: checkout.lineItems.filter(ensureVariant).map(mapLineItem),
      },
    });
  },
);
analytics.subscribe("checkout_completed", ({ id, data: { checkout } }) => {
  dataLayer.push({ ecommerce: null });
  dataLayer.push({
    event: "purchase",
    event_id: id,
    ecommerce: {
      currency: checkout.currencyCode,
      value: checkout.subtotalPrice.amount,
      shipping: checkout.shippingLine?.price.amount,
      tax: checkout.totalTax.amount,
      transaction_id: checkout.token,
      coupon: checkout.discountApplications[0]?.title,
      items: checkout.lineItems.filter(ensureVariant).map(mapLineItem),
    },
  });
});
analytics.subscribe("checkout_started", ({ id, data: { checkout } }) => {
  dataLayer.push({ ecommerce: null });
  dataLayer.push({
    event: "begin_checkout",
    event_id: id,
    ecommerce: {
      currency: checkout.currencyCode,
      value: checkout.subtotalPrice.amount,
      coupon: checkout.discountApplications[0]?.title,
      items: checkout.lineItems.filter(ensureVariant).map(mapLineItem),
    },
  });
});
analytics.subscribe("collection_viewed", ({ id, data: { collection } }) => {
  dataLayer.push({ ecommerce: null });
  dataLayer.push({
    event: "view_item_list",
    event_id: id,
    ecommerce: {
      item_list_id: collection.id,
      item_list_name: collection.title,
      items: collection.productVariants.map((variant, index) => ({
        ...mapVariant(variant, index),
        item_list_id: collection.id,
        item_list_name: collection.title,
      })),
    },
  });
});
analytics.subscribe("payment_info_submitted", ({ id, data: { checkout } }) => {
  dataLayer.push({ ecommerce: null });
  dataLayer.push({
    event: "add_payment_info",
    event_id: id,
    ecommerce: {
      currency: checkout.currencyCode,
      value: checkout.subtotalPrice.amount,
      coupon: checkout.discountApplications[0]?.title,
      items: checkout.lineItems.filter(ensureVariant).map(mapLineItem),
    },
  });
});
analytics.subscribe("product_added_to_cart", ({ id, data: { cartLine } }) => {
  if (cartLine != null) {
    dataLayer.push({ ecommerce: null });
    dataLayer.push({
      event: "add_to_cart",
      event_id: id,
      ecommerce: {
        currency: cartLine.cost.totalAmount.currencyCode,
        value: cartLine.cost.totalAmount.amount,
        items: [
          {
            ...mapVariant(cartLine.merchandise, 0),
            quantity: cartLine.quantity,
          },
        ],
      },
    });
  }
});
analytics.subscribe("product_viewed", ({ id, data: { productVariant } }) => {
  dataLayer.push({ ecommerce: null });
  dataLayer.push({
    event: "view_item",
    event_id: id,
    ecommerce: {
      currency: productVariant.price.currencyCode,
      value: productVariant.price.amount,
      items: [mapVariant(productVariant, 0)],
    },
  });
});

Shopify Settings Meta

!(function (f, b, e, v, n, t, s) {
	if (f.fbq) return;
	n = f.fbq = function () {
		n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);
	};
	if (!f._fbq) f._fbq = n;
	n.push = n;
	n.loaded = !0;
	n.version = "2.0";
	n.queue = [];
	t = b.createElement(e);
	t.async = !0;
	t.src = v;
	s = b.getElementsByTagName(e)[0];
	s.parentNode.insertBefore(t, s);
})(
	window,
	document,
	"script",
	"https://connect.facebook.net/en_US/fbevents.js",
);
fbq("init", "META_FIXEL_ID");

analytics.subscribe("page_viewed", ({ id }) => {
	fbq("track", "PageView", {}, { eventID: id });
});

analytics.subscribe("cart_viewed", ({ id, data: { cart } }) => {
	fbq(
		"track",
		"ViewContent",
		{
			content_ids: cart.lines.map((line) => line.merchandise.product.id),
			content_category: "cart",
			content_name: "cart",
			content_type: "product",
			contents: cart.lines.map((line) => ({
				id: line.merchandise.product.id,
				quantity: line.quantity,
			})),
			currency: cart.cost.totalAmount.currencyCode,
			value: cart.cost.totalAmount.amount,
		},
		{ eventID: id },
	);
});

analytics.subscribe("checkout_completed", ({ id, data: { checkout } }) => {
	fbq(
		"track",
		"Purchase",
		{
			content_ids: checkout.lineItems.map((line) => line.variant.product.id),
			content_type: "product",
			contents: checkout.lineItems.map((line) => ({
				id: line.variant.product.id,
				quantity: line.quantity,
			})),
			currency: checkout.currencyCode,
			num_items: checkout.lineItems.reduce(
				(sum, line) => sum + line.quantity,
				0,
			),
			value: checkout.subtotalPrice.amount,
		},
		{ eventID: id },
	);
});

analytics.subscribe("checkout_started", ({ id, data: { checkout } }) => {
	fbq(
		"track",
		"InitiateCheckout",
		{
			content_ids: checkout.lineItems.map((line) => line.variant.product.id),
			contents: checkout.lineItems.map((line) => ({
				id: line.variant.product.id,
				quantity: line.quantity,
			})),
			currency: checkout.currencyCode,
			num_items: checkout.lineItems.reduce(
				(sum, line) => sum + line.quantity,
				0,
			),
			value: checkout.subtotalPrice.amount,
		},
		{ eventID: id },
	);
});

analytics.subscribe("collection_viewed", ({ id, data: { collection } }) => {
	fbq(
		"track",
		"ViewContent",
		{
			content_ids: [collection.id],
			content_name: collection.title,
			content_type: "product_group",
			contents: collection.productVariants.map((variant) => ({
				id: variant.product.id,
				quantity: 1,
			})),
		},
		{ eventID: id },
	);
});

analytics.subscribe("product_added_to_cart", ({ id, data: { cartLine } }) => {
	fbq(
		"track",
		"AddToCart",
		{
			content_ids: [cartLine.merchandise.product.id],
			content_name: cartLine.merchandise.product.title,
			content_type: "product",
			contents: [
				{ id: cartLine.merchandise.product.id, quantity: cartLine.quantity },
			],
			currency: cartLine.cost.totalAmount.currencyCode,
			value: cartLine.cost.totalAmount.amount,
		},
		{ eventID: id },
	);
});

analytics.subscribe("product_viewed", ({ id, data: { productVariant } }) => {
	fbq(
		"track",
		"ViewContent",
		{
			content_ids: [productVariant.product.id],
			content_name: productVariant.product.title,
			content_type: "product",
			contents: [{ id: productVariant.product.id, quantity: 1 }],
			currency: productVariant.price.currencyCode,
			value: productVariant.price.amount,
		},
		{ eventID: id },
	);
});