I want to track custom events in GA4 via GTM. I have setup a GA4 custom event tags which works fine. See screenshot below for example, it’s not 100% correct to be working as described here but it’s just for illustration. I was able to confirm my custom events triggered in GTM via the dataLayer.push()
are passed to GA4.
Here’s how I push the event data to the dataLayer:
dataLayer.push({
"event": "GA4Event",
"ga4EventName": "view_item_list",
"ga4EventParameters": {
"item_list_name":"Homepage",
"items":[{
"item_id":"8888888",
"item_name":"A product",
"item_brand":"a brand",
"price":220.4892,
"currency":"USD",
"index":0
}]
}
});
My gripe with this is that I need to list all event parameters (attributes from the ga4EventParameters
object) one by one in the GA4 event tag configuration. See section circled in red in the screenshot. I honestly don’t want to do this. It is tedious (we have multiple custom events with their own attributes), and will break as soon as we introduce a new attribute and we don’t put it in that list.
I’ve created my own tag template to make it so that the entire ga4EventParameters
object gets passed to GA4 without having to list all of its attributes. It works some of the time, but not all the time, which is where I need help.
Here’s the template code (short version, removed init. code and imports):
const gtag = copyFromWindow('gtag');
// The GA4 tag id
const measurementId = data.measurementId;
if (measurementId) {
const ga4EventName = copyFromDataLayer('ga4EventName');
if (ga4EventName) {
let ga4EventParameters = copyFromDataLayer('ga4EventParameters');
if (!ga4EventParameters) {
ga4EventParameters = {};
}
// Set the GA4 property id to send the custom event to
ga4EventParameters.send_to = measurementId;
log('GA4 event data:', ga4EventName, ga4EventParameters, gtag);
if (gtag) {
gtag('event', ga4EventName, ga4EventParameters);
log('gtag called');
} else {
log('gtag not avail.');
}
}
} else {
log('Tag is missing at least one of its configuration parameters');
}
My issue is with gtag
, it’s only present in window
once all the GTM events have occurred:
- If I run a
dataLayer.push()
with my custom event once the page is entirely loaded and GTM has completely run (like after 3-4seconds), it works completely fine, everything’s great. - However, I have
dataLayer.push()
in the HTML of my page. This means it gets executed early. My custom GTM tag gets triggered by it, butgtag
doesn’t exist inwindow
yet, so I can’t send the event to GA4.
I tried triggering my custom tag template on the Window Loaded
event that GTM has, but same thing, gtag
isn’t available yet.
I’m at a loss, I don’t know how to solve this. Sure I could just use setTimeout
to delay my dataLayer.push()
call on the page but it would be unreliable as that delay would vary depending on device, network speed and script execution speed.
On a side note, I have no idea what script exposes gtag
to window
, and no idea why it gets set so late.