Hotjar User ID tracking in Google Analytics with Google Tag Manager

Hotjar Recordings Dashboard

Updated 30th of July 2021.

This is the 4th time I write about tracking Hotjar User ID in Google Analytics using Google Tag Manager. Some people were complaining that the setup didn’t work (they were having issues with storing the Hotjar User ID in the Session Cookie. Because of this, in this last update, I have tried to simplify this by using a GTM Template for setting the cookie.

I have also deleted some comments that no longer are relevant.

Updated 14th of May 2019.

This is the 3rd time I write about tracking Hotjar User ID in Google Analytics using Google Tag Manager. Hotjar have had a history of changing how to access the User ID, and that is why this is the 3rd time I write about the subject.

The advantage of tracking the Hotjar User ID in Google Analytics, is that you now can use Google Analytics to identify behavior that Hotjar can help you answer.

The first thing you should do if you haven’t done it yet is to head over to Hotjar, and create an account.

Google Analytics setup

Head over to Google Analytics and create a Custom Dimension with Scope set to Session. The S: as I use in the Dimension name, simply means that this is a Dimension with the Scope set to Session.

Google Analytics Hotjar Dimension

Google Tag Manager Setup

We are going to create 4 Variables, 2 Tags and 1 Trigger.

We are also going to store the Hotjar User ID in a Session Cookie. For simplicity I’m using the Cookie Creator Template for setting the Session Cookie, and I use the Template as is. This means the Session Cookie name will use the default allowed template cookie name which is _my_cookie_name.

For setting a more useful cookie name, read the documentation of the template (for some reasons the template is made in a way that you have to alter the template to use your own cookie name).

Google Tag Manager Variables

NoVariable NameVariable TypeBuilt in / Custom
1Hotjar - timerEventNumberData Layer VariableCustom
2Hotjar - timerLimitCustom JavascriptCustom
3Hotjar - UserId - CJSCustom JavascriptCustom
4Hotjar - UserId - Cookie1st Party CookieCustom

We need to create 4 different GTM Variables.

  1. Getting the Hotjar userId from Hotjar
  2. Getting the Hotjar User ID from the Session Cookie
  3. Hotjar – timerEventNumber
  4. Hotjar – timerLimit

The method we are going to use to trigger these tags are somewhat special, we are going to use Tag Sequencing with the Cookie Creator Tag.

If you aren’t familiar with Tag Sequencing, I recommend that you read Understanding Tag Sequencing In Google Tag Manager by Simo Ahava.

1. Getting the Hotjar userId from Hotjar

The Hotjar userId contains a value similar to this: 41d7c48b-8689-42dd-9a79-83690993f2ee. Create a Custom Javascript Variable, and add the code below. This code will grab the first part of the Hotjar userId (41d7c48b), which is the User ID you find in Hotjar. We will later save this ID to a Session Cookie.

Name the Variable Hotjar – UserId – CJS.

This code have been changed several times. I credit Alex Asigno (see comment field) for this version.

Create a 1st Party Cookie Variable, and add _my_cookie_name as the Cookie Name (_my_cookie_name is the default allowed cookie name in the Cookie Creator Template). This variable will grab our modified Hotjar User ID that we have stored as a Session Cookie.

Name the Variable Hotjar UserId – Cookie.

Hotjar userId Cookie Variable

3. Hotjar – timerEventNumber

This is a “nice to know” variable for our tracking. We are going to use a Timer trigger for our Hotjar User ID tracking, and the timerEventNumber will tell us how many times the Timer has to “ping” Hotjar before we get the Hotjar userId.

Create a Data Layer Variable, name the Variable for timerEventNumber. In the field Data Layer Variable Name, add gtm.timerEventNumber as the value.

Hotjar - GTM - timerEventNumber Variable

4. Hotjar – timerLimit

A Timer Trigger can be limited. We are going to “ping” for the Hotjar ID up to 6 times. However, if the Hotjar UserId already exists in the hotjarId cookie, we will not run the trigger. This is done by setting the timerLimit to 0.

Create a Custom Javascript Variable, and add the code below, and call the variable for Hotjar – timerLimit.

Google Tag Manager Trigger

We need to create a Timer Trigger for our tracking. This Trigger will check if the Hotjar userId is avilable, it will store the modified Hotjar UserId from the variable Hotjar UserId to a Session Cookie, and then the ID will be tracked in Google Analytics.

Name the Trigger Hotjar – Timer.

Hotjar - GTM Timer Trigger

Interval setting

This is the number of milliseconds between firing events. I have set the timer to check for the Hotjar userId every 2 seconds (2000 milliseconds).

Limit setting

This is the maximum number of times to fire the event. Insert the Hotjar – timerLimit Variable here.

Enable This trigger setting

This setting tells the Timer when it should be triggered. The condition checks if our modified Hotjar UserId is stored in the Session Cookie. If it exist, the Trigger will NOT be enabled.

Fire On setting

The setting is the same as above. If the Hotjar UserId is found in the Session Cookie, the Timer will not fire.

Google Tag Manager Tags

We need to create 2 different GTM Tags.

  1. 1 Cookie Creator Tag for storing the Hotjar User ID to a Session Cookie.
  2. 1 Google Analytics Tag for tracking the ID from the Session Cookie.

Tag 1: Google Analytics Event tracking of Hotjar User ID

This is the Tag that is going to track the Hotjar UserId to Google Analytics. Create a Google Analytics Event Tag with the Non-Interaction Hit set to True.

Hotjar Google Analytics Event Tag

In the Label field, add the Variable {{Hotjar UserId – Cookie}}.

In the Value field, add the Variable {{Hotjar – timerEventNumber}}.

You should also add the Variable {{Hotjar UserId – Cookie}} as a Dimension to your Google Analytics Settings Variable. I have only added the dimension directly to this tag for demonstration purposes. Note that I also use a Variable for the Dimension Index Number.

Do NOT add any Triggers to the Tag. Our tag “Hotjar – Store UserId to Cookie” will trigger this tag as a Cleanup Tag. The screenshot below only shows how things will look when we are finished with our setup.

Hotjar Google Analytics Event Tag Trigger Setting

Create a Cookie Creator Tag and name it Hotjar – Store UserId to Cookie.

  • Install the Cookie Creator Template.
  • Set up the Cookie Creator Tag and name it Hotjar – Store UserId to Cookie.
    • Cookie Name: _my_cookie_name
    • Cookie Value: {{Hotjar – userId – CJS}}
    • Trigger: Hotjar – Timer
Hotjar set cookie with Cookie Creator Tag
Hotjar - Store UserId to Cookie - Advanced Setting - GTM Tag

The image shows settings for this Tag. As you can see we are using Tag Sequencing, and the Trigger is the previous made Hotjar – Timer Trigger. Here is the explanation of what’s going on:

  • The Timer Trigger will every 2 seconds check if the variable Hotjar User ID contains a Hotjar userId, unless our modified User ID is already stored in a Session Cookie.
    • If Hotjar User ID is undefined, this tag fails and further sequences are aborted. Then new attempts will be done every 2 second until it has a userId, or 6 attempts have been done.
  • If it’s not undefined, our modified Hotjar User ID is stored to a Session Cookie.
    • In addition, this will trigger our GA – Event – Hotjar tag as a Cleanup Tag.
    • The GA – Event – Hotjar tag will track our modified Hotjar User ID from the Session Cookie.

If you haven’t done it already, head over to Hotjar, create an account, set up the tracking described in this blog post, and use Google Analytics to identify behavior that Hotjar can help you answer.

Some final words

The content of this blog post was last updated 30th of July 2021, so if you have visited this blog post before, some of the content and solutions are different.

We live in a world of consent and privacy. Make sure you have the right consent to do this type of tracking.

I have deleted some comments that are no longer relevant.

27 Comments on "Hotjar User ID tracking in Google Analytics with Google Tag Manager"

  1. Very useful, thanks Savio!

    Those copying / pasting names of variable/trigger/container names might run into an issue when previewing the tag in the last step “Tag 2: Store Hotjar User ID to Local Storage” because “{{Hotjar User ID – Get}}” uses a hyphen, while the earlier steps formatted itself to a dash.

  2. Loryn Thompson | June 14, 2016 at 4:33 pm | Reply

    Hey Eivind, thanks so much for putting this together! It’s always best to link your analytics tools together whenever possible 🙂

    I’m curious, though — could I achieve the same (or similar) result by pushing the Hotjar ID to the data layer, setting up a data layer variable, and adding it as a custom dimension on a pageview, making sure that the Hotjar tag fires before the pageview tag? Just wanted to avoid adding an extra event to my setup, if possible, or at least understand why it wouldn’t work for my own edification 🙂

    Also, do you know if the Hotjar ID is set for every user that visits a page with the Hotjar code, or only if the user has data saved to Hotjar (poll, recording, etc.)?

    Thanks for your help!

    • Eivind Savio | June 16, 2016 at 9:18 pm | Reply

      Hi Loryn

      Unfortunately you get access to the Hotjar ID a long time after the pageview tag has fired. You will not be able to grab the ID on DOM Ready, but you may be able to grab the ID on Window Load (and you wouldn’t track pageviews on Window Load).

      You could however use my “timer method” and set the Hotjar ID into Local Storage (or a cookie), and on the next pageview you will be able to grab the ID from Local Storage or the cookie, and send it to a dimension. This method means that you will not be able to track Hotjar ID for “bounces”, only for users with more than 1 pageview.

      Is the Hotjar ID set for every user…?
      I haven’t studied this in detail, but some quick tests indicates that the Hotjar ID is only set when a user has data saved to Hotjar (poll, recording, heatmap).

      Regards,
      Eivind

  3. Hi Eivind,

    first of all, great idea and find!
    I’ve integrated this as a test in Google Analytics and see the first ID’s dripping in.
    The only difference I made is set the custom dimension to ‘Hit’ level as this is an ID tied to a user (due to privacy concerns).
    I understand choosing the ‘session’ level but that might mean you could get stuck on the login/logged-out user (if you only use the hotjar ID for user ID tracking, which I’m doing in this test).

    Do you have any idea what triggers the hotjar ID in particular?
    I’ve been testing the tracked hotjar ID’s and haven’t found them in Hotjar (yet? have you noticed a lag in hotjar?)

    gr,
    dries

    • You will not be able to match all Hotjar ID’s vs. those collected in GA. However, I’m able to match most of them. Your Hotjar plan may also play a role here. I checked this today on a paid Hotjar account. I could find most Hotjar ID’s tracked in GA that I was interested in (and nailed down some checkout issues). 🙂

  4. I have been noodling on this for awhile. You make my day. There is rich information by matching up GA behavior with Hotjar’s recording. It will provide much better analysis for UX and CRO issues. Thank you very much 🙂

  5. That’s correct, and I have done that on purpose. Why have the tag to fire on every page, you just need to store the Hotjar User ID once. Reading the Hotjar User ID can be done with your other tags as I mention at the bottom of this post.

  6. Excellent post and a great intro to Google Tag Manager timers!

  7. Thanks for this help Savio, but I’m also at the end of the road on this. I’ll be watching out for ay new on a solution of course

    Meanwhile does anyone know of any good survey/poll tool that does have a working method for populating a GU custom dimension with a UID?

    GA integration?

  8. Rainer Kretzer | December 22, 2016 at 4:59 pm | Reply

    After trial and erroring throug the properties for a while, I have been successful with: hj.pageVisit.property.get(‘userId’).

    • Nice find Rainer. Did try it on a couple of sites, and it works.

      Can I credit you somehow when I update this blog post? Ex. do you have a blog or something?

      Regards,
      Eivind

    • Wow, thanks a lot Rainer!

      • Rainer Kretzer | December 23, 2016 at 7:10 pm | Reply

        Hej Eivind,

        the way you mentioned me in your update is absolutely fine. I am grateful for your great tutorial and I am glad I was able to help out with a solution for the issues related to Hotjar’s recent API changes.

        Merry Christmas!
        Rainer

  9. Hi Ancu

    You are correct about localStorage on iPhone. As far as I know this problem is for Safari in Private Browsing:
    http://www.mattburkedev.com/dom-exception-22-quota-exceeded-on-safari-private-browsing-with-localstorage/

    Or have you come across this as a general problem for iPhone?

    Happy holiday to you too!

  10. Followed the guide rigorously using the ‘userID’ method, with no joy.
    Should l be abel to see the UserID as a variable using GTM in preview mode?
    The timer runs for 6 iterations, but i still get undefined. Have increased to 6s intervals but still nothing.
    Bad question in know but can anyone give me any hints on what else to check?

    • Rainer Kretzer | January 6, 2017 at 9:41 pm | Reply

      I have initially encountered the same problem. Reading the first comment to this post I realized, that I did not name my variables consistently regarding declaration and usage in different places in GTM. Please check all your hyphens. I had some inconsistencies with them: some where simple minus-chars, others have been typographically correct hyphens, which are different characters and hence will result in inconsistent variable names.

  11. Hi,

    I don’t understand, Where did you identfy this ” Hotjar UserID – D – Index ” ?

    Thanks

    • Eivind Savio | May 11, 2017 at 6:29 pm | Reply

      This is your Google Analytics Custom Dimension Index number.

      You could write the number directly into the GTM Custom Dimension Index column, but it’s better to use a GTM Variable for this.

  12. Hi there!

    Thank you for your instructions, very helpful 🙂 However, I do have a question – I followed the instructions and I am indeed getting the Hotjar User Ids as a second dimensions. Sometimes I get the User Id but when inserted into the search box in Hotjar, there are no recordings. Am I the only one getting this..?

  13. Hi Eivind,

    Thank you for this great post 🙂 I have been using it successfully but I notice that i still see Hotjar User ID’s coming in, even if I have no recordings/heatmpas whatsoever running. I have exactly did what you’ve written down. Do you have any idea as to why this might be the case?

    Best,

    Paco

  14. For new readers – the tracking was down but now it works again because id remains the same after page reload (at least 4 me), so this post is still relevant 🙂
    Altho you might want to check out the above comments where Savio mentioned another method (a better one), using session cookies.

  15. Anyone reading this will need to update the get variable with the following as Hotjar have updated their code.

    function() {
    return hj.globals.get(“userId”).split(“-“).shift();
    }

  16. I’ve made a script based on this article. You can just create new session based custom dimension and paste this script into custom html tag with window load trigger:

    (function(){
    var hjCoockieName=’hotjarid’; //name for cookie mark
    var dimensionNumber=’3′; //prefered custom dimension number
    var gaTrackerName=’myTraker’; //your tracker name

    function setCookie(cname, cvalue, exhours) {
    var d = new Date();
    d.setTime(d.getTime() + (exhours*60*60*1000));
    var expires = “expires=”+ d.toUTCString();
    document.cookie = cname + “=” + cvalue + “;” + expires + “;path=/”;
    }
    function getCookie(cname) {
    var name = cname + “=”;
    var decodedCookie = decodeURIComponent(document.cookie);
    var ca = decodedCookie.split(‘;’);
    for(var i = 0; i 0)
    gaTrackerName=gaTrackerName+’.’
    var dimension = ‘dimension’+dimensionNumber;
    ga(gaTrackerName+’send’, ‘event’, ‘setHotjarId’, document.location.pathname, {
    ‘nonInteraction’ : true,
    dimension : hj.globals.get(“userId”).split(“-“)[0]
    });
    setCookie(hjCoockieName, ‘true’, 0.5);
    }

    if (getCookie(hjCoockieName).length==0){
    setTimeout(check, 1000);
    }
    })();

    It works perfect for me.
    Don’t forget to set tracker name in your GA settings variable in GTM.

  17. Hi Eivind, Thank you for the great write-up. What would be the end result of this? Would I be able to see Hotjar UserIDs in Google Analytics? Thanks!

Leave a comment

Your email address will not be published.


*


This site uses Akismet to reduce spam. Learn how your comment data is processed.