May 08 13

Linking events to a specific user in Google Universal Analytics

By

In this post I will show you how to send events for a specific user from both the JavaScript agent (Analytics.js) and the Measurement Protocol. I could not find any existing information about how to do so. After some research, I did, however, find a great presentation by @techpad that talks about improving e-commerce tracking using Universal Analytics. In one of the last slides, the presentation talks about this issue exactly (slide #31).

The Measurement Protocol enables you to send events from a non web-based system, including a native mobile application or a batch process. In order to be able to link an event to the right user, you have to present the user identification as part of the call. Following is an example:


curl --data "v=1&tid=UA-XXX-X&cid=12345&t=pageview&dp=%2Fhome" http://www.google-analytics.com/collect

In this call I tell Google Analytics that user ID no. 12345 viewed a page called “home”.

curl is used here to execute a post call to Google. Even if you are not familiar with curl, or are not a technical person, the call is pretty trivial: you have to pass:

  • The property ID you want to use for tracking this event (tid)
  • The client ID (cid)
  • The information about the pageview (t and dp)

I recommend you check out the Measurement Protocol Developer Guide for detailed information about the parameters that you can pass, and examples of how to send pageviews, events, e-commerce tracking and more.

Google documentation states that the client ID (cid) should be an anonymous ID

v=1             // Version.
&tid=UA-XXXX-Y  // Tracking ID / Web property / Property ID.
&cid=12345        // Anonymous Client ID.
&t=             // Hit Type.

(I’m guessing they mean that the ID should be anonymous to Google – not to you, obviously…) Using an email address as the client’s ID will enable Google to identify this user, whereas passing a client ID that you allocated/invented, and which does not hold any personal information, can only be linked to the actual user by yourself.

So far so good. Now we know how to send specific user events using the Measurement Protocol, but what about sending events using Analytics.js? Luckily, there is a way to send pageviews and other events on behalf of users:

Tell Analytics.js to use your own client ID (clientId) when creating the tracker:

ga('create', 'UA-XXXX-Y', {
  'clientId', '12345'
});

However, when using this method there are a few things you should keep in mind:

  • The default tracking code includes the domain as a 3rd parameter that is passed to the create command. Trying to set the clientId when the domain is passed did not work. I’m not sure why.

    // does not work
    ga('create', 'UA-XXXX-Y', 'mydomain.com', {'clientId': clientId });
    
    // does work
    ga('create', 'UA-XXXX-Y', {'clientId': clientId });
    

  • The GA team says they have “two acceptable formats for a client ID: either a UUID Version 4 (recommended) or their legacy anonymous identifier format “X.Y”, where X and Y are each random 32-bit numbers”. Based on my own experiments, you can, in fact, pass anything you like as the clientId, but I assume that sooner or later they will change this and only accept these two formats.
  • If you already have a tracker and you want to change the clientId while the user is on the page (for example, if you use an Ajax call for the login process), the best way of doing so is by creating a second tracker and passing the clientId during the creation of that tracker:
    // create a second tracker (called 'identified') with the
    //  relevant client Id
    ga("create", "UA-XXXX-Y", {
          "name":"identified", 
          "clientId":"12345"
    });
    

    Now you have two trackers on the page – one with the wrong client Id (the tracker you had before the login) and another one with the right client Id (the one we called “identified”). All you have to do from now on (as long as the user does not leave the page) is make sure you send events using the right tracker:

    ga(function() {   
      // look for a tracker called 'identified' (exists
      //   only after login)
      var tracker = ga.getByName('identified');
      if (typeof(tracker) == "undefined") {
        // if does not exist, send the event using 
        //   the default tracker
        ga('send', 'pageview');
      } else {
        // if exists, send the event using that tracker
        ga('identified.send', 'pageview');
      }
    });
    

    The second tracker overrides the clientId in _ga so from now on, new trackers will use the right clientId.

You should also note that the clientId is the ID that Google Analytics uses to identify the user. It is stored in a cookie (Universal uses the _ga cookie and Google Analytics uses __utma). The above call will tell Google to use your clientId instead of creating one (or using the one that is already in the cookie in the case of a returning user). Don’t confuse this method with the “alias” method available in Mixpanel where they link the current user ID to the one you pass. This might sound like a small nuance but it is actually a big deal. I will explain more about it in my next post.

It is also important to state that this is the exact equivalent to manually changing the ID in the cookie (changing the _ga and __utma cookies) – which I have done in the past when wanting to send offline events on behalf of my visitors. There are, however, two improvements: It is easier to do so using this method, and more importantly, if the offline events are sent during the 30 minute session (or any other time limit you specify), they will be part of the same session.

One last thing you should remember: In order to be able to send events using the measurement protocol, you have to store the clientId somewhere on your server so that later on you are able to send that ID back to Google via the measurement protocol.

I would be happy to hear your thoughts. Please feel free to email me or leave a comment.

  • Pingback: The User-Centric Approach – Google Universal Analytics vs. Mixpanel | Web Analytics()

  • Niroshan

    GUA match offline event with previous session(online visit), if and
    only if the offline events are sent during the 30 minute(default time)
    session.

    I conducted a test you can find it here –

    goo.gl/F6QJ0

    If you have better solution please let me know

    • Shay Sharon

      Do you say that offline events that are sent after the session is over will not be credited to the last session? I think that is a normal behavior.

      From your post it sounds like you could not even tie the offline event to the right user after the session was over. Is that the case?

      • niroshan

        Yes that is the case. GUA identified the offline event(fired after 12 hours) as a new user even though I used the same cid.

        • Shay Sharon

          weird! I will give it a try.

          • NIroshan

            thanks share the result with me

          • Frank

            Hi everybody, if I capture the client id of an AdWords visit and send a transaction via measurement protocol with this client id it does not get stitched to this session but shows as a new direct visit (and it seems as a new user) even if this hit is made immediately after the client id capturing. Anything to be aware of, any idea what I might be doing wrong?

          • Anonymous

            Hey, I could not reproduce your problem. I’ve sent an offline event (using the measurement protocol) and it was added to the same visit as the online event I’ve sent seconds before.

            Try working with the real time report in Google Analytics and see if Google Analytics identifies the offline and online events as two separate users.

          • Frank

            Thanks for your reply. I found the error… I was using Analytics Pros’ PHP library and had set ANALYTICS_HASH_IDS to true – misinterpreted what it does 🙂

          • did you figure this out?

    • So far, this is what I’m seeing too. I have conversions I need to load a day after the data is collected, but the conversions I load create a new user, even though I’m using the correct clientid’s.

      • shaysharon

        I have no problem sending offline events. If you want, contact me via email and I will try to help you out.

        • Are you able to send them after the session timeout? this is my current theory. My conversions are loaded the following day, so well beyond the 30 minute session.

          let me know how to email you and I’ll send details. Thanks for the help!

          • shaysharon

            Yes. I did not have a problem sending offline events after the session was closed. Please contact me at shay dot sharon at gmail dot com.

  • I believe UA operates with 2 core dimensions – Client ID and User ID. Client ID is a client instance (will be different across devices etc). It’s the User ID that will be used to tie visits back to a single user. Not sure if User ID is enabled yet but this message (albeit from last year) suggests it’s still in development https://groups.google.com/d/msg/google-analytics-measurement-protocol/rE9otWYDFHw/8JlJJV-UmKcJ

    • Anonymous

      You are right that eventually, the User ID property will be used to set your own alias. Regarding the Client ID, I think it will be better to define it as the internal ID used by Google rather than the client instance since I should use (according to Google’s documentation) the same Client ID to send events on behalf of a specific user across devices.

      I agree that once the User ID will be available, it will be better to use it instead of overriding the Client ID (check out my latest post about this issue – http://blog.intlock.com/the-user-centric-approach-google-universal-analytics-vs-mixpanel/).

      Thanks,

      Shay

      • Priya

        My application is only hosted on desktop and I need the ability to identify users uniquely. In this case , the userid will map to user alias ( a UUID for user ) , but should the client id be unique for the session ? Because when I look at the data ( cid is different for different users), User Id based view in google analytics UI, tells me that unique visitors is greater than returning visitors for the hits sent for 2 users . This seems wrong to me. So does it mean cid remains same across users but uid is unique ?? Pls clarify

    • Ed

      Has anyone heard anymore about the release of the User ID (not Client ID) feature? It is not documented anywhere yet as far as I can see.

      • Anonymous

        I don’t think there is anything new… Google Universal does not support the User ID (at least not according to the official documentation of Analytics.js and the measurement protocol).

  • Pingback: Linking events to a specific user in Google Uni...()

  • Pingback: A Different Approach to Cross-Domain Tracking | Web Analytics()

  • Pingback: The Full Customer Journey - Google, Mixpanel and KISSmetrics - Part II | Web Analytics()

  • Priya

    My application is only hosted on desktop and I need the ability to identify users uniquely. In this case , the userid will map to user alias ( a UUID for user ) , but should the client id be unique for the session ? Because when I look at the data ( cid is different for different users), User Id based view in google analytics UI, tells me that unique visitors is greater than returning visitors for the hits sent for 2 users . This seems wrong to me. So does it mean cid remains same across users but uid is unique ?? Pls clarify.

    • Anonymous

      I am not sure I understand your question but it makes sense that a) you will have more unique visitors than returning visitors and b) the client id will be different for different users/devices/browsers.

  • Mike

    Thanks a lot for the post, it was very helpfull as we are trying to get all the tracking done by analytics. I have just one question left and that is “How can I find the client_id inside the analytics reporting” … I tried already a lot of custom reports but cannot find this specific field anywhere? Maybe somebody here can help? Thanks a lot!

  • Mike

    Thanks a lot for the post, it was very helpfull as we are trying to get all the tracking done by analytics. I have just one question left and that is “How can I find the client_id inside the analytics reporting” … I tried already a lot of custom reports but cannot find this specific field anywhere? Maybe somebody here can help? Thanks a lot!

    • Anonymous

      Thanks! As far as I know, the client_id is hidden in the analytics reporting. You can always store it as a custom variable if you want to be able to retrieve it.

      By the way, you can use now the User ID feature instead of changing the client id. The User ID field is also hidden but by using it, you will be able to get the cross device reports. For more information, check out this excellent post: http://cutroni.com/blog/2014/04/10/understanding-cross-device-measurement-and-the-user-id/

  • Anthony Stal

    Hey There! Thanks so much for this amazing piece of information. I’d like to ask if you might have advice on the following issue. I work for a business that makes sales online in a type of “shopping cart”, but by the nature of our business, when a user submits their application there are some manual checks that have to happen on our part, which can take up to a few days. Then if we approve the user, we send the user an email telling them to back to our website to complete the last steps in “checking out” or their cart (or completing their partnership). When they return to the shopping cart for this last step, we need them to be linked to their initial session in analytics, so we can attribute that final conversion to its original sources. Could we achieve this by pushing their original user-id, as you mention in this post? Do you have any suggestions for us? Any help you can provide will be immensely appreciated, thank you! – Anthony

    • Anonymous

      Hey Anthony, you can definitely use this method to do that! I don’t know if you had a chance to read my post about the user-centric approach in Google Universal (http://blog.intlock.com/the-user-centric-approach-google-universal-analytics-vs-mixpanel/ ) but towards the end of the post there is an example of how to get the client id from Google Universal. If you can send this value along with the shopping cart and later on, append it as a parameter to the checking out page (where you will take this parameter and set it as the current client id) you will be able to close the loop.

      Another option is to use the User ID feature (which was not available when I wrote this post). The only advantage here is that you will use your own ids instead of using the client id generated by Google Universal.