In our current client project, we are using Google Analytics to track custom events of what users are doing on our website.
To make sure, this is working in the way we expect, we want to write functional tests to check if the events are send to Google Analytics when we expect them.
In this article, I will describe how we created a solution were the events sent are made visible on the website in a ‘debug mode’. They are captured and tested against in our Cucumber Test suite using Capybara and Poltergeist.
Testing Google Analytics Custom Events
Custom Events in Google Anayltics are a great way to enhance your usage statistics by tracking events specific to your website. However, as they are specific to your web page, they require you to write custom logic and call ga.js when done: _gaq.push('_trackEvent', 'Contract', 'scrollToEnd', 'landLine').
This means you will want to test this behaviour. So, let’s assume for this article you want to satisfy a Cucumber behaviour like this (./features/google-analytics.feature):
Feature: Google Analytics Tracking
Scenario: Reading land line contract
Given I am on the "/contracts/land-line" page
And I scroll to the bottom
GA should get an event {"Contract", "scrollToEnd", "landLine"}
So how to test this? We are currently working in Ruby. And there is a Ruby framework called WAAT to help test what is send to Google Analytics. It uses the Ruby Java Bridge and the jpcap library to monitor your HTTP traffic and capture the events send to Google Analytics. While this is working, we didn’t like to use Java and jpcap, especially on our CI and preview boxes.
So we thought of something different: What if we have a ‘debug mode’ where we just print the messages send to Google Analytics to the HTML and read them from Capybara? Turns out is no to hard.
Print Messages send to Google Analytics
When you send any data to Google Analytics, you are using the global variable _gaq and call the push method with an array as argument. To hook into this mechanism, just implement and own push method and replace calls to _gaq.push with your own method:
var Example = Example || {};
Example.Analytics = Example.Analytics || {};
var _gaq = _gaq || [];
Example.Analytics.push = function () {
_gaq.push.apply(_gaq, arguments);
}
Next, add a hidden DIV somewhere to your website and use CSS to style it the way you like (I include my styles in the gist for this blog post).
<div id="google-analytics-debug"></ol></div>
This should be made visible (e.g. with the help of JQuery), when there is a get parameter google-analytics-debug somewhere in the in URL, so for example in http://example.com/contracts/land-line?google-analytics-debug:
Example.Analytics.is_debug = window.location.href.match(/[\?&]google-analytics-debug([&#]|$)/);
$(function () {
if (Example.Analytics.is_debug) {
$("#google-analytics-debug").show();
}
});
And then you can add code to make the message send to Google Analytics appear in the DIV:
Example.Analytics.push = function () {
_gaq.push.apply(_gaq, arguments);
if (Example.Analytics.is_debug) {
var args = arguments[0];
$(function () {
var li = $("<li/>").text(JSON.stringify(args));
$("#google-analytics-debug ol").append(li);
});
}
}
This will add any message send to Google Analytics to the DIV. In my example this looks like this:
Write Cucumber steps with Capybara and Poltergeist
Now we want to automate the testing using the Cucumber BDD framework. To handle the browser part in a headless mode, we use Capybara and Poltergeist/PhantomJS to simulate JavaScript. I assume you have cucumber already running on your project.
To get going, install PhantomJS, add the following gems to your Gemfile and run bundle install:
group :test do gem 'cucumber' gem 'capybara' gem 'poltergeist' gem 'rspec' end
Next add the following lines to ./support/env.rb
require "capybara" require "capybara/cucumber" require 'capybara/poltergeist' require "json" Capybara.app_host= 'localhost:4567' Capybara.default_selector= :css Capybara.default_driver = :poltergeist include Capybara::DSL
Now you can use capybara to read all Google Analytics events pushed. Add a file ./support/google_analytics.rb with the method ga_pushes to extract them from the website:
def ga_pushes
ga_pushes = []
all('#google-analytics-debug li').each do |li|
ga_pushes << JSON.parse(li.text)
end
ga_pushes
end
Finally implement the steps for the cucumber feature above:
Given /^I am on the "([^"]*)" page$/ do |path|
visit "http://localhost:4567/#{path}?google-analytics-debug"
end
When /^I scroll to the bottom$/ do
page.execute_script "window.scrollBy(0,100000)"
end
Then /^GA should get an event {"([^"]*)", "([^"]*)", "([^"]*)"}$/ do |category, action, value|
ga_pushes.should include(["_trackEvent", category, action, value])
end
When you run the Cucumber feature you should see a passing test result.
Discussion
The solution I propose in this article to test Google Analytics Custom Events consists of two parts:
- Making Google Analytics Events visible with JavaScript
- Reading them from Cucumber tests
The underlying assumption of this is, that the ga.js library actually works – which I think you can. The other assumption is, that the first line of your Example::Analytics.push function does work as well. You have to make sure, this is true by code review and by manually testing using the ga_debug.js library or Chrome extension.
A nice benefit of this mechanism is, that you can see what Google Analytics Events are send even when you are doing development or manual testing.
On the down side, because of the get parameter, you have slightly different code in production than development and testing. You have to make your own judgement if you want to make this trade-off.
Another thing we discussed is, that people will be able to actually turn on the debugging in production as well. We don’t see a security issue here, because this will only tell people what they could already know, e.g. when using the Google Analytics Debugger Chrome extension.
All code presented in this article can be found at https://gist.github.com/3600363.


Wow, very cool mix of tech ! I need to try Capybara/Poltegeist/Cucumber
Hi,
I agree the HttpSniffer approach of WAAT (using jpcap) is cumbersome – especially when running tests via CI. Also the other limitation of that approach is that you cannot sniff the requests if the url is using https.
I have recently released a new version of WAAT v1.5.0 (on github and rubygems) that uses a new plugin – JsSniffer. The approach is on similar lines what you mention – however, it does need to change the html of the product at all.
What you need instead is to write a small javascript (you can take the developer’s help if required for it) and execute that javascript in the browser – which will return the url to the test.
This way, the product does NOT need to change just for testing perspective.
You can get more information regarding WAAT and JsSniffer on my blog: http://essenceoftesting.blogspot.in/search/label/waat
Comments / suggestions / feedback most welcome!