GA4 purchase event not being fired during checkout

Hey guys, I have an issue with multiple of the stores I manage. Essentially, the purchase event stopped firing since 15th of July.

I have tried the following things:

  • standard Google & YouTube app for tracking

  • adding GTM script to track conversions

  • adding gtag() to the checkout pixel to track the purchase event

But none of those methods allow me to see the purchase inside of GA4.

All the other events are reported just fine, see the screenshot below.

I tried running it with GTM debugger and GA4 debug view but to no luck, I am still only able to see scripts fired after the checkout is done.

I have tried a script by feedarmy (https://feedarmy.com/kb/adding-adwords-conversion-tracking-to-shopify/) where it should send the data to datalayer and trigger and action within GTM.

However, nothing gets pushed into the datalayer, even though console.log() works just fine with the conversion data.

I also added gtag() snippet into the “checkout_complete” subscription, but again I cannot see it neither in console, in the debug view nor in the analytics.

I can see that the ‘View Checkout - Processing Page’ event is sent which should be the true number of conversions. It is around 50 a day for the past week, while only one or two purchase events are being sent.

Is anyone else facing this issue right now? Is there a fix for this?

Thank you.

Michael

1 Like

This is the code that I am using as a custom pixel at the checkout (redacted credentials and sensitive scopes):

// Code Created By FeedArmy V1.05 (please don't remove the creator)
// Copyright FeedArmy Co., Ltd.

const GOOGLE_TAG_MANAGER_ID = '';
const GOOGLE_MERCHANT_CENTER_ID = '';
const PRODUCT_COUNTRY_CODE = '';

// for the ID_TYPE, if your products look like shopify_US_123456789_123456798 add the word shopify
// if your products are sku's add the value sku -- const ID_TYPE = 'sku';
// if your proudcts use the variant id use the value variant_id -- const ID_TYPE = 'variant_id';
// if your proudcts use the parent id use the value parent_id -- const ID_TYPE = 'parent_id';

const ID_TYPE = 'shopify';

// If you want to capitalize the SKU set CAPITALIZE_SKU to true, if you don't want to change anything set to false
const CAPITALIZE_SKU = false;

// SETTINGS END

// Define dataLayer and the gtag function.
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}

//Initialize GTM tag
(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://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer', GOOGLE_TAG_MANAGER_ID);

//Google Consent Mode v2
gtag('consent', 'update', {
  'ad_storage': 'granted',
  'analytics_storage': 'granted',
  'ad_user_data': 'granted',
  'ad_personalization': 'granted',
});

gtag('config', '');

const createLineItemsData = (lineItems, ID_TYPE, PRODUCT_COUNTRY_CODE, CAPITALIZE_SKU) => {
  return lineItems.map((item) => {
    let itemId;
    if (ID_TYPE === "shopify") {
      itemId = "shopify_" + PRODUCT_COUNTRY_CODE + "_" + item.variant?.product?.id + "_" + item.variant?.id;
    } else if (ID_TYPE === "parent_id") {
      itemId = item.variant?.product?.id;
    } else if (ID_TYPE === "sku") {
      itemId = item.variant?.sku;
      if (CAPITALIZE_SKU) {
        itemId = itemId.toUpperCase();
      }
    } else {
      itemId = item.variant?.id;
    }

    return {
      id: itemId,
      price: item.variant?.price?.amount,
      quantity: item.quantity
    };
  });
};

const calculateTotalDiscount = (lineItems) => {
  let totalDiscount = 0;
  lineItems.forEach(item => {
    item.discountAllocations.forEach(discount => {
      totalDiscount += parseFloat(discount.amount.amount);
    });
  });
  return totalDiscount.toFixed(2); // Convert to string with 2 decimal places
};

analytics.subscribe("checkout_completed", (event) => {
  console.log("checkout_completed, sending data")
  const lineItemsData = createLineItemsData(event.data?.checkout?.lineItems, ID_TYPE, PRODUCT_COUNTRY_CODE, CAPITALIZE_SKU);
  const email = event.data?.checkout?.email;
  const phone = event.data?.checkout?.phone;
  const address = event.data?.checkout?.shippingAddress;
  const totalDiscountAmount = calculateTotalDiscount(event.data?.checkout?.lineItems);

  let shopifyPixelData = {
    currency: event.data?.checkout?.subtotalPrice?.currencyCode,
    value: event.data?.checkout?.subtotalPrice?.amount,
    transaction_id: event.data?.checkout?.order?.id,
    shipping: event.data?.checkout?.shippingLine?.price?.amount,
    tax: event.data?.checkout?.totalTax?.amount,
  };

  if (email) {
    shopifyPixelData.email = email;
  }

  if (phone) {
    shopifyPixelData.phone = phone;
  }

  if (address) {
    let addressData = {};
    if (address.firstName) addressData.first_name = address.firstName;
    if (address.lastName) addressData.last_name = address.lastName;
    if (address.address1) addressData.street = address.address1;
    if (address.city) addressData.city = address.city;
    if (address.province) addressData.region = address.province;
    if (address.zip) addressData.postal_code = address.zip;
    if (address.provinceCode) addressData.province_code = address.provinceCode;
    if (address.country) addressData.country = address.country;
    if (address.countryCode) addressData.country_code = address.countryCode;

    if (Object.keys(addressData).length > 0) {
      shopifyPixelData.address = addressData;
    }
  }
    
  shopifyPixelData.aw_merchant_id = GOOGLE_MERCHANT_CENTER_ID;
  shopifyPixelData.aw_feed_country = address.countryCode;
  shopifyPixelData.discount = totalDiscountAmount;
  shopifyPixelData.items = lineItemsData;

    gtag('event', 'purchase', {
    transaction_id: event.data?.checkout?.order?.id,
    value: event.data?.checkout?.subtotalPrice?.amount,
    tax: event.data?.checkout?.tax?.amount,
    shipping: event.data?.checkout?.shipping?.amount,
    currency: event.data?.checkout?.subtotalPrice?.currencyCode,
    coupon: event.data?.checkout?.appliedCoupon?.code,
    items: event.data?.checkout?.lineItems?.map((item, index) => ({
      item_id: item.id,
      item_name: item.name,
      coupon: item.appliedCoupon?.code,
      discount: item.discountedAmount?.amount,
      index: index,
      item_brand: item.brand,
      item_category: item.category,
      item_category2: item.subcategory,
      item_category3: item.subcategory3,
      item_category4: item.subcategory4,
      item_category5: item.subcategory5,
      item_list_id: 'related_products',
      item_list_name: 'Related Products',
      item_variant: item.variant,
      location_id: item.locationId,
      price: item.price.amount,
      quantity: item.quantity
    }))
  });

  dataLayer.push({ shopify_pixel_data: null });
  dataLayer.push({
    event: "feedarmy_purchase",
    url: event.context.document.location.href,
    shopify_pixel_data: shopifyPixelData
  });
});

Hello Mmdigital,

Your implemented datalayer is not working properly.

I did set up conversion tracking for shopify on so many website and it worked perfectly.

please check out the attachment with the datalayer I used to track the purchase.

Hi Sam, I do not seem to be able to find the attached script. Perhaps you forgot to attach it? Thank you for replying to the thread

oh i see. can you do it by yourself? because it is technical set up.

Yes, I am hoping that you can share your script with me (and others facing the issue). Thank you

1 Like

const event_prefix = ‘’;
const formattedItemId = true;
const GTM_container_url = ‘https://www.googletagmanager.com’;
const GTM_container_id = ‘GTM-00000’;

let storeCountryCode = window.localStorage.getItem(‘shopCountryCode’);
storeCountryCode = storeCountryCode || ‘US’;
window.dataLayer = window.dataLayer || ;
function gtag() {
dataLayer.push(arguments);
}

if(/.+/checkouts?/.*/.test(window.location.href)) {
// tag manager
(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=GTM_container_url + ‘/gtm.js?id=’ + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, ‘script’, ‘dataLayer’, GTM_container_id);

analytics.subscribe(‘page_viewed’, (event) => {
window.dataLayer.push({
event: event_prefix + ‘page_view’,
page_location: event.context.document.location.href,
});
});
// end tag manger

// DataLayer Events
analytics.subscribe(‘payment_info_submitted’, (event) => ecommerceDataLayer(‘add_payment_info’, event));

analytics.subscribe(‘checkout_shipping_info_submitted’, (event) => ecommerceDataLayer(‘add_shipping_info’, event));

analytics.subscribe(‘checkout_completed’, (event) => ecommerceDataLayer(‘purchase’, event));

}

async function sha256Hash(value) {
const encoder = new TextEncoder();
const data = encoder.encode(value);

const hashBuffer = await crypto.subtle.digest(‘SHA-256’, data);

const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashedValue = hashArray.map(byte => (‘00’ + byte.toString(16)).slice(-2)).join(‘’);
return hashedValue;
}

async function ecommerceDataLayer(gtm_event_name, event) {
let hash_email;
let hash_phone;
const phone = event.data?.checkout?.phone;
const email = event.data?.checkout?.email;

if (phone) {
hash_phone = await sha256Hash(phone);
}

if (email) {
hash_email = await sha256Hash(email);
}

const customerInfo = {
customer: {
first_name: event.data?.checkout?.billingAddress?.firstName || event.data?.checkout?.shippingAddress?.firstName,
last_name: event.data?.checkout?.billingAddress?.lastName || event.data?.checkout?.shippingAddress?.lastName,
email: email,
hash_email: hash_email,
phone: phone,
hash_phone: hash_phone,
address: event.data?.checkout?.shippingAddress
}
}
dataLayer.push(customerInfo);

const dataLayerInfo = {
event: event_prefix + gtm_event_name,
ecommerce: {
transaction_id: event.data?.checkout?.order?.id,
value: event.data?.checkout?.totalPrice?.amount,
tax: event.data?.checkout?.totalTax?.amount,
shipping: event.data?.checkout?.shippingLine?.price?.amount,
currency: event.data?.checkout?.currencyCode,
coupon: (event.data?.checkout?.discountApplications || ).map(discount => discount.title).join(‘,’),
items: (event.data?.checkout?.lineItems || ).map(item => ({
item_id: formattedItemId ? ‘shopify_’ + storeCountryCode + ‘’ + (item.variant?.product?.id || ‘’) + '’ + (item.variant?.id || ‘’) : item.variant?.product?.id,
product_id: item.variant?.product?.id,
variant_id: item.variant?.id,
sku: item.variant?.sku,
item_name: item.title,
coupon: item.discountAllocations?.discountApplication?.title,
discount: item.discountAllocations?.amount?.amount,
item_variant: item.variant?.title,
price: item.variant?.price?.amount,
quantity: item.quantity,
item_brand: item.variant?.product?.vendor,
item_category: item.variant?.product?.type

}))
}
}

dataLayer.push({
ecommerce: null
});
dataLayer.push(dataLayerInfo);

const css1 = ‘background: red; color: #fff; font-size: normal; border-radius: 3px 0 0 3px; padding: 3px 4px;’;
const css2 = ‘background-color: blue; color: #fff; font-size: normal; border-radius: 0 3px 3px 0; padding: 3px 4px;’;

console.log(
‘%cGTM DataLayer Event:%c’ + event_prefix + gtm_event_name, css1, css2, Object.assign({}, dataLayerInfo, customerInfo)
);
}

let me know if it works perfectly. i have used this for numerous Shopify website and worked perfectly.

Hi @mmDigital Thank you for reaching out regarding the issue with purchase event tracking in GA4. Here are some solutions and troubleshooting steps that might help resolve the issue:

Solution 1: Verify Data Layer Implementation

Ensure that the data layer is correctly implemented and that the purchase event is being pushed to the data layer.

Check Data Layer Push:

window.dataLayer.push({ event: ‘purchase’, ecommerce: { transaction_id: ‘12345’, value: 23.07, currency: ‘USD’, items: [ { item_name: ‘T-shirt’, item_id: ‘12345’, price: 14.99, quantity: 1 } ] } });
Debug Data Layer Push: Use the browser’s console to verify that the purchase event is being pushed correctly.

console.log(window.dataLayer);

Solution 2: Review GTM Tags and Triggers

Ensure that the GTM tags and triggers are set up correctly to capture the purchase event.

  • Navigate to GTM and ensure the tag for the purchase event is configured correctly.
  • Ensure that the tag fires on the correct trigger (e.g., Order Confirmation Page).
  • Verify that the trigger conditions are accurately set to fire on the purchase event.

Solution 3: Debug GA4 Configuration

Use the GA4 DebugView to troubleshoot and ensure that the events are being sent correctly.

  • Enable debug mode in GA4 to see real-time event tracking.
  • Navigate to DebugView in GA4 and confirm that the purchase event is being tracked.

Solution 4: Use GA4 Event Tag in GTM

Set up a GA4 event tag in GTM specifically for the purchase event.

  • Tag Type: GA4 Event
  • Event Name: purchase
  • Event Parameters: Include necessary parameters (e.g., transaction_id, value, currency, items).
  • Configure the trigger to fire on the order confirmation or purchase completion page.

Solution 5: Review Custom Scripts

Ensure that any custom scripts are correctly implemented and do not interfere with the standard tracking.

  • Review and validate custom scripts, including those from Feedarmy.
  • Test the custom scripts independently to ensure they work correctly.

Additional Recommendations

  • Refer to the GA4 and GTM documentation for best practices on event tracking.
  • Contact Google support for additional assistance if the issue persists.

By following these steps, you should be able to identify and resolve the issue with the purchase event not firing correctly in GA4. If you need further assistance, please let us know.

Best regards,

Ina

Hey Sam, thank you for sharing the code. I tried your approach and I am getting the console logs with the purchase event but it does not seem to propagate into the Data layer. When you run that code on your stores, do you get the event into the data layer?

Hi Ina, I can see that the data is not being pushed to datalayer. I tried with the following code:

window.dataLayer = window.dataLayer || [];
function gtag() {
	dataLayer.push(arguments);
}

analytics.subscribe("checkout_completed", (event) => {
  window.dataLayer.push({ event: 'purchase', ecommerce: { transaction_id: '12345', value: 23.07, currency: 'USD', items: [ { item_name: 'T-shirt', item_id: '12345', price: 14.99, quantity: 1 } ] } });

})

But once I inspect the datalayer, nothing gets pushed there.

One thing that concerns me is that when using a test store, I can see the purchase being sent to analytics, without any extra code - only the Google & YouTube app.

But when I try this on the live store, nothing gets sent to Analytics during the checkout.

How is it possible that two stores with identical setup report differently? ?

from console you can see the datalayer and create datalayer variable from there.

Hey Sam, yes the issue though is that on the checkout page, I do not get any dataLayer. Even when I try to initialize it from the code, window.dataLayer is undefined . Nothing gets pushed there.

you did not configured the datalayer properly. i did many times never faced any issue.

Update with a working solution

It turns out that the issue was not in the scripts, but rather in the fact that Shopify deprecated the checkout scripts and with them, the Thank You page and Order summary pages.

For this reason, the page where the Pixel would run was not being rendered properly.

The solution was to simply publish the Thank You and Order status pages. This solved the issue and now the proposed solutions from feedarmy, Sam and others work fine.

Also, the native Google & YouTube app tracking is working as expected.

Also the gtag() and dataLayer solution is working now.

Hello,

I am also experiencing the same. Here’s a screenshot of my GTM Data Layer. Only the purchase event is I am not able to track because I can’t put tracking in the checkout url.

I know how to create a Data Layer Push but the thing is I can’t see tracking when the url switch to checkout. But I am able to see view_item until begin_checkout but upon purchase which fires in checkout with thank-you in url, I can’t get tracking on it. Please see screenshot.

How can we solve that one? Thanks

Hello sbbmaster,

Thanks for sharing the details.

since the additional script is deprecated you can not preview the purchase event in the GTM.

you have to track the purchase through the customer event custom pixel.

and custom pixel works in the sandbox environment.

If you have the datalayer go to the console then select Lax from top then test purchase.

though you are unable to see the purchase event in the GTM still you can track the purchase event from GTM with all kinds of event parameters and customer information for enhanced e-commerce tracking.

I hope my explanation makes sense

Feel free to reach or ask me any questions you may have about conversion tracking with Google Tag Manager.

Thanks

We do have a custom pixel from this website. We copied the “checkout-webpixel.js” into custom pixel. Is that correct?

What I don’t know is how can I check in Console? I tried to purchase and check console but I don’t see a purchase event. how do I show it and see?

When we check GA4 Reports, the Purchase Journey has numbers in purchase column, but in Ecommerce purchases and Checkout Journey, purchase is not populated even the revenue part.

Can you give me a guide on that one to better trace it? Looks like I am doing it wrong. Thanks

hey sbbmaster,

I have successful track record on purchase tracking for Shopify.

If you’d like to discuss this more, don’t hesitate to send me a PM."

Thanks

Have you solved your issue?

If not, one thing to check is wether you are getting this data into GA4 in real time using the Debug View in GA4[https://support.google.com/analytics/answer/7201382?hl=en]

However, if you have the official Google & YouTube app installed on your store, you should also see these events in the data layer.

One thing to note is my solution above, that is make sure that you have the new checkout experience enabled - if you were using custom scripts before, your page is not published yet and therefore cannot be tracked.

There are usually 4 methods to track events in the web:

  1. GA4 Debug View, if you are concerned about data flows

  2. DataLayer if you are trying to see if GTM is working

  3. GTM Debugger to see if your GTM tags are firing properly

  4. Network events in Chrome Developer Tools to see what data is being sent from the website