Customer Events DataLayer issue

Topic summary

Issue: GA4 dataLayer product title (item_name/product_title) is undefined on product_added_to_cart (and product_viewed) when using Shopify Customer Events (analytics.subscribe API).

What was tried:

  • Adjusted path from merchandise.product.title to merchandise.title; no change.
  • Shared a full working example (Dawn theme, no third‑party apps) showing item_name from merchandise.product.title, suggesting the mapping itself is valid.

Key findings/diagnosis:

  • Likely cause is theme/app code or the add-to-cart fetch implementation altering the Customer Events payload.
  • Different fetch approaches (Shopify AJAX cart add) return different responses. Using a custom/default fetch may omit product context, especially when multiple items are added, so the event can’t resolve a single product title.

Working approach reported:

  • Align with Dawn or Shopify docs. Using the documented request structure produced correct data and even triggered two add_to_cart events when adding two items, confirming payload integrity.

Actions/next steps:

  • Review product-form.js fetch; match Dawn/FormData or Shopify AJAX spec.
  • Test without third‑party scripts/apps.
  • Console-log event payloads to verify merchandise/product fields.

Status: Unresolved for OP, but evidence points to fetch implementation as the root cause. Code snippets are central to understanding.

Summarized with AI on December 26. AI used: gpt-5.

Hello everyone,

I have been trying to get product_title value in GA4 datalayer in customer event when product added to cart. But It shows undefined every time https://d.pr/i/BK23ro. This is the code I have added https://d.pr/i/zUPOA1.

analytics.subscribe("product_added_to_cart", (event) => {
  console.log('custom event', event)
  var cartItems = parseItems(event)
  window.dataLayer.push({
    'event': "add_to_cart",
    'currency': event.data.cartLine.merchandise.price.currencyCode,
    'price': event.data?.cartLine?.merchandise?.price?.amount,
    'product_id': event.data.cartLine.merchandise.product.id,
    'product_title': event.data.cartLine.merchandise.product.title,
    'quantity': event.data.cartLine.quantity,
    'lineItems': cartItems,
    'value': event.data?.cartLine?.cost?.totalAmount?.amount,
    'fired_from': 'custom_pixel'
  });
});

Is there anyone who facing the same issue

Hi @Kintesh
Can you update the title code

FROM:

'product_title': event.data.cartLine.merchandise.product.title,

TO:

'product_title': event.data.cartLine.merchandise.title,

No, I have updated https://d.pr/i/Ji7Wpt and checked the datalayer. But it doesn’t help https://d.pr/i/qx37cu

Hi @Kintesh
Here is the complete code which I have checked on my test store and it is working fine

const script = document.createElement("script");
script.setAttribute("src", "https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX");
script.setAttribute("async", "");
document.head.appendChild(script);

window.dataLayer = window.dataLayer || [];
function gtag() {
  dataLayer.push(arguments);
}
gtag("js", new Date());
gtag("config", "G-XXXXXXXXXX");

const Custom_layer = {
  getItemsFromLineItems(lineItems) {
    let items = []
    for (const item of lineItems) {
      items.push({
        item_id: item.variant.product.id,
        item_name: item.variant.product.title,
      })
    }

    return items
  },

  getPageViewData(evt) {
    let ctx = evt.context
    return {
      page_location: ctx.document.location.href,
      page_title: ctx.document.title,
      language: ctx.language,
    }
  },

  getViewItemData(evt) {
    return {
      currency: evt.data.productVariant.price.currencyCode,
      value: evt.data.productVariant.price.amount,
      items: [{ item_id: evt.data.productVariant.id, item_name: evt.data.productVariant.product.title }],
    }
  },

  getAddToCartData(evt) {
    return {
      currency: evt.data.cartLine.merchandise.price.currencyCode,
      value: evt.data.cartLine.merchandise.price.amount,
      items: [{ item_id: evt.data.cartLine.merchandise.id, item_name: evt.data.cartLine.merchandise.product.title }],
    }
  },

  getPaymentInfoData(evt) {
    return {
      currency: evt.data.checkout.currencyCode,
      value: evt.data.checkout.totalPrice.amount,
      items: this.getItemsFromLineItems(evt.data.checkout.lineItems),
    }
  },

  getCheckoutData(evt) {
    return {
      currency: evt.data.checkout.currencyCode,
      value: evt.data.checkout.totalPrice.amount,
      items: this.getItemsFromLineItems(evt.data.checkout.lineItems),
    }
  },

  getCheckoutCompletData(evt) {
    return {
      transaction_id: evt.data.checkout.order.id,
      currency: evt.data.checkout.currencyCode,
      value: evt.data.checkout.totalPrice.amount,
      items: this.getItemsFromLineItems(evt.data.checkout.lineItems),
    }
  }
}

analytics.subscribe("page_viewed", async (event) => {
  gtag("event", "page_view", Custom_layer.getPageViewData(event));
});

analytics.subscribe("product_viewed", async (event) => {
  gtag("event", "view_item", Custom_layer.getViewItemData(event));
});

analytics.subscribe("search_submitted", async (event) => {
  gtag("event", "search", {
    search_term: event.data.searchResult.query,
  });
});

analytics.subscribe("product_added_to_cart", async (event) => {
console.log(Custom_layer.getAddToCartData(event));
  gtag("event", "add_to_cart", Custom_layer.getAddToCartData(event));
});

analytics.subscribe("payment_info_submitted", async (event) => {
  gtag("event", "add_payment_info", Custom_layer.getPaymentInfoData(event));
});

analytics.subscribe("checkout_started", async (event) => {
  gtag("event", "begin_checkout", Custom_layer.getCheckoutData(event) );
});

analytics.subscribe("checkout_completed", async (event) => {
  gtag("event", "purchase", Custom_layer.getCheckoutCompletData(event));
});

Hi kintesh,

I have a readymade datalayer for Shopify for all e-commerce event with GA4 schema. if you need you can PM me.

Thanks

Hi @Huptech-Web ,

Thanks for sharing code! I have added in my test store and checked, It still item name/product title undefined https://d.pr/i/IbU6td.

Hi @Sam_Mahmud ,

I already have implemented complete GA4 events. The only thing is item name/product_title is undefined while product_viewed or product_added _to_cart.

Thank you.

I have 2 types of datalayer. Theme dependent and theme Independent.

both types of datalayer push all product data with event. you can take any data via the GTM variable.

hi @Kintesh

Okay got it.

I have checked it in the latest version of dawn theme without any third-party app.

So, May be there are any certain app or script that alters the output.

Because in my test I got complete data with all the details.

1 Like

OK, I will check.

Hi there,

Any update on this? I’m facing the same issue at the moment, but only with a specific client.

Hi @Kintesh ,

How does your fetch looks like in the product-form.js (or other file where you fetch the add to cart url)?

I have taken a look at the dawn theme and tried their code. That actually worked. After this I was checking what the difference was between our script and their script. Check the documentation here.

The only difference for now I could find was the way we fetch the data. We use the default setup (first option in the docs), and the dawn theme uses the FormData constructor to fetch the data (alternative solution).

Both return a different response, and that is the point where I think it’s going wrong. And that actually makes sense as well. If you add multiple items, the event doesn’t know what product has been added, because it can be multiple.

I hope this makes sense and you could find a solution yourself. I’m also already in contact with the Shopify Plus Support and updated them about this as well.


Update

The code below is actually working. It even fires 2 added to cart events. So most likely there is something wrong in my (and your) fetch.

// Save form data
const formData = new FormData(this.form);

fetch(window.Shopify.routes.root + 'cart/add.js', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    items: [
      {
        id: variantID,
        quantity: 1,
      },
      {
        id: anotherVariantID,
        quantity: 1,
      },
    ],
  }),
})
  .then((response) => {
    return response.json();
  })
  .then((data) => {
    console.log('Success:', data);
  })
  .catch((error) => {
    console.error('Error:', error);
  });
2 Likes