How to Track if Google Analytics Is Blocked in Analytics
Ad blockers have been around for years - and I won’t go into a moral or ethical discussion about the use of them. But with Apple’s iOS9 update, content (or ad) blocking suddenly became much more mainstream. Now, the problem is that many ad blockers also block Google Analytics. Analytics software such as Google Analytics is there to help users - not monitor or track them per se. We use analytics data to improve and optimize our websites. When our analytics software is blocked, we risk making bad or outright wrong decisions. So one important thing to do as an analyst in this landscape of blocking, is to get an idea of how big the problem actually is. And why not use Google Analytics to track how many users are blocking Google Analytics? There are some great articles out there on how to track whether or not your users are blocking ads. But since I don’t have a lot of clients that are serving ads in the first place, I’m actually more interested in how many of my users aren’t being tracked in Analytics.
Related Post: Which Ad Blockers are blocking Google Analytics?
Analytics, javascript, PHP & Measurement Protocol
So, some ad blockers will outright block any calls to the Google Analytics servers, preventing your website from downloading the analytics.js library at all. Some blockers are a bit more clever (or annoying) and will alter the ga object rendering methods such as ga.create useless. It really doesn’t matter - in my eyes - how they do it. I just care about it happening in the first place. And as an analyst, we also have to respect the choices of our users - so I won’t be trying to collect data in another way - I simply want to track how many users are blocking Google Analytics. Luckily, I know my way around javascript and PHP. I’m no programmer at all, but I’m fairly experienced anyway. So the approach I chose goes like this:
- Use javascript to detect if Google Analytics is loaded
- If not post a hit using PHP to Google Analytics via the Measurement Protocol
1. Is Google Analytics blocked?
First off, I used this javascript to check if Google Analytics is being blocked by the user’s browser:
window.addEventListener("load", function() { if(window.ga && ga.create) { console.log("GA loaded."); } else { var img = document.createElement("img"); img.setAttribute("style","width:0px;height:0px;display:none;"); img.src = "/ping.php"; document.body.appendChild(img); } }, false);
I’m not enough of a javascript wizard to guarantee that this is foolproof, but it should do the job in most cases (please comment if you have a better solution!). Basically, this script executes when the page has finished loading (including scripts such as Google Analytics). So when the page has loaded, we are checking if the ga object is present and if there is a create method inside the ga object. If not (else), we will load an invisible 0x0 pixel image and insert that into the HTML document. Now, this doesn’t do anything other than loading an image. So the magic mostly happens “inside” that image. Because - as you might have guessed - that image is not really an image, but rather a PHP script. It will indeed return an image to the browser, but not without posting a hit to the Measurement Protocol ;-)
2. Do the PHP dance with Measurement Protocol
If you’re not familiar with PHP, this will not make much sense - unless you’re familiar with server side programming, in which case you might get the gist. Anyway, before sending anything to Google Analytics, we need to have a couple of things in place first:
header("Content-Type: image/gif"); echo "\x47\x49\x46\x38\x37\x61\x1\x0\x1\x0\x80\x0\x0\xfc\x6a\x6c\x0\x0\x0\x2c\x0\x0\x0\x0\x1\x0\x1\x0\x0\x2\x2\x44\x1\x0\x3b";
This is the first couple of lines in my ping.php file that just make sure to return a transparent 1x1 pixel gif. It doesn’t do anything. This is a bit more interestering though:
function uuid() { return sprintf( "%04x%04x-%04x-%04x-%04x-%04x%04x%04x", mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0x0fff ) | 0x4000, mt_rand( 0, 0x3fff ) | 0x8000, mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ) ); }
I grabbed this PHP function from Dave Meindl over at Mudd.com. It’s a neat little function to generate a unique Client ID which is needed to send data to Analytics through the Measurement Protocol. And now for the really interesting part:
$data = array( "v" => "1", "t" => "event", "tid" => "UA-XXXXXXXX-X", "cid" => uuid(), "ds" => "web", "ni" => "0", "ec" => "Measurement Protocol", "ea" => "Hit", "el" => "Analytics Blocked" ); $content = http_build_query($data); $content = utf8_encode($content);
This bit of code prepares the payload - i.e. the data that we want to send to Google Analytics in case Analytics has been blocked. In this example, I"m simply sending a non-interaction (ni = 0) event (t = event). But you can send any type of hit; the Measurement Protocol parameter reference is a great place to start reading if you want to know more about how to send data this way. So the only thing that remains is to post the data to Measurement Protocol. Using the cURL extension for PHP (which is enabled by default in most cases), we can post the data like so:
$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "http://www.google-analytics.com/collect"); curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: application/x-www-form-urlencoded")); curl_setopt($ch, CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1); curl_setopt($ch, CURLOPT_POST, TRUE); curl_setopt($ch, CURLOPT_POSTFIELDS, $content); curl_exec($ch); curl_close($ch);
And that’s it. The hit has been sent to Analytics and will appear in the Top Events Report - and you can even see the hits in the Real Time reports too!
Disclaimer!
As I mentioned earlier, I’m no javascript and PHP expert - so there are most likely better ways of doing this. Also, this PHP script simply tracks a hit every time a page is loaded without Google Analytics being present. So naturally, if your tracking code is missing from a page, you’ll record an event. Another thing to note is that this will fire multiple times per session. And as of now, it will send a new Client ID every time. So if putting it into production, I’d suggest to either limit the number of hits sent to one, or store the generated Client ID to make sure to use the same Client ID for hits for the same user.
Improve it!
Please: If you have other or better ways of tracking the number of users that are blocking Google Analytics, please let me know in the comments or by sending me an email.