Shopify Conversion Tracking And Attribution – How To Set Up
Attribute Shopify purchases to original customer sources to report marketing sources of all purchases, as well as to understand individual customer journeys.
Contents
Track Purchases and other funnel events
Attribute Shopify purchases to original customer sources to report marketing sources of all purchases, as well as to understand individual customer journeys.
Able CDP extends Shopify attribution capabilities by recording the source of each visitor, including a paid click ID if present, as well as any activities such as viewed products. By taking advantage of the newest Shopify Custom Pixel capabilities, Able associates the customer's website journey with both the internal Shopify Client ID, as well as the email and phone number entered by the customer during checkout. This allows for the reliable attribution of future conversions to the original customer source, even if the cookies are missing at the time of purchase, as long as the previous customer checkout or lead form completion was recorded by Able CDP.
Track Purchases and other events
To track Shopify purchases and other events:
-
From your Shopify admin, go to Settings > Customer events.
-
Give your pixel a unique name. If you enter the name of a custom pixel that already exists, then you'll be prompted to give your pixel a different name.
-
Click Add pixel to open the event editor.
-
Optional: In the Customer privacy section, select the Permission and Data sale settings that you want to adjust. Learn more about managing app pixel customer privacy.
-
Paste the code below into the Code window. (Note: %%FUNNEL_MARK%% in the code must be the Able CDP identifier of your Able funnel you'd like to connect Shopify to. You may find the identifier of your funnel on the Get Code page of the Able Dashboard.)
// Array to store remembered events
let rememberedEvents = [];
// Function to get cookies
async function getCookies() {
const gaCookie = await browser.cookie.get('_ga');
const fbp = await browser.cookie.get('_fbp');
const fbclid = await browser.cookie.get('_fbc');
return {
ga_cookie: gaCookie,
fbp: fbp,
fbclid: fbclid
};
}
// Helper function to track events
async function trackEvent(eventName, event, eventData = {}) {
const cookies = await getCookies();
const keys = {
...cookies,
client_id: event.clientId ? `shopify:${event.clientId}` : undefined,
email: event.data?.checkout?.email,
phone: event.data?.checkout?.phone
};
// Remove undefined values
Object.keys(keys).forEach(key => keys[key] === undefined && delete keys[key]);
const trackingData = {
...eventData,
keys: keys,
event_time: event.timestamp,
event_source: event.context.document.location.href,
order_id: event.data?.checkout?.order?.id
};
if (typeof uipe !== 'undefined') {
uipe('init', '%%FUNNEL_MARK%%');
uipe('track', eventName, trackingData);
} else {
rememberedEvents.push({ eventName, trackingData });
}
}
// Script loading and initialization
var el = document.createElement('script');
el.src = 'https://app.ablecdp.com/ue.js';
el.async = true;
// Append the script to the document head
document.head.appendChild(el);
// Use polling to detect when the script has loaded
var checkScriptLoaded = setInterval(function () {
// Check if the `uipe` object or function is defined (indicates script is ready)
if (typeof uipe === 'function') {
clearInterval(checkScriptLoaded); // Stop polling
initializeUIPE(); // Call initialization logic
}
}, 50); // Check every 50ms
// Initialization logic
function initializeUIPE() {
uipe('init', '%%FUNNEL_MARK%%');
// Send any previously remembered events
if (Array.isArray(rememberedEvents)) {
rememberedEvents.forEach(function (event) {
uipe('track', event.eventName, event.trackingData);
});
}
// Clear the remembered events array
rememberedEvents = [];
}
// Event subscriptions
analytics.subscribe("page_viewed", async (event) => {
await trackEvent('PageView', event);
});
analytics.subscribe("product_viewed", async (event) => {
await trackEvent('ViewContent', event, {
deal_items: [{
sku: event.data?.productVariant?.id,
name: event.data?.productVariant?.title,
price: event.data?.productVariant?.price.amount
}],
deal_currency: event.data?.productVariant?.price.currencyCode,
deal_value: event.data?.productVariant?.price.amount
});
});
analytics.subscribe("search_submitted", async (event) => {
await trackEvent('Search', event, {
description: event.searchResult.query
});
});
analytics.subscribe("product_added_to_cart", async (event) => {
await trackEvent('AddToCart', event, {
deal_items: [{
sku: event.data?.cartLine?.merchandise?.productVariant?.id,
name: event.data?.cartLine?.merchandise?.productVariant?.title,
price: event.data?.cartLine?.merchandise?.productVariant?.price.amount
}],
deal_currency: event.data?.cartLine?.merchandise?.productVariant?.price?.currencyCode,
deal_value: event.data?.cartLine?.merchandise?.productVariant?.price.amount
});
});
analytics.subscribe("payment_info_submitted", async (event) => {
await trackEvent('AddPaymentInfo', event);
});
analytics.subscribe("checkout_started", async (event) => {
await trackEvent('InitiateCheckout', event);
});
analytics.subscribe("checkout_completed", async (event) => {
await trackEvent('Purchase', event, {
deal_currency: event.data?.checkout?.currencyCode,
deal_value: event.data?.checkout?.totalPrice?.amount,
deal_items: event.data?.checkout?.lineItems.map(item => ({
sku: item.variant?.id,
name: item.title,
price: item.variant?.price?.amount,
qty: item.quantity
}))
});
});
Next Steps
After Shopify purchases begin to appear in Able CDP under Customers — Purchases tab, set up one or a few of the supported outbound Purchase conversion integrations listed below. If you're currently sending Purchase events to the same service using another integration or tracking code, it's recommended to disable sending Purchase conversions with it and only send Purchase conversions using Able CDP Conversions API integration to prevent duplicates.
If Duplicate Purchase conversions appear in Facebook Ads Manager or duplicate events warning appears in Facebook Events Manager
When Able is used, conversion events that are sent by it to the Facebook Conversions API should not be sent using Facebook Pixel as it'll lead to event duplication.
Able doesn't send deduplication parameters in its Conversions API calls as it'll lead to additional customer tracking data collected by Able CDP and sent to Conversions API to be ignored altogether in favor of the Pixel event. This is done by design on the Facebook end.
To prevent duplicates from appearing, send PageView events to Facebook Pixel from the browser and use Able to send Lead and Purchase events attributed to the original visitor.
Doing this in Shopify requires the following steps:
- Disable Shopify Facebook Data Sharing
- Edit Shopify theme and add Facebook Pixel code using the instructions to Manually add pixel code to website
This should resolve event duplication issues by making sure that each type of event is sent to Facebook Pixel and Conversions API once.