Obtain GA4 session_id, client_id via GTM
ライター:JAIN Vibhor

Here in this column we share how to obtain GA4 specific parameter values for ex. session_id, client_id. These are auto-generated by the GA4 library and play a crucial role in attributing events / conversions to specific user and traffic sources (Session scoped). 

The process of obtaining these parameter values for the GA4 library is slightly different from the old Universal Analytics (UA) library. In GA4, it’s not straightforward to obtain these values, because there is no customTask method or tracker object (as in UA) and the API used to fetch these values is asynchronous in nature.

In this column we assume GA4 implementation has been done exclusively via GTM.

  1. Business use case
  2. STEP1 –  modify the existing GTM tag
  3. STEP2 –  Custom HTML tag using gtag(“get”,…) API
  4. STEP3 –  Push values to dataLayer
  5. Final result
  6. Should we send to GA4 custom dimension?

Business use case 

Although these values are exported to BigQuery already, there may be specific use cases where it is useful to obtain these on client side and store in other systems or your CRM. 

One specific use case is for use with the Measurement Protocol. Since late October 2022, GA4 Measurement Protocol supports session_id parameters, so that measurement protocol events appear in session-based reporting. A user visits the webshop (through an ad click, google search etc.) —> later goes on to make a purchase from a physical retail store —> but you would still like to attribute such offline purchase to the original campaign source that led a user to the website in the first place.

Similarly, the values can be passed to your CRM during Lead generation Form submission, as a hidden Form field value.

We divide the implementation in 3 steps

STEP1 –  modify the existing GTM tag

Update your GTM tag by adding the following small piece of code (highlighted in yellow) right at the beginning.

window.dataLayer = window.dataLayer || [];
function ga4(){dataLayer.push(arguments);}
<!-- Google Tag Manager -->
// your GTM tag here
// . . .
// . . .
<!-- End Google Tag Manager -->

This will initialize our custom command ga4() giving us access to gtag API commands.

You can choose any custom name you wish, we used ga4(), as long as you do not use the same name as gtag() as this is reserved for use by Google owned tags.

STEP2 –  Custom HTML tag using gtag(“get”,…) API

Next, we create a new Custom HTML tag in GTM which utilizes our custom command ga4() (initialized in STEP1 above) to obtain the necessary GA4 parameter values.

  ga4("get", "YOUR-GA4-MEASUREMENT-ID", "session_id", function(field){ 
    // console.log(field)
    window.dataLayer.push({ event: "session_id_ready", session_id: field });
  ga4("get", "YOUR-GA4-MEASUREMENT-ID", "client_id", function(field){ 
    // console.log(field)
    window.dataLayer.push({ event: "client_id_ready", client_id: field });

Do remember to replace the text YOUR-GA4-MEASUREMENT-ID with you actual GA4 Measurement ID (“G-” ID) 

STEP3 –  Push values to dataLayer

In the last step, you fire this new Custom HTML tag (one we created in STEP2 above) right after GA4 Config tag as part of Tag Sequencing Clean Up tag.

The last point is very important! The way GA4 library works, our Custom HTML should fire after the very first GA4 event on the page has fired (usually this happens with Config tag fires, which is usually set up to automatically send the initial pageview event).

In some GTM set-up, config tag and initial pageview event tag are separate tags (the setting “Send a page view when this configuration loads” is disabed). In such situations, our Custom HTML should fire after the page view event tag (not the GA4 config tag!). 

Final result

Once everything is implemented and published to LIVE site, this is what you will see as page loads

Browser Dev tools —> Console, session_id and client_id values made available in dataLayer

GTM Debug/Preview window —> session_id and client_id values pushed to dataLayer

As you can see, the values are now available in dataLayer. From here on you can access them in any GTM tag, trigger for your use case (send to your CRM, used in another tag etc.)

Should we send to GA4 custom dimension?

Lastly you might think we can send these values to GA4 as custom dimensions in order to generate more granular reporting in GA4 UI, for example User-level, Session-level reports. A similar use case is very common for Universal Analytics. However, it is not recommended to send these to GA4 for following reasons:

  • These values are already exported to BigQuery, if you need more granular reporting
  • session_id, client_id are essentially random numbers. Independently, they may not classify as PII, but depending how you use these and stitch with other user data these might classify as PII and therefore may bring legal, privacy risk under GDPR, CCPA 
  • Lastly, depending on user traffic volume, these can be high cardinality dimensions (dimensions with high number of unique values assigned to it) for your webstream and can affect your standard reports in GA4. In GA4, in-case dimensions exceed the maximum threshold of unique value in one day (currently max 500 unique value for a dimension in one day) GA UI’s standard report aggregates results in the “(other)” row. Even the reports that do not include such high-cardinality dimensions, it will cause every other standard report to be aggregated under (other) as well. So be careful to set up custom dimensions that have a high number of unique values.


JAIN Vibhor