Skip to content

Update GTM example with real events #2699

Open
@benjaminsehl

Description

Here's a basic version I made — looks like some of the payloads are incomplete, for example currency for a product should be available, but isn't. The items inside a collection payload, and the collection title, aren't available — and so I just skipped that event.

Event details required here: https://developers.google.com/analytics/devguides/collection/ga4/reference/events?client_type=gtm#add_to_cart

import {
  type CartUpdatePayload,
  type CartViewPayload,
  type PageViewPayload,
  type ProductViewPayload,
  type SearchViewPayload,
  useAnalytics,
} from '@shopify/hydrogen';
import {useEffect} from 'react';

declare global {
  interface Window {
    dataLayer: any[];
  }
}

export function GoogleTagManager() {
  const {subscribe, register} = useAnalytics();
  const {ready} = register('Google Tag Manager');

  const getCookie = (name: string) => {
    const value = `; ${document.cookie}`;
    const parts = value.split(`; ${name}=`);
    if (parts.length === 2) return parts.pop()?.split(';').shift();
    return null;
  };
  const gaClientId = getCookie('_ga')?.split('.').slice(-2).join('.');

  useEffect(() => {
    // Page View
    subscribe('page_viewed', (data: PageViewPayload) => {
      window.dataLayer.push({
        event: 'page_view',
        page_location: data.url,
        page_title: document.title,
        client_id: gaClientId,
      });
    });

    // Product View
    subscribe('product_viewed', (data: ProductViewPayload) => {
      window.dataLayer.push({
        event: 'view_item',
        ecommerce: {
          currency: data.shop?.currency || 'USD',
          value: Number(data.products[0]?.price) || 0,
          items: [
            {
              item_id: data.products[0]?.id,
              item_name: data.products[0]?.title,
              price: Number(data.products[0]?.price) || 0,
              item_variant: data.products[0]?.variantTitle,
              item_brand: data.products[0]?.vendor,
            },
          ],
        },
      });
    });
    // CART VIEW
    subscribe('cart_viewed', (data: CartViewPayload) => {
      window.dataLayer.push({
        event: 'view_cart',
        ecommerce: {
          currency: data.cart?.cost?.totalAmount?.currencyCode || 'USD',
          value: Number(data.cart?.cost?.totalAmount?.amount) || 0,
          items: data.cart?.lines.nodes.map((line) => ({
            item_id: line.merchandise.id,
            item_name: line.merchandise.product.title,
            price: Number(line.cost.amountPerQuantity.amount),
            quantity: line.quantity,
            item_variant: line.merchandise.title,
          })),
        },
      });
    });

    // Search
    subscribe('search_viewed', (data: SearchViewPayload) => {
      window.dataLayer.push({
        event: 'search',
        search_term: data.searchTerm,
        client_id: gaClientId,
      });
    });

    // Add to Cart
    subscribe('product_added_to_cart', (data: CartUpdatePayload) => {
      const newItems = data.cart?.lines.nodes.filter(
        (node) =>
          !data.prevCart?.lines.nodes.some(
            (prevNode) => prevNode.id === node.id,
          ),
      );

      window.dataLayer.push({
        event: 'add_to_cart',
        ecommerce: {
          currency: data.cart?.cost?.totalAmount?.currencyCode || 'USD',
          value: Number(data.cart?.cost?.totalAmount?.amount) || 0,
          items: newItems?.map((item) => ({
            item_id: item.merchandise.id,
            item_name: item.merchandise.product.title,
            price: Number(item.cost.amountPerQuantity.amount),
            quantity: item.quantity,
            item_variant: item.merchandise.title,
          })),
        },
      });
    });

    // Remove from Cart
    subscribe('product_removed_from_cart', (data: CartUpdatePayload) => {
      const removedItems = data.prevCart?.lines.nodes.filter(
        (node) =>
          !data.cart?.lines.nodes.some(
            (currentNode) => currentNode.id === node.id,
          ),
      );

      window.dataLayer.push({
        event: 'remove_from_cart',
        ecommerce: {
          currency: data.cart?.cost?.totalAmount?.currencyCode || 'USD',
          value: Number(data.cart?.cost?.totalAmount?.amount) || 0,
          items: removedItems?.map((item) => ({
            item_id: item.merchandise.id,
            item_name: item.merchandise.product.title,
            price: Number(item.cost.amountPerQuantity.amount),
            quantity: item.quantity,
            item_variant: item.merchandise.title,
          })),
        },
      });
    });

    ready();
  }, [subscribe, register, ready, gaClientId]);

  return null;
}

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions