As a game developer I’m terribly jealous of the data-gathering schemes that companies like Valve and Bungie have going. Take Valve for example: they have detailed stats of where players get killed in their games. This is invaluable stuff for creating a consistent level of difficulty. I decided that I wanted a system like this of my own.
I started designing a database and looking at server-side programming languages. After I’d been working on this for a couple of days, I thought “logging events and aggregating statistics is incredibly common, someone must’ve done this already. If only I could use their code…”
Then I realised, Google Analytics. Duh!
Google Analytics logs web traffic numbers and gives you a nice user interface for slicing and dicing the data. Not only had they already written the server code, they also run the server for you! It’s free for the first 5 million page-views per month. I’d been reinventing the wheel.
All I had to do was trick Google, by feeding them a special fake page view whenever a player dies. I soon discovered that Google was way ahead of me. They already have an API for tracking ‘events’ that happen on a page. People seem to mostly use these for integrating e-commerce sale figures into their web traffic reports, but it’s equally suitable for tracking in-game events.
Setting Up
If you sign up for Google Analytics and put their Javascript snippet in the page with the game, you’re all set. You’ll need your own domain name, or a subdomain at the least to sign up.
Here’s the code you need to run in Unity whenever something happens:
Application.ExternalCall("pageTracker._trackEvent", new object[] { category, action, label, value} );
Um, that’s all of it. This is a non-blocking call to run a Javascript function in the page that holds the Unity Player. I haven’t investigated triggering events from a standalone app yet.
The line above will work with the standard Javascript that Google hand out upon signing up. Note that you won’t be able to test it locally – it needs to run on a page hosted at your domain. If you run it locally, you’ll get an error in the Javascript console saying ‘O not defined’.
Data Model
By now you’re probably wondering what the 4 parameters are to our function call:
- Category. This is a free-form string used to categorise your events. It’s the highest level of organisation applied to your events. I’ve been storing a concatenation of the game name, version number and level ID in here.
- Action. Another free-form string which represents the type of event. I’ve been using actions such as “killed” and “game_start”.
- Label. This is an optional string parameter to the action. For example, the killed action uses the label to store the cause of death.
- Value. This is an optional fractional number parameter to the action. For example, I keep the length of the game session in here when I send the ‘game_end’ action.
Analysis
So what’s all this look like from inside Google Analytics? It’s a batch processing system, so first you need to wait overnight for your data to come through. Next, log in, pick your site and select ‘Event Tracking’.

You’ll see a hierarchy of categories and actions, like so:

Yes, those are real numbers. Some day I’ll get around to promoting this site.
If I want a breakdown of causes of death in Glob Arena, I hit the ‘killed’ link and get this moneyshot:

Glorious.
Limitations
Thankfully, collecting personally identifiable information via Google Analytics is not allowed. Not only is it a sleazy thing to do to your customers, it’ll get your account banned.
This means that you’ll only get aggregate information on player behaviour. You can split the statistics up into sub-populations using the Advanced Segments tool, but it won’t ever show you a log of some individual’s actions. Google Analytics is no substitute for asking someone to test your game, while you look over their shoulder.
Home Page
Nice article!
I think I’m doing everything right, and I see the traffic in GA.. but I’m not seeing the actual events.. any ideas? Is there like a minimum amount of events that need to be received before they are displayed, to prevent personally identifiable information?
Didn’t check the unity webplayer log yet tho, might do that.
The javascript console log in your web browser would be good to check too. That’ll tell you whether the call to the GA page tracker is going OK or not.
There’s no minimum of the amount of data. I was getting events listed as soon as I got pageviews listed.
One thing that I should’ve mentioned in the article is that the _trackEvent call has 3 variations:
– _trackEvent(category, action, label)
– _trackEvent(category, action, value)
– _trackEvent(category, action, label, value)
A call like _trackEvent(category, action, null, value), won’t work.
Maybe I didn’t implement it correctly in my html.
This is what I get when trying to evaluate something similar in the firefox “error console”:
Error: pageTracker is not defined
Source File: javascript:%20pageTracker._trackEvent(“Test”,%20″test”,%20″foo”,%205);
Line: 1
I don’t think that Evaluate field evaluates the expression in the scope of any particular page. Running the snippet from there doesn’t work on my pages either. I was suggesting looking at the javascript error list after the embedded Unity has sent events.
If you want to test the JS without anything else getting in the way, Google’s documentation suggests dumping it in an OnClick handler. They’ve got an example here:
http://code.google.com/intl/en-US/apis/analytics/docs/tracking/eventTrackerGuide.html
If you’re getting pageviews through, I kinda doubt the problem is in the page. That indicates that at least pageTracker._trackPageview() is running. The worst that could happen would be Unity trying to send events before the browser has received the part of the page with the GA code. I’ve never seen that happen though, I’ve only been sending events in response to user input.