can GA4 custom dimensions be updated after the initial 'config' call?
Asked Answered
S

2

6

I have google analytics 4 being loaded via GTM, and i've been struggling with adding custom dimensions to the "enhanced measurement" events. after reading some other answers i've determined that yes, the dimensions work when set in the 'config' call for the tracking id (which i can do in GTM under "fields to set"), but 'config' seems like it noops on subsequent calls for an already configured tracker with GA4 (with UA it does something).

as discussed in the other questions, 'set' operations don't seem to do anything, and i'm not manually dispatching the "enhanced collection" events so i can't manually specify the parameters in the call.

is there any way to add parameters to "enhanced measurement" events after the tracker is configured?

a minimal example:

gtag('set', {'dimension1': 'test1'})
gtag('config', 'G-XXXXX', {dimension2: 'test2'})
gtag('set', {'dimension3': 'test3'})
gtag('event', 'test', {send_to: 'G-XXXXXX', foobar: 'baz'})

the debugger shows the event parameters: en: test _ee: 1 ep.dimension2: test2 ep.foobar: baz

on a page navigation the automatic enhanced collection event looks like this: en: page_view ep.dimension2: test2 _et: 922

however when using an old GA account:

gtag('config', 'UA-XXXXXX')
gtag('event', 'test', {send_to: 'UA-XXXX', foobar: 'baz'})

it shows all the set dimensions: "dimension1": "test1" "dimension3": "test3" "&jsscut": "1" "hitCallback": [function] "hitType": "event" "eventCategory": "general" "eventAction": "test"

why does the G4 integration not pick up on set dimensions? and is there any way to modify dimensions after the tracker is configured other than including them on the event call

Spinescent answered 4/5, 2023 at 20:44 Comment(3)
How about configuring it again, but asking configure not to send the pageview? Just do a silent reconfig. Though it's odd to me that you can config and yet don't send the EEC event. Does an plug-in send it? No GTM?Jelly
i updated my question with a more minimal example, to answer the first part of your question, calling config again doesn't seem to do anything or affect future events, with or without send_page_view specifiedSpinescent
I'll try to find out if there's a way to update the persisted dimensions, but would you be ok doing it through GTM? Sending the data to GTM (through dataLayer []) and having it setting the dimensions? This is also the best practice since it limits any data setting to GTM, making it way easier to debug. It seems to me a dangerous mess to send events through both gtag() and gtm.Jelly
J
6

Okay, dug the issue up. Google is a bit odd with how they push new stuff related to GA4. Somewhere last August Google rolled out a new feature. To ignore 'duplicate' config calls. And enabled it by default. While the idea of it seems a bit ridiculous, it becomes even more ridiculous when you realise it was a sneak update without notifying us or documenting it.

Anyhow:

  • Go to your GA4 property’s Admin
  • Data Streams
  • (your data stream)
  • Configure Tag Settings
  • Your Google Tag and
  • Click the box on the left for your stream
  • Toggle OFF “Ignore duplicate instances of on-page configuration.”

source

Yes, gtag.js' behavior is configured depending on the config of your GA4 property. There are more things you configure in your library through this ui. One of which would be cross-domain linking rules.

Thanks to Angela Grammatas and Todd Bullivant for helping figuring this out on Measure slack :)

Other than that, it's a bit odd to use both GTM and gtag() in parallel. Will lead to gathering of technical debt. It's much better to migrate all direct gtag() calls to GTM via dataLayer.

Jelly answered 10/5, 2023 at 21:55 Comment(11)
thank you for your comment, i'll look into changing that setting. can you elaborate on: "migrate all direct gtag() calls to GTM via dataLayer"? if i'm installing the tracker using GTM, and i would like to allow my marketing team to use GTM to add additional tags if necessary, but also in application code i'm sending some custom events and setting special dimensions, should i not be calling gtag to do that? are you suggesting i call dataLayer.push directly instead of calling gtag? i'm a little ignorant on the nuances of all thisSpinescent
So, GTM is meant to be a central hub for all analytics things. GTM is meant to be able to control whatever is being set or sent to any analytics endpoint. And GTM is actually exceptionally good at this kind of analytics stuff management. GTM has mechanisms of communicating with the front-end. It's done through the dataLayer. Here, have a read: developers.google.com/tag-platform/tag-manager/web/datalayer It's considered a good practice for all traffic to be in GTM and for GTM to be the only one allowed to call gtag, so frontend shouldn't touch gtag at all, ideally.Jelly
I must say that your organisation might just not want to have a dedicated person governing all tags, so that may be the reason why they leave it for the front-end devs to tackle. Well, they're just being cheap really. And it's not good for data governance and data quality, especially in the long-term. This is analytics tech debt on drugs.Jelly
so if i have an event like "app_initialized" that i currently use to make sure page metadata is loaded. GTM triggers the G4 config tag based on this. currently i'm sending that with "gtag('app_initialized')", but you're saying i should be using "dataLayer.push({event: 'app_initialized'})"? since all the gtag function does is push to the datalayer i'm unclear on what its significance is.Spinescent
note that you pushed an object with DL.push and all gtag does is pushes args. Args is an array. GTM ignores arrays in DL. GTM can only react to objects with the event property set. So the proper way of tracking is to push objects to the DL as the analytics person asks. Then the analytics person goes to GTM and sets up a trigger listening for this particular event and does other 20 things they need to do on this trigger. All kinds of pixels, GA events, AA events, Tealium events, whatever they need. Front-end does not need to be involved in further marketing complexity.Jelly
ok i'm understanding that if i push an agnostic event to the DL then GTM tags can do multiple things with that, maybe report it to different platforms, that sounds reasonable. but to your point about GTM ignoring arrays, i'm currently using an event that i trigger with "gtag('app_initialized')" as a trigger in GTM and it works. i think it also shows up as an event in the GA3 dashboard, which maybe could have been avoided by doing it your way, but its not ignored by GTM as you say.Spinescent
yeah, not sure how that app_initialized triggers GTM. We typically don't want gtag to trigger anything in GTM, since then it only adds to confusion.Jelly
yes i see that, since using gtag also tracks the event in GA sometimes. anyway to put a bow on the questions from earlier, using a DL variable in the G4 configuration in GTM does not magically update the config after doing DL.push externally (you didn't say that it would, but i was hoping), but if you adjust the settings you described you can re-configure the tracker with a new config. this appears to be the only way to set parameters on events that are dispatched out of your control (such as the enhanced measurement ones).Spinescent
Yeah, that seems to be the only way so far. But they're still working at least on the GTM part of interactions with the gtag lib since it's not perfect either.Jelly
@Jelly did you ever use this approach for "Shared Event Settings" for the Google Tag? It looks like this really is just for the Configuration Settings. Do you have an approach for Shared Event Settings too?Holp
I have not. Seems like a new feature. But it should work just as advertised. I quickly reviewed Measure's log on the shared events properties/settings and found nothing concerning about them there. I would suggest not to use any new functionality from Google unless you really need it. GA4 and GTM lately deploy lots of odd issues to production.Jelly
E
1

in addition to the correct info from @bnazaruk(that is STILL undocumented), I also found that subsequent calls to gtag('config',...) overwrite values from previous calls instead of merging them. The documentation seems to suggest that they are merged rather than replaced and I feel like that was what it used to do a few years ago when I last had to set something like this up. To keep previous config objects I also had to do this

const oldConfig =
  window.dataLayer.find((args) => args['0'] === 'config')?.['2'] ?? {};
gtag('config', '<GA_KEY>', {
  ...oldConfig,
  new_prop: 'blahblah'
});

which only adds in the first instance of a config call since that's the only one I care about, but you could easily change the find call to a filter or reduce to get all of them

Endow answered 1/5, 2024 at 22:29 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.