Note: If you haven’t read David Vallejo’s blog yet, please stop wasting your time reading this post and read David’s post about GA4 cross-domain tracking.
Goal
Manually set up GA4 cross-domain tracking in cases when auto set up doesn’t work
Intro
GA4 makes cross-domain implementation very simple, just a few clicks in the admin interface and everything should work. You can read Simo Ahava post with all the details.
But if you need to set up cross-domain manually for example for JavaScript redirects, GA4 documentation gives very brief instructions, in short add client_id
and session_id
in a redirect url, and set them in GA4 config after the redirect. It sounds easy, but not as cool as it was for GA3. In GA3 we have a special linker helper which can decorate any link.
I made a Google-recommended implementation and even wrote a blog post about it, but during testing I faced very strange GA4 behavior. Despite that after redirection I sent the same client_id
and session_id
in GA4 report sessions become direct / none
. I tried different variants and was ready to give up, then suddenly found a brilliant David Vallejo post about cross domain tracking.
David Vallejo in his post mentioned that analytics.js
has utility method google_tag_data.glBridge.generate
which can create valid _gl
param. I don’t know how he found it, for me it’s next to impossible. He must have been in the middle of rewriting out of pleasure analytics.js
for C++ or Assembler and found this tiny little utility. David is really the best.
Tag solution
Unfortunately, we can’t use custom templates, as Google doesn’t allow us to access google_tag_data
from templates anymore.
The idea remains the same: we will create the chtml.setup_gl HTML tag, which generates the dataLayer event with _gl
:
|
|
The code is very simple, we call window.google_tag_data.glBridge.generate()
and pass two cookies:
_ga
- clientId cookie_ga_<Measurement Id>
- session cookie (in my case_ga_WSNZDRC2JS
)
That’s all we need. So to get these cookies, I defined a few cookie variables:
{{cookie._ga}}
- with Cookie Name_ga
{{cookie._ga4_session}}
- with Cookie Name_ga_{{const.ga4.mid}}
And also a constant variable {{const.ga4.mid}}
with Measurement Id in my case WSNZDRC2JS
.
The important note
This solution uses analytics.js
, so it will work only after the library is loaded. If you don’t use UA anymore, you still need to inject the library, for example, using an HTML tag:
|
|
And now you can use the ga_ready
event to trigger the previous tag to generate _gl
.
Previous solution, currently not working
Based on David’s blog post I created a GTM custom template which makes it easier to generate a _gl
parameter. But please keep in mind, this template uses glBridge
utility, and this utility is a part of analytics.js
. In 2023, Google is going to shut down GA3 and analytics.js
might stop working or turn into a pumpkin.
Template logic
- The template get
_ga
and_ga_YOUR_MEASURMENT_ID
cookie values and pass them intogoogle_tag_data.glBridge.generate
method. google_tag_data.glBridge.generate
method returns a value for_gl
parameter.- The template makes a dataLayer push with
_gl
value. - You can get the value from a dataLayer and add
_gl
parameter to any link you need
Template usage example
Note: I sent the template for submission in the Template Gallery, but at the moment you can download it by this link .
Add template to your landing page GTM container. Go to the Template Page, click
New
in the Tag Templates section. In the left menu selectImport
and select the template file . And Save template after importing.Create template’s tag. Go to the Tags page and add a new tag based on the template.
In the Measurement Id field set your GA4 data stream id.
You should load
analytics.js
before using the template, it’s not a problem if you use GA3 alongside with GA4. Otherwise, the template has a checkbox called load analytics.js, you can check it and the template will load the library.Also in Additional Settings you can add cookie prefix if for some reasons you changed it in GA4.config. You can also change dataLayer event name, as by default it is linker_ready.
- Add the tag as a
cleanup tag
for the GA4 Configuration tag. It is guaranteed that_ga
cookie is set, and the tag can get its value. If a user can spend more than 2 minutes on a landing page, it’s better to add a timer trigger for the tag, just to refresh_gl
value. The GA3 linker param was valid for 2 minutes, I don’t know the number for GA4, but I expect it should be the same. Another variant instead of using a timer trigger where you can trigger the tag just before the redirect.
- Create a dataLayer variable to get
_gl
value.
- If you will decorate links from GTM, you can create custom html tag and add something like this:
|
|
- If developers will decorate links from code they can get
_gl
value from dataLayer for example like this, I assume that you have one GTM container on a landing page:
|
|
And ask developers to add this value to the url
before redirect, something like this:
|
|
That’s all, thanks for reading. I hope you will find the template helpful, and as usual if you have any questions or ideas please message me on LinkedIn