Google Analytics : Measurement Protocol

February 24, 2016 by JavaScript   PHP   SEO  

Recently after whining like a little bitch and a soothing evening of brutally flogging myself, I delved deeper into the features of my resurrected Google Analytics (GA) account as an attempt to amend for my sins.

Lets assume for a second that you want to measure the performance of certain assets on your website (just like Silas from the Da Vinci Code in the preceding clip).

In my case I am interested in:

  • how users interact with the social buttons on my website (yes GA reports traffic sources - the FROM part, I am however interested in the TO part as well - do users actually use these buttons?).

  • how users interact with the real estate on my website (e.g. the Latest Posts, Most Commented Posts sections, do these sections deserve the real estate they're in, or can / must I replace it with something else?)

  • the metrics regarding source code downloaded from my website (how often do visitors download stuff and what do they download?).

How would one go about measuring this using GA?

The easiest way is to make use of analytics.js library - which you're most likely using on your website already (the notorious tracking snippet).

(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),

ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');

There are various tracking options available to capture user interactions, in the snippet below I measure social interactions (one can also provide custom measurable actions using events)

ga(function(tracker) { // Library fully loaded
	$(function() { // DOM fully loaded
		$('.mySelector').on('click', function() { 
			tracker.send('social', {
			  'socialNetwork': 'facebook',
			  'socialAction': 'share',
			  'socialTarget': ''

In the snippet above the GA callback (ga(function(tracker)), executes as soon as the analytics.js library is loaded and ready. Which in turn (if the DOM is loaded) attaches a click event to our social button and ultimately sends the interaction to the GA server for collection when clicked.

On the GA dashboard side of things, one can add a new widget containing the social network columns like seen in the screenshot below.

Social Actions by Social Network and Action

A widget similar to the one seen below will be displayed.

Social Actions by Social Network and Action Widget

But what about scenarios where using the GA JavaScript library might not be an option?

In situations like that we can make use of the measurement protocol (underlying service used by analytics.js as well), basically one would just need to make a HTTP request along with the appropriate parameters to the GA servers.

As demonstration, my poison of choice is PHP, observe the constructor of CSTruter\Analytics\MeasurementProtocol :

public function __construct($trackingId, $clientId = NULL) {
	$this->trackingId = $trackingId;
	$this->request = new Request();
	if ($clientId == NULL) {
		if (isset($_COOKIE["_ga"])) {
			list($version, $domainDepth, $cid1, $cid2) 
				= explode('.', $_COOKIE["_ga"], 4);
			$clientId = $cid1.'.'.$cid2;
		} else {
			$clientId = session_id();
	$this->clientId = $clientId;

The interesting thing to note is the usage of the $clientId parameter, like seen in the snippet above this parameter is optional, but the field it represents in the HTTP request is actually required. I attempt to retrieve the clientId from the cookie previously set via the analytics.js code (sensible from a reporting perspective to use the same clientId for the backend and frontend), if that fails, I simply use the session id instead.

This might be a bit superfluous, if the tracking cookie is available, it means that the analytics.js library was involved somewhere in the process and seeing that it is not recommended to access the cookie directly, we should rather retrieve the clientId from our GA ready callback and pass it on to our PHP script. Additionally if JavaScript is not part of the equation, it means the cookie won't be set either.

Observe the sendEvent method:

public function sendEvent($category, $action, $label = NULL) {
	$args = [
		'v' => $this->version,	// Protocol Version
		'tid' => $this->trackingId, // Tracking Id
		'cid' => $this->clientId, // Client Id
		't' => 'event',	// Hit Type
		'ec' => $category, // Event Category
		'ea' => $action, // Event Action
		'el' => $label, // Event Label
		'dr' => filter_input(INPUT_SERVER, 'HTTP_REFERER'), // Document Referrer (Optional)
		'uip' => filter_input(INPUT_SERVER, 'REMOTE_ADDR') // IP Override (Optional)
	return $this->request->getResponse($args);

The dr (Document referrer) and uip (User IP) fields are optional, but I feel it is quite important to provide values for these fields (also more consistent with what the analytics.js functions are doing), if we omit the uip field, the IP address of the originating server will be used (my server is located in Germany, so it might start to think of myself as ChristHoff, in the meantime it is a penguin somewhere in Antarctica looking for a good time).

Weirdly enough the server responds with a transparent 1x1 gif image to our request, known as a tracking pixel (probably as a remnant of its analytics.js legacy), the crappy thing is that it will do that regardless of the validity of the request, luckily the protocol also provides the means to validate our requests (you can see an example of this in the unit test for the demo code).

In the following snippet, you can see an usage example.

$analytics = new Analytics('UA-XXXXX-Y');
$analytics->sendEvent('Downloads', 'Download', 'David Hasselhoff greatest hits');

To display the event on one's dashboard, the following settings can be used when creating a new widget.

Downloads Widget Settings

A widget similar to the one seen below will be displayed.

Downloads Widget

And that is pretty much the just of it, be sure to explore a bit further, e.g. e-commerce tracking.

Leave a Comment

Related Downloads

Google Measurement Protocol