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.

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.

Cross-domain scripting

Unity Player 3 tightened up the security model to match the same-origin policy of Adobe Flash Player. Basically if you request information from a different domain to the one where the .unity3d file is hosted, the owner of that domain has to explicitly allow it using a file called crossdomain.xml. You’d imagine that would prevent the analytics from working, but it’s not affected.

With this technique the sequence of events is:

The app makes a Javascript call to the enclosing page.

Google’s Javascript snippet rolls up all the event data into a query string, then requests a GIF image from their servers with the query string in the URL.

Google’s server logs the information in the query string, and sends back an empty GIF which is discarded by the client.

Cross-domain restrictions apply to the request of the GIF, but luckily it’s the web browser making the request, not Unity. Loading an image in the browser isn’t subject to Javascript’s same origin policy. It works just as if you were hot-linking the image at Google.

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.

Like this:

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?

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’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.

In the case of time tracking, the length of time would go in ‘Value’ parameter.

Google’s analysis system can also analyse the time between calls to _trackPageview(), although using that approach in a Unity game would require faking the page address to something meaningful, and I have no idea how to do that.

i will try that will see what happens.I was using the timetraker function mentioned in the google docs but looks like its recording something but not time stuff.Will try the above way and see what happens.

Is there any way of get analytic data back into my game so I can make the game chaneg acordingly?. For example, if google traces that I have had 10000 people die in the last 10 minutes because they stepped on the landmine in level 1, then my game reads this and de-activates the landmine…(the game is obviously too hard at this stage.)
I imagine (apart from my terrible example) there could be some really great uses for this!

Yeah, manually updating the software is one thing, but automatic updates are what I’m after. The software recieves anayltic data and is preprogrammed to respond and adjust itself according to that data…

I wrote this article 2 years ago; if you’re looking for Unity analytics today, you should also consider Playtomic (http://playtomic.com/). They’ve got an actual Unity client, and it’s generally more suited for games.

Google’s new Universal Analytics has a “measurement protocol” specification, and the above package uses that to send hits to analytics. The advantage here is that there’s no need for native library for each platform. So the same code actually works on mobile, desktop and web player platforms (Desktop – Windows, OSX, Linux, Windows8; Mobile – iOS, Android, Windows Phone 8, BlackBerry 10; Browser – Unity Web Player plugin). It’s implemented in pure C# and uses Unity’s WWW class for networking.