64

I want to use Google's new measurement protocol for sending tracking events from my server instead of JavaScript.

This page says the client ID is required: https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide#required

And this page says it's optional: https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#visitor

Plus, the format defined in these docs is different- the first page gives an integer as an example and just says it's "a unique value" while the second link says it should be a UUID.

If I send either user IDs or generated UUIDs on my backend, how will Google know to link that visitor to an existing visitor session? It seems like I would need to retrieve GA's internal reference to an existing user.

Any help is appreciated - thanks!

j0k
  • 22,600
  • 28
  • 79
  • 90
Alan Illing
  • 1,376
  • 2
  • 14
  • 18

3 Answers3

60

Integer or UUID

The cid is the equivalent of the second value in the _utma cookie when you use the javascript tracking. In js tracking, it is a random integer (generated by Math.round(2147483647 * Math.random())). But it is strored and sent as a string : so you can use both formats (integer or UUID).

Required/Optional

With js tracking, a request sent with a missing user id is ignored by Analytics servers. So assume that it is required.

Link web visitor with measurement protocol actions

If you want to link your backend user with a visitor previously tracked with Analytics javascript ga.js, you can get the cid value from the _utma cookie. But I don't recommend it; each time it changes (terminal or browser change, cookies cleaning, etc.), you will lose the link with your customer's previous actions.

Update

The analytics.js did not exist when the question was asked. cid is now stored in the cookie _ga. You can get it in javascript with:

ga(function(tracker) {
  var clientId = tracker.get('clientId');
});

As of writing this, when you do get the clientId from the tracker as in the above code it won't give you a UUID but two random 32-bit integers in the format of "X.Y". This implementation may change to the UUID in the future.

Or set it with your own value (like a backend generated UUID):

ga('create', 'UA-XXXXX-Y', {'clientId': 'your_client_id'});
brclz
  • 806
  • 9
  • 23
greg
  • 2,339
  • 1
  • 18
  • 23
  • 2
    Isn't linking a backend user with a visitor previously tracked by analytics.js one of the main points of the 'measurement protocol', allowing correlation of referrers/campaigns/landing-pages with later non-web results? I suspect the right approach is to supply your own site's `clientId` from the get-go (using https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#clientId), so that it's trivially available to both analytics.js's in-page tracking and your own later measurement-protocol operations. – gojomo May 16 '13 at 04:55
  • 1
    The new clientId is the old cid and is now writable (response updated). You still have the same problem: cid is often set before you know the visitor (ex. before login). And you can't re-set it with your own value without loosing all session data (ex referer). – greg Jun 05 '13 at 11:59
  • You have a small typo: an additional ')' at this line: var clientId = tracker.get('clientId')); Thanks a lot for your answer! – claudiut Jul 25 '13 at 07:18
  • 21
    The `clientId` represents a client, as in *device* or *client-side* - **not** a user. As such, it should NOT be set to a backend UUID. The reason Google made it writable is only to use with Measurement Protocol. To track server-side events, for instance, you should 1. have your js code get the clientId value from ga 2. send it to the server (you could store it in session for later use) 3. use that clientId server-side – guidupuy Jul 25 '13 at 16:18
  • 4
    Oh, and linking backend users with Google Analytics is the purpose of the yet-to-be-release `userId`. Coming soon! – guidupuy Jul 25 '13 at 16:25
  • 1
    So what is the best approach? Generate the cid on the server (i'm using node/universal-analytics) or allow analytics.js to manage the cid and retrieve this from the cookie on the server (still not sure how to do this, the format looks different.. req.cookies._ga:GA1.1.759500204.1374013344) Seems like if I generate on the server, I am responsible for keeping a long running session for long term analytics (e.g. express.session.MemoryStore() isn't going to cut it anymore) – Michael Dausmann Sep 02 '13 at 22:19
  • 1
    Does `Math.round(2147483647 * Math.random())` produce a valid `cid`? It doesn't look long enough. – Ken Sharp Mar 02 '16 at 06:06
7

In Rails:

  def save_google_analytics_client_id
    if current_user && cookies["_ga"]
      client_id = cookies["_ga"].split(".").last(2).join(".")
      if current_user.google_analytics_client_id != client_id
        current_user.google_analytics_client_id = client_id
        current_user.save
      end
    end
  end
Jason
  • 89
  • 1
  • 3
  • Beware that Google warns about reading the cookie directly as the format might change. This warning can, at the time of this writing, be found [here](https://developers.google.com/analytics/devguides/collection/analyticsjs/cookies-user-id#getting_the_client_id_from_the_cookie) – rogerkk Dec 13 '18 at 12:57
3

I am using node with express and universal-analytics module and have chosen to use the cid embedded in the _ga cookie rather than generate my own cid server side.

my server.js looks like this...

app.use(function(req, res, next) {
  if(req.session && (!req.session.cid) && req.cookies._ga){
    //Use the cid already embedded in the _ga cookie and save to session so I can access from socket routes
    var gaSplit = req.cookies._ga.split('.');
    req.session.cid = gaSplit[2] + "." + gaSplit[3];
  };
  next();
});  

Then later on, I can do this..

ua = require('universal-analytics')
var visitor = ua('UAXXX', req.session.cid)

HTH

Michael Dausmann
  • 4,202
  • 3
  • 35
  • 48
  • This commit includes all the work I did to get server side ga integration working (I think) https://github.com/hackify/hackify-server/commit/dc9244287b19b7a4c08136918cd213758f6dce11 – Michael Dausmann Sep 04 '13 at 22:39
  • 2
    would probably have this instead: `req.session.cid = req.cookies._ga.split('.').slice(2, 4).join('.');` – waltfy Sep 01 '14 at 16:12
  • @MichaelDausmann, from your example it looks like you have data.userId on backend. From my point of view, I would to recommend you start using server-side userID rather than client-side generated clientID. Such approach unlocks cross-device tracking and enhanced deduplication for your GA data. They have a good article on this particular topic: https://support.google.com/analytics/answer/6205850?hl=en#clientid-userid – Vlad Mysla Jul 03 '15 at 04:38