Jump to content

  • Log In with Google      Sign In   
  • Create Account






Gentle introduction to Google Analytics for Flash

Posted by Koshmaar, 28 June 2013 · 1,285 views

google analytics flash as3 tutorial
Being able to check out how many players play your game, from what countries, for how long, on which levels they have problems, even do they ever visit your precious Credits screen - that sounds incredibly useful, doesn't it? Fortunately, in web browser games, there's a way to get such informations. In this post I'm going to describe the process for Flash (ActionScript 3).

And there are even many ways. First, some time ago you could use Playtomic.com - however they had notorious problems with reliability, and are now out of bussiness. Then, the second try could be Mochimedia - they have many services, and one of them is statistics. Unfortunately, it is very simple and unable to give you such detailed data as in the first paragraph. You could also google and find few other services... and among few smaller ones, Google Analytics for Flash project (later shortened to GAF).

That's true - you can use the well known, very powerfull, complex, free, reliable and spied service from Google to process the statistics from your own Flash games. And it's actually pretty easy to use. Sadly, the documentation is rather cryptic, sparse, ambigous and hard to follow. So, here goes a quick, practical tutorial for you + code samples Posted Image

First, download the files from their site and put it some directory like lib/gaf, alongside other game sources and libraries. Inside your IDE link to the one of the .swc files: analytics.swc (codebased IDE like FlashDevelop) or analytics_flash.swc (component for Flash CS). Code snippet from Ninja Cat:
import com.google.analytics.AnalyticsTracker;
import com.google.analytics.GATracker;

CONFIG::stats
{
    public static var tracker:AnalyticsTracker;
}

public static function Stats_StartTracking() : void
{
    CONFIG::stats
    {
        // UA-google-api-code has to be replaced by your code
        // fourth parameter is visual_debug - its described later in post
        tracker = new GATracker( FlxG.stage, "UA-google-api-code", "AS3", false );
        Stats_PageView("Home");
    }
}

public static function Stats_PageView( URL : String ) : void
{
	CONFIG::stats
	{
        // I think google wants to have slashes before names of pages
		tracker.trackPageview( "/" + URL );
	}
}

public static function Stats_LinkOpen( URL : String ) : void
{
	CONFIG::stats
	{
		tracker.trackPageview( "/" + URL );
	}
}

public static function Stats_LevelStart( ) : void
{
	Stats_PageView( "Level_" + current_level );
}

public static function Stats_LevelQuit( ) : void
{
	Stats_PageView( "Quit_" + current_level );
}

public static function Stats_Event( category : String, action : String,
				    label : String = null, value : int = NaN ) : void
{
	CONFIG::stats
	{
		tracker.trackEvent(category, action, label, value );

		trace("GA event: " + category + " | " + action + " = " +
			(isNaN(value) ? "NaN" : value) + " ( " + label + " )" );
	}
}

Before anything: what is CONFIG::stats? It's a way of conditionally including code in AS3 (a kind of #ifdef macrodefinitions for you C++ buffs). It's very useful - by toggling one variable in IDE, you can build a significantly different version of game. So, if CONFIG::stats is not defined, all that is between braces will be ignored. In this case, it might be useful to disable statistics ie. for local testing. Here you can read more about this technique.

So, what I've done here, is estabilished interface for using GAF in my game. I put this code in my Game class, which I'm using as a singleton. Methods like StartTracking, LinkOpen, LevelStart are obvious. But how about PageView() and Event() ?

GAF gives you two ways of tracking user behaviour: page views and events. Pages are like in the web browser - navigation between different URL locations. Events are for user interactions with elements of the page, which don't result in changing of the page - ie. movie controls. With events you can log more informations; pages only log the name of the visited pages.

In case of games, you'd want to use this duo like that: pages are reserved for game states and menu screens (MainMenu, Options, Credits, Level1, StatsScreen), while events are used for detailed statistics about in-game... events (duh). From the code above you can also see that I decided to have LinkOpen and LevelQuit be page views.

So, when you add this kind of code to your game, add the function calls in appropriate places, and turn debug mode on (fourth parameter to GATracker is true), you'll see some debugging info appear:

Posted Image

With this you can quickly confirm that things work as expected.

Here's how Google Analytics looks with the data from Ninja Cat and Zombie Dinosaurs (I cut out only the interesting bits):

Posted Image

What is interesting here, is the incredibly small Bounce rate of 0.03% - it means that 99,97% of users who load the game and see menu, continue to play it. Compare that to Bounce rate of anywhere between 40-70% for normal websites.

Posted Image

Google Analytics has this nice feature of showing some stats in a realtime preview. Wow, at this sunday evening four actual people were playing my game, and from the map below I saw one was from USA, one Germany, one China and one Thailand. For the creator it's humbling Posted Image

Posted Image

Last of screenshots shows the details on which "pages" were viewed the most. We can see ie. that players are not interested in me (Credits) or sponsors (links), and they even very rarely visit Options.

Apart from the dashboard, you can find useful data a bit burried in Content -> Site content -> Content drilldown and Content -> Events -> Overview. I would really recommend to spend few hours reading Google Analytics help, to get a good understanding of the platform (goal completions, funnels, conversions, intelligence events, how to filter, learning UI - there's lots of stuff).

According to Mochimedia, my game so far had around 28k displays of ads - which is almost the same amount as /Main views in Google. So both systems confirm each others reliablity. As for an online flash game, almost 30k (and 1-2k per day) is very small number. I think after maybe 2 months I'm going to write a separate post about how Ninja Cat succeeded in the "internets".

So, coming back to the beginning of post - how about original requirement? I tried to get detailed statistics about player progress - they are displayed after finishing a level. Those are things like number of points, enemies killed, katana kills, how much time (in seconds) did it take to finish it. I also tried logging player name, because I was curious what players will write there Posted Image Here's the code I used:
public static function Stats_LevelEnd(
        level_index : int, level_time : int,
        enemies_killed : int, katana_kills : int, score_points : int,
        total_keystrokes : int, accuracy : int,
        avg_kill_time : int, avg_kill_score : int,
        collected_powerups : int, stars : int, health_loss : int,
        player_name : String,
        _result : int // 1 for died, 2 for won
    ) : void
{
    CONFIG::stats
    {
        var cat : String=Level_" + level_index;

        Stats_Event(cat, "time", null, level_time );

        Stats_Event(cat, "enemies_killed", null, enemies_killed );
        Stats_Event(cat, "katana_kills", null, katana_kills );
        Stats_Event(cat, "score", null, score_points );

        Stats_Event(cat, "keystrokes", null, total_keystrokes );
        Stats_Event(cat, "accuracy", null, accuracy );

        Stats_Event(cat, "avg_kill_time", null, avg_kill_time );
        Stats_Event(cat, "avg_kill_score", null, avg_kill_score );

        Stats_Event(cat, "powerups", null, collected_powerups );
        Stats_Event(cat, "stars", null, stars );
        Stats_Event(cat, "health_loss", null, FlxU.abs(health_loss) );

        Stats_Event(cat, "player_name", player_name );

        Stats_Event(cat, "music_volume", null, int(FlxG.music.volume * 100) );
        Stats_Event(cat, "sound_volume", null, int(FlxG.volume * 100) );

        var result : String =(_result == StatsScreen.FINISHED_LEVEL ? "win" : "lost");

        Stats_Event(cat, "difficulty", result, Game.difficulty );
    }
}

Unfortunately I don't know how to get to the data. I asked about it on both GA support forum and on mailinglist, but nobody answered. I'm not sure if GA just can't display the exact amount that was passed as last parameter, or I can't find a place where its available. So if you know something, please write the comment below. Thanks!

If you still have questions, you may read a similiar, but more thorough (and more oriented towards Flash CS users) tutorial over here, or ask question in comment below.

Btw, this entry has been cross-posted on my blog: www.koshmaar.pl/blog




Thank you for sharing this information. It is great to see an article with so much detail.

Interesting, it never occurred to try using Google Analytics for a Flash game before, but it looks like it does a pretty good job.

 

Thanks for sharing such a good write-up!  We'd love if you also submitted this as an article! :-)

Thanks guys, I only wish I had this kind of article when I was starting to implement statistics :) Actually those kinds of things are rather popular in flash games.

 

Jbadams - cool, why not. Do you think a lot of editing, additions and/or improvements would be needed?

Unless you've found out more information I don't think any real editing or additions are needed -- it's great information, and you've presented it well. :-)

September 2014 »

S M T W T F S
  1 23456
78910111213
14151617181920
21222324252627
282930    

Recent Comments

Latest Visitors

PARTNERS