06
Oct
09

Gathering statistics using Google Analytics and Unity 3D

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

analytics1

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

analytics2

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:

analytics3

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.

About these ads

20 Responses to “Gathering statistics using Google Analytics and Unity 3D”


  1. 1 Magnus
    October 16, 2009 at 9:34 am

    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.

    • October 16, 2009 at 11:48 am

      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.

      • 3 Magnus
        October 17, 2009 at 5:24 am

        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

  2. October 17, 2009 at 8:15 am

    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.

  3. 5 Shweta Gupte
    April 22, 2010 at 8:58 am

    Hi,
    I am trying to do time tracking for a game.How long it take to get to the end of the game or to move a item etc.Could you be able to help me with that?
    Thanks
    Shweta

    • 6 Anonymous
      April 22, 2010 at 7:13 pm

      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.

      • 7 Shweta Gupte
        April 23, 2010 at 3:19 am

        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.

        Thanks for the response

  4. May 23, 2010 at 1:00 pm

    How did I miss this post? This would be interesting experimentation.

  5. August 11, 2010 at 4:20 am

    This is the new async calling formula:

    Application.ExternalCall(“_gaq.push”, “[‘_trackEvent’, ‘” + myCategory + “‘, ‘” + myAction + “‘, ‘” ” myOpt_label + “‘, ” + myOpt_value + “]”);

  6. August 11, 2010 at 5:12 am

    Cool update. I still have to try to implement this myself. Chaotic few weeks!

  7. August 16, 2010 at 8:20 am

    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!

  8. December 1, 2011 at 8:12 am

    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.

  9. December 21, 2013 at 1:32 am

    I hope you don’t mind if I mention my solution for integrating Google Analytics to Unity projects:

    https://www.assetstore.unity3d.com/#/content/11098

    Website: http://strobotnik.com/unity/googleuniversalanalytics/
    Forum thread: http://forum.unity3d.com/threads/202335-Google-Universal-Analytics

    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.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.

Join 59 other followers

%d bloggers like this: