How to Track Checkout Events with checkout.liquid with the Shopify Source
Overview
Prerequisites:
- You have completed the upgrade process to the new Shopify Source.
- Shopify Plus store with checkout.liquid active
- You are not using Checkout Extensibility
How to Track Checkout Events with checkout.liquid with the Shopify Source
Create Snippet in Shopify Theme:
- Begin on your Shopify homepage and use the left-hand menu to click on the "Online Store" tab. An additional drop-down menu will appear, locate and click on the "Themes" tab.
- Locate your current theme and click on the three dots. An additional drop-down menu will appear, click on the "Edit code" tab.
- Once in your Shopify theme code, locate the "Snippets" tab and click on the "+ Add a new snippet" button.
- (See Figure 1)
_Figure 1_
- You will brought to a pop-up window titled "Add a new snippet" and click on the text box titled "File name".
- Name the new snippet elevar-checkout-script.
- (See Figure 2)
_Figure 2_
Add 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 will need to modify the code you've pasted into your new snippet to reference your personalized configuration script.
- To do this you will 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
- (See Figure 3)
_Figure 3_
- Return to your snippet in your Shopify theme and replace the same line with this line that has your personalized URL.
- (See Figure 4)
_Figure 4_
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.- (See Figure 5)
- After making the desired changes, be sure to click on the "Save" button in the upper right-hand corner of the page.
_Figure 5_
Review 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.
- (See Figure 6)
_Figure 6_
It is recommended to user server-side checkout events and combined web and server-side checkout events where available.
Updated 3 months ago