How to Track Checkout Events with checkout.liquid with the Shopify Source

Prerequisite

Create a snippet in your Shopify theme

Access your theme code and select Add a new snippet

Name the new snippet elevar-checkout-script

Add the base code

Copy and past the code below into the snippet you have created in your theme

<!-- Begin Elevar -->
<script type="module">
  if (Shopify?.Checkout && !Shopify.Checkout.page?.includes("thank_you")) {
  try {
    const config = (await import("/a/elevar/static/configs/.../config.js")).default;
    const scriptUrl = config.script_src_app_theme_embed;

    if (scriptUrl) {
      const { handler } = await import(scriptUrl);

      await handler(
        config,
        
        {
          cartData: {
  attributes: {{- cart.attributes | json -}},
  cartTotal: "{{- cart.total_price | times: 0.01 | json -}}",
  currencyCode: {{- cart.currency.iso_code | json -}},
  items: [
    {%- for line_item in cart.items -%}
      {
        {%- if line_item.sku != blank -%}
          id: {{- line_item.sku | json -}},
        {%- else -%}
          id: "{{- line_item.product_id | json -}}",
        {%- endif -%}
        name: {{- line_item.product.title | json -}},
        brand: {{- line_item.vendor | json -}},
        category: {{- line_item.product.type | json -}},
        variant: {{- line_item.variant.title | json -}},
        price: "{{- line_item.final_price | times: 0.01 | json -}}",
        position: {{- forloop.index -}},
        quantity: "{{- line_item.quantity | json -}}",
        productId: "{{- line_item.product_id | json -}}",
        variantId: "{{- line_item.variant_id -}}",
        compareAtPrice: "{{- line_item.variant.compare_at_price | times: 0.01 | json -}}",
        image: "{{- line_item.image | image_url -}}",
        url: {{- line_item.url | json -}}
      },
    {%- endfor -%}
  ]
}
,
          user: {
  {%- if checkout -%}
    cartTotal: "{{- checkout.total_price | times: 0.01 | json -}}",
    currencyCode: {{- checkout.currency | json -}},
  {%- else -%}
    cartTotal: "{{- cart.total_price | times: 0.01 | json -}}",
    currencyCode: {{- cart.currency.iso_code | json -}},
  {%- endif -%}
  {%- if customer -%}
    customer: {
      id: "{{- customer.id | json -}}",
      email: {{- customer.email | json -}},
      firstName: {{- customer.first_name | json -}},
      lastName: {{- customer.last_name | json -}},
      phone: {{- customer.phone | json -}},
      city: {{- customer.default_address.city | json -}},
      zip: {{- customer.default_address.zip | json -}},
      address1: {{- customer.default_address.address1 | json -}},
      address2: {{- customer.default_address.address2 | json -}},
      country: {{- customer.default_address.country | json -}},
      countryCode: {{- customer.default_address.country_code | json -}},
      province: {{- customer.default_address.province | json -}},
      provinceCode: {{- customer.default_address.province_code | json -}},
      tags: {{- customer.tags | join: ', ' | json -}}
    }
  {%- endif -%}
},
          isOnCartPage: false,
          collectionView: null,
          searchResultsView: null,
          productView: null,
          checkoutComplete: null

        }
        
      );
      const data = {
  currencyCode: {{- checkout.currency | json -}},
  items: [
    {%- for line_item in checkout.line_items -%}
      {
        {%- if line_item.sku != blank -%}
          id: {{- line_item.sku | json -}},
        {%- else -%}
          id: "{{- line_item.product_id | json -}}",
        {%- endif -%}
        name: {{- line_item.product.title | json -}},
        brand: {{- line_item.vendor | json -}},
        category: {{- line_item.product.type | json -}},
        variant: {{- line_item.variant.title | json -}},
        price: "{{- line_item.final_price | times: 0.01 | json -}}",
        quantity: "{{- line_item.quantity | json -}}",
        productId: "{{- line_item.product_id | json -}}",
        variantId: "{{- line_item.variant_id -}}",
        compareAtPrice: "{{- line_item.variant.compare_at_price | times: 0.01 | json -}}",
        image: "{{- line_item.image | image_url -}}"
      },
    {%- endfor -%}
  ]
};

const deriveEventFromValidShopifyCheckoutStep = step => {
  switch (step) {
    case "contact_information":
      return "dl_begin_checkout";
    case "shipping_method":
      return "dl_add_shipping_info";
    case "payment_method":
      return "dl_add_payment_info";
  }
};

const deriveActionFieldStepFromValidShopifyCheckoutStep = step => {
  switch (step) {
    case "contact_information":
      return "1";
    case "shipping_method":
      return "2";
    case "payment_method":
      return "3";
  }
};

const formatPrice = value => {
  return value !== undefined ? Number(value).toFixed(2) : undefined;
};

const deriveCheckoutStepDataLayerItem = args => {
  const eventName = deriveEventFromValidShopifyCheckoutStep(args.step);
  return {
    event: eventName,
    event_id: `${eventName}_${args.token}`,
    ecommerce: {
      currencyCode: args.currencyCode,
      checkout: {
        actionField: {
          step: deriveActionFieldStepFromValidShopifyCheckoutStep(args.step)
        },
        products: args.items.map(item => ({
          id: item.id,
          name: item.name,
          brand: item.brand,
          category: item.category,
          variant: item.variant,
          price: formatPrice(item.price),
          quantity: item.quantity,
          list: item.list,
          product_id: item.productId,
          variant_id: item.variantId,
          image: item.image
        }))
      }
    }
  };
};

const getCart = () => {
  const serializedCart = localStorage.getItem("___ELEVAR_GTM_SUITE--cart");

  if (serializedCart === null) {
    return [];
  } else {
    const dirtyCart = JSON.parse(serializedCart);
    return dirtyCart.map(({ image, ...rest }) => ({
      ...rest,
      image: typeof image === "string" || image === null ? image : image.url
    }));
  }
};

const step = window.Shopify?.Checkout?.step;
const token = window.Shopify?.Checkout?.token;

if (
  (step === "contact_information" ||
    step === "shipping_method" ||
    step === "payment_method") &&
  token
) {
  const cart = getCart();

  window.ElevarDataLayer.push(
    deriveCheckoutStepDataLayerItem({
      token,
      step,
      currencyCode: data.currencyCode,
      items: data.items.map(item => {
        const cartItem = cart.find(
          existingItem => existingItem.variantId === item.variantId
        );
        return { ...item, list: cartItem?.list ?? "" };
      })
    })
  );
}
    }
  } catch (error) {
    console.error("Elevar Error:", error);
  }}
</script>
<!-- End Elevar -->

Update the code

You'll need to modify the code you've pasted into your new snippet to reference your personalized configuration script.

To do this you'll need to retrieve your config URL from your Elevar App within the Shopify Souce.

On the Configure Order Status Page step copy the single line of copy that appears like this const config = (await import("a/elevar/static/configs/.../config.js

Return to your snippet in your Shopify theme and replace the same line with this line that has your personalized URL.

You are now ready to reference this snippet in your checkout.

Reference your new snippet in your checkout.liquid

For the new snippet you've create to run on your checkout pages, you'll need to reference the snippet in your checkout.liquid. Add {% render "elevar-checkout-script" %}in your checkout.liquid directly below the opening <head>element.

It will look like this:

Save your changes.

Review your destinations

This setup is intended to restore missing pageview events in the checkout flow for GA4, however it could cause duplication of the checkout events if you have not updated your GA4 web container when you update to the Shopify source.

We recommend you update GA4 web tags for for best performance.

To update, access your GA4 Destination(s) in the Elevar App. Follow the instructions on the Web Container setup.

It is recommended to user server-side checkout events and combined web and server-side checkout events where available.