Reputation: 419
I have set up google tag manager with my GA4 property
(NOT legacy Universal Analytics)
according to the official guide:
https://support.google.com/tagmanager/answer/6103696?hl=en&ref_topic=3441530#zippy=%2Cweb-pages
and I have figured out how to send custom/recommended events to GA4 using
dataLayer.push({}) objects, using their "event" field in triggers and tags,
based on a Universal Analytics guide
(https://www.analyticsmania.com/post/track-logins-with-google-tag-manager/),
because this appears to be a black hole in the official guide:
https://support.google.com/tagmanager/answer/9442095
only describes, briefly, the GTM-side of the story.
Same goes for sending User ID: the docs only tell
when creating a Google Analytics 4 Configuration tag:
To set a user ID, add a row to Fields to Set.
Set the Field Name to user_id, and the Value to
a Tag Manager Variable that returns the user ID.
and I only take the knowledge from the external UA guides
to use a Data Layer Variable that reads the user_id field from the dataLayer,
and also create a corresponding user_id User Property on Google Analytics,
which in Universal Analytics used to
have related settings that don't exist anymore
(https://www.analyticsmania.com/post/google-analytics-user-id-with-google-tag-manager/).
So I have deployed my GA4 Events with the user_id
data layer variable
referenced in their Configuration (and it is visible on the datalayer in Debug View),
created the corresponding User Property in GA, and enabled User-ID reporting.
Yet, in my real-time view, the user_id
fields always get some weird "gtm.js" value
(as if my data layer variable value was replaced by the event name
from the default dataLayer.push({event:"gtm.js",user_id:"ignored value")).
What in the world is missing for my user_id field to be recognised?
Thanks!
Upvotes: 8
Views: 13092
Reputation: 5367
That is not maybe the best option as it's not entirely following google guidelines, but it works perfectly.
So, in your initializing script we can setting our user id first, and only then calling the gtm.start
/ gtm.js
events :
setGTMDataLayer() {
const { dataLayer } = window;
if (!dataLayer) window.dataLayer = [];
if (this.props.user) {
window.dataLayer.push({
userId: this.props.user.userid,
event: 'setUserId',
});
}
const gtmScript = (w, d, s, l, i) => {
w[l] = w[l] || []; w[l].push({
'gtm.start':
new Date().getTime(),
event: 'gtm.js',
}); const 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);
};
gtmScript(window, document, 'script', 'dataLayer', 'GTM-XXXXXX');
}
At the end of that script, in case we are using react we can call
this.setState({ renderGTM: true });
Then, and only after the setGTMDataLayer
function was exectued, we need to render the iframe. so using the created state, all needed to do is :
renderGTM = () => this.state.renderGTM && <noscript>
<iframe title="gtm" src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXX"
height="0" width="0" style={{ display: 'none', visibility: 'hidden' }} />
</noscript>
Upvotes: 0
Reputation: 368
Option 1
Addition to above mentioned Configuration Tag. For Single Page Apps I used to fire an additional GA4 Config Tag with automated Page View tracking disabled whenever the user properties change.
Very important!!!! This approach is only working if you switch of a setting in you GA4 Stream configuration labeled:
Ignore duplicate instances of on-page configuration (recommended)
That is hard to find under:
Admin
Because you fire the configuration tab multiple times that has to be disabled.
Read the warning of the toggle though, it has some Caveats, but so far have not encountered real problems yet.
Option 2
It seems to work to set also the user_id
under User Properties although it is marked as reserved property name in the GA4 Docs.
In my case the website happly send a set_user_properties
event, so I could utilize this.
That approach will of course create a new event that doesn't have much business value than setting the props.
Other event based approaches: Set user properties on every event you fire (hard to maintain) or just set them on the frequent page_view event (in which case you need to disable automatic page view tracking).
Upvotes: 0
Reputation: 101
Thanks @bpstrngr! Was going around in circles for a while before finding your answer.
To clarify the step by step in case anyone else bumps into this;
dataLayer
add an event name:window.dataLayer.push({
'userId' : '{{ myUserId }}',
'event': 'userIdSet',
})
In GTM, create a Custom Event
trigger that listens to that event (set event name equal to whatever event you wrote in step 1):
Upvotes: 8
Reputation: 419
So at long last it turned out, that since the configuration tag was fired by the Page View event, that happened before I pushed the user_id to the dataLayer, so it filled the non-existing value with the event name instead.
I gave the user_id event a name to create a custom event trigger, that re-triggers the configuration tag. This way the user_id-s are finally visible.
Upvotes: 3