Analytics, Level sharing, Leaderboards and more for Flash ActionScript 2 casual and social games.
Download it: playtomic-as2-3.16.zip, or get it from GitHub
Unzip that file so that the Playtomic folder is in the same folder as your game FLA.
Import the Playtomic classes into any of your ActionScript files or code sections that will use them:
import Playtomic.*;
A view occurs when someone loads the game in any way. Begin by registering the view early in your game. You must log the view before anything else to initialize the Playtomic API.
Playtomic.Log.View(gameid, "guid", _root._url);
Check the API page for your game in the dashboard to get your codes. Remember to encrypt your game with something like Kindisoft to protect your game.
A view occurs whenever somebody views your game. This should go somewhere very early in your code like before the preloader.
Because the View method initializes the entire Playtomic API it has several parameters that must be passed, and it must be called before you can log anything else.
Playtomic.Log.View(xxx, "xxxxxxxxxxxx", root.loaderInfo.loaderURL);
A play occurs when someone begins a game by clicking your play button or whatever action is relevant to your game. A person can get between 0 and many plays during a single view.
They're tracked seperately because the main menu is the first thing the player sees after loading and splash animations, and if they don't like it they'll leave.
This data is logged automatically when you send other events.
import Playtomic.*; PlayButton.onPress = function():Void { Playtomic.Log.Play(); // continue starting game ...
Events are sent in batches each time the play timer updates (every 30 seconds after the first minute). If you want to ensure an event gets sent:
Playtomic.Log.ForceSend();
Some games are very resource-intensive and the API might send off a batch of events at exactly the wrong time. You can freeze and unfreeze the logging at any time by:
Playtomic.Log.Freeze(); Playtomic.Log.UnFreeze();
When logging is frozen all events are queued but not sent until you unfreeze the API.
Custom metrics allow you to track how many people do something in your game, for instance how many play on easy, medium or hard, or how many play in English vs. Spanish, or how many view the tutorial or skip it. Anything you think can help you improve your game.
You can define custom metrics directly in your game and they will be added to Playtomic automatically. Groups can be automatically assigned via an optional second parameter or set up later in the dashboard.
You can also limit custom metrics to unique-per-view occurances with a third parameter.
Playtomic.Log.CustomMetric("ViewedCredits"); // metric, names must be alphanumeric Playtomic.Log.CustomMetric("Credits", "Screens"); // metric with group, groups must be alphanumeric Playtomic.Log.CustomMetric("ClickedSponsorsLink", "Links", true); // unique metric with group
Level metrics track events on a per-level basis so you can drill down into your difficulty and retention by identifying which levels have problems and what those problems are.
There are three types of level metrics - counters (like custom metrics), ranged-value and average-value.
Note that you can pass either an integer level number or a string name of the level. If your game is not using numeric levels (eg an escape game) then you would pass the name of each screen / area as a level.
You can define level metrics directly in your game and they will be added to Playtomic automatically.
Level metrics support unique-per-play occurrances via an optional second parameter. If the player starts a new game they will be tracked again.
These metrics track how many times something occurs in your levels, for instance deaths and restarts.
One of the most valuable pieces of data you can track is how many people begin each level, this allows you to see where you lose players.
Playtomic.Log.LevelCounterMetric("Deaths", level_number); // names must be alphanumeric Playtomic.Log.LevelCounterMetric("Restarts", "LevelName"); // level names must be alphanumeric Playtomic.Log.LevelCounterMetric("Restarts", "LevelName", true); // unique only
These metrics track the average of something in your levels, for instance the average time to finish a level or the average number of retries. It also tracks the minimum and maximums.
Playtomic.Log.LevelAverageMetric("Time", level_number, seconds); Playtomic.Log.LevelAverageMetric("Retries", level_number, retries); Playtomic.Log.LevelAverageMetric("Retries", level_number, retries, true); // unique only
These metrics track metrics with values, for instance in a golf game you might track how many shots it takes to complete each level, or you might track the % of coins collected on each level.
Playtomic.Log.LevelRangedMetric("Shots", level_number, shots); Playtomic.Log.LevelRangedMetric("PercentCoinsCollected", level_number, int(coins / coinstotal * 100)); Playtomic.Log.LevelRangedMetric("Shots", level_number, shots, true); // unique only
Heatmaps allow you to map activity (clicks, deaths, first deaths, or anything else you want) against an image you upload in the dashboard.
Playtomic.Log.Heatmap("Metric", "Heatmap", x, y);
In the dashboard you upload a background image for the heatmap, and then it is shared by any metrics using it.
Link tracking allows you to keep track of how many people open URLs in your game, providing you information on unique, total and failed clicks that can fully audited to allow you to identify good sources of traffic and sites that block links.
Link tracking does not change your URL or redirect traffic through a different url!
You track a link by passing a URL and some other information to the API. The API will return true or false if the link opens, everything else is automatic.
Playtomic.Link.Open(url:String, name:String, group:String):Boolean
Playtomic.Link.Open("http://website.com/?gameref=my_game", "PlayMoreGames", "Sponsor");
When you track a link it automatically also tracks the totals for the domain in a group it creates called DomainTotals. The DomainTotals allows you to see how many unique, total and failed clicks occurred for a single domain even if you have multiple, different links to it (eg walkthrough or differently-structured sponsor links).
The level sharing API provides a way to store and retrieve user-generated content for your game. It can operate anonymously or authenticated via any 3rd party service you're already using.
Saving and listing levels uses this class to represent a level.
| Property | Type | Description |
|---|---|---|
| PlayerName | String | The name of the player (or "anonymous", "guest", etc), or the name provided by any 3rd party API. |
| PlayerId | String | If you're working under a 3rd party API you can include the player's user id |
| PlayerSource | String | If you're working under a 3rd party API you can specify which, eg "gamersafe" or "mochicoins" |
| Name | String | The name of the level |
| Data | String | The data for the level. |
| Votes | int | The number of votes the level has |
| Score | int | The sum of all votes the level has |
| Plays | int | The number of plays the level has |
| Rating | int | The rating the level has (score / votes) |
| SDate | Date | The date of the level, determined automatically by Playtomic |
| RDate | String | The relative date of the level eg "7 minutes ago", determined automatically by Playtomic |
| CustomData | Object | Any additional data you want to (or have) attached to a level. |
Playtomic.PlayerLevels.Save(level:PlayerLevel, callback:Function)
| Parameter | Type | Description |
|---|---|---|
| level | PlayerLevel | An instance of PlayerLevel holding the level data |
| callback | Function | Optional function to pass the submission result to |
Example saving level:
savebutton.onPress = function():Void { var level:PlayerLevel = new PlayerLevel(); level.Name = "My level"; level.Data = level_data; // level data is a string and can be up to about 3 megabytes Playtomic.PlayerLevels.Save(level, this.SaveComplete); } function SaveComplete(level:PlayerLevel, response:Object):Void { if(response.Success) { trace("Level saved successfully, the level parameter is ready for use!"); } else { // failed because of response.ErrorCode } }
Levels can be rated 1 - 10 by players. Rating can be done anonymously with some protection against repeat voting, or bound to PlayerIds if you specify them.
Playtomic.PlayerLevels.Rate(levelid:String, rating:int, callback:Function)
| Parameter | Type | Description |
|---|---|---|
| levelid | String | a_player_level.LevelId |
| rating | int | 1 - 10 |
| callback | Function | Optional function to pass the submission result to |
Example rating level:
ratebutton.onPress = function():Void { Playtomic.PlayerLevels.Rate(currentlevel.LevelId, rating_amount, this.RateComplete); } function RateComplete(response:Object):Void { if(response.Success) { trace("Rating complete""); } else { // Rating failed because of response.ErrorCode } }
Listing levels can be done by popular or newest, with optional filtering by date ranges and/or custom data.
Playtomic.PlayerLevels.List(callback:Function, options:Object)
| Parameter | Type | Description |
|---|---|---|
| callback | Function | Function to pass the levels to |
| options | Object | Optional object which may contain these properties:
|
An example listing levels:
listbutton.onPress = function():Void { Playtomic.PlayerLevels.List(this.ListLoaded, {mode: "newest", customfilters: {difficulty: "hard"}}); } function ListLoaded(levels:Array, numlevels:int, response:Object):Void { if(response.Success) { for(var i:int=0; i<levels.length; i++) { trace(" - " + levels[i].LevelId + ": " + levels[i].Name); } } else { // Level list failed to load because of response.ErrorCode } }
If you do not include the data when you load lists of levels then you can request it seperately:
Playtomic.PlayerLevels.Load(levelid:String, callback:Function)
| Parameter | Type | Description |
|---|---|---|
| levelid | String | a_player_level.LevelId |
| callback | Function | Function to pass the level to |
An example loading a single level
loadbutton.onPress = function():Void { Playtomic.PlayerLevels.Load(level.LevelId, this.LoadComplete); } function LoadComplete(level:PlayerLevel, response:Object):Void { if(response.Success) { trace("Level has been loaded, now you can begin playing it"); } else { // level failed to load because of response.ErrorCode } }
The Leaderboards API gives you very flexible high and low score leaderboards. They can be created in your game dynamically or set up in the edit leaderboards page.
The scores code includes basic protection from cheating but you should also include options like Mochi Digits to protect values in-memory.
The leaderboards use the PlayerScore class for representing the players' scores.
| Property | Type | Description |
|---|---|---|
| Name | String | The player name. This can be by the player or provided by any 3rd party |
| FBUserId | String | If you're working with Facebook scores specify the player's user id |
| Points | Number | The player's score |
| Website | String | The website the score occurred on, determined automatically by Playtomic |
| SDate | Date | The date of the score, determined automatically by Playtomic |
| RDate | String | The relative date of the score eg "7 minutes ago", determined automatically by Playtomic |
| CustomData | Dictionary | Any additional data you want to (or have) attached to a score, like the level the player reached or what character they used |
Score submission is handled by:
Leaderboards.Save(score:PlayerScore, table:String, callback:Function, options:Object);
| Parameter | Type | Description |
|---|---|---|
| score | PlayerScore | An instance of PlayerScore which contains score information |
| table | String | The score table to submit to, alphanumeric |
| callback | Function | Optional function to pass the submission result to |
| options | Object | Optional object which may contain these properties:
|
submitbutton.onPress = function():Void { var simple_score:Playtomic.PlayerScore = new Playtomic.PlayerScore(); simple_score.Name = player_name; simple_score.Points = player_score; // submit to the highest-is-best table "highscores" Playtomic.Leaderboards.Save(simple_score, "highscores"); // submit to the lowest-is-best table "besttimes" Playtomic.Leaderboards.Save(simple_score, "besttimes", null, {highest: false}); // submit an advanced score with custom data and a callback function var advanced_score:Playtomic.PlayerScore = new Playtomic.PlayerScore(); advanced_score.Name = player_name; advanced_score.Points = player_score; advanced_score.CustomData["Character"] = player_character; advanced_score.CustomData["Level"] = current_level; Playtomic.Leaderboards.Save(advanced_score, "highscores", this.SubmitComplete); } function SubmitComplete(score:PlayerScore, response:Object):Void { if(response.Success) { trace("Score saved!"); } else { // submission failed because of response.ErrorCode } }
This allows you to send a new score and return the page the new score is on in the leaderboards, with its appropriate rank:
Leaderboards.SaveAndList(score:PlayerScore, table:String, callback:Function, options:Object);
| Parameter | Type | Description |
|---|---|---|
| score | PlayerScore | An instance of PlayerScore which contains score information |
| table | String | The score table to submit to, alphanumeric |
| callback | Function | Optional function to pass the submission result to |
| options | Object | Optional object which may contain these properties:
|
submitbutton.onPress = function():Void { var simple_score:Playtomic.PlayerScore = new Playtomic.PlayerScore(); simple_score.Name = player_name; simple_score.Points = player_score; // submit to the highest-is-best table "highscores" Playtomic.Leaderboards.Save(simple_score, "highscores"); // submit to the lowest-is-best table "besttimes" Playtomic.Leaderboards.Save(simple_score, "besttimes", null, {highest: false}); // submit an advanced score with custom data and a callback function var advanced_score:Playtomic.PlayerScore = new Playtomic.PlayerScore(); advanced_score.Name = player_name; advanced_score.Points = player_score; advanced_score.CustomData["Character"] = player_character; advanced_score.CustomData["Level"] = current_level; Playtomic.Leaderboards.Save(advanced_score, "highscores", this.SubmitComplete); } function SubmitComplete(score:PlayerScore, response:Object):Void { if(response.Success) { trace("Score saved!"); } else { // submission failed because of response.ErrorCode } }
Scores are loaded via a simple method that returns an array of PlayerScore objects to your function where you can display the data in your leaderboard.
Playtomic.Leaderboards.List(table:String, callback:Function, options:Object);
| Parameter | Type | Description |
|---|---|---|
| table | String | Your leaderboard table name |
| callback | Function | Your function that receives the data |
| options | Object |
Optional object which may contain:
|
showscores.onPress = function():Void { Playtomic.Leaderboards.List("highscores", this.ListComplete); } function ListComplete(scores:Array, numscores:int, response:Object):Void { if(response.Success) { trace(scores.length + " scores returned out of " + numscores); for(var i:int=0; i<scores.length; i++) { var score:PlayerScore = scores[i]; trace(" - " + score.Name + " got " + score.Points + " on " + score.SDate); // including custom data? score.CustomData["property"] } } else { // score listing failed because of response.ErrorCode } }
This is now merged with normal listing. Set the option property facebook to true, and optionally pass an array of the user's friend ids to only show their friends scores.
Scores are no longer available directly via URL as they expect POST data now. You will need to use the HTML5 / JavaScript API for showing scores on your web page, or the Flash or other APIs for embedding them in a SWF or other container.
GameVars let you change the value of key variables in your game any time you want. They must be configured in the edit GameVars page in advance.
It is called via:
Playtomic.GameVars.Load(callback);
The callback parameter is your function that receives an object that has properties matching the variables you have configured here:
// our variables with default, original values var BaseHitPoints:int = 100; var BaseGold:int = 50; function InitialiseGame():Void { // load GameVars Playtomic.GameVars.Load(this.GameVarsLoaded); // carry on initializing your game } function GameVarsLoaded(vars:Object, response:Object):Void { if(response.Success) { // sync the in-game variables this.BaseHitPoints = vars.BaseHitPoints; this.BaseGold = vars.BaseGold; } else { // request failed because of response.ErrorCode } }
The GeoIP service identifies which country the player is from, returning their country code and name.
It is called via:
Playtomic.GeoIP.Lookup(callback);
The callback function receives an object that has Code and Name properties:
function SetPlayerCountry(country:Object, response:Object):Void { if(response.Success) { // we have the country data trace("Player is from " + country.Code + " / " + country.Name); } else { // request failed because of response.ErrorCode } }
Note: You must enable this functionality in each game's settings. By default it is disabled becaue it can expose your game data.
The Data class in the API allows you to retrieve any of your game data to display in your game.
Each function for retrieving data takes an optional parameters object for day, month and year, with default values of 0.
The Views, Plays and PlayTime functions returns this data to you for processing:
Playtomic.Data.Views(callback:Function, options:Object);
| Parameter | Type | Description |
|---|---|---|
| callback | Function | Your function that receives the data |
| options | Object | Optional object which may contain day, month and year properties |
Playtomic.Data.Views(thisOutputData); // views for all time Playtomic.Data.Plays(this.OutputData, {day: 22, month: 3, year: 2010}); // plays on March 22, 2010 Playtomic.Data.PlayTime(this.OutputData, {month: 3, year: 2010}); // play time for March, 2010 function OutputData(data:Object, response:Object):Void { if(response.Success) { // we have the data trace(data.Name + " has value " + data.Value + " for " + data.Month + "/" + data.Day + "/" + data.Year); } else { // request failed because of response.ErrorCode } }
The CustomMetric function returns data about a custom metric to your function, which receives the same parameters as views/plays/play time above.
Playtomic.Data.CustomMetric(name:String, callback:Function, options:Object);
| Parameter | Type | Description |
|---|---|---|
| name | String | The name of your custom metric |
| callback | Function | Your function that receives the data |
| options | Object | Optional object which may contain day, month and year properties |
Playtomic.Data.CustomMetric("Clicked sponsor link", this.OutputData); function OutputData(data:Object, response:Object):Void { if(response.Success) { // we have the data trace(data.Name + " - " + data.Metric + " has value " + data.Value + " for " + data.Month + "/" + data.Day + "/" + data.Year); } else { // request failed because of response.ErrorCode } }
There are three methods for retrieving level metrics. The functions that receive the data are different from the above examples.
Playtomic.Data.LevelCounterMetric(name:String, level:*, callback:Function, options:Object); Playtomic.Data.LevelRangedmetric(name:String, level:*, callback:Function, options:Object); Playtomic.Data.LevelAverageMetric(name:String, level:*, callback:Function, options:Object);
| Parameter | Type | Description |
|---|---|---|
| name | String | The name of your custom metric |
| level | int or String | The level number or name |
| callback | Function | Your function that receives the data |
| options | Object | Optional object which may contain day, month and year properties |
Playtomic.Data.LevelMetricCounter("Started level", level_number, this.OutputLevelCounter); Playtomic.Data.LevelMetricRanged("Shots remaining", level_name, this.OutputLevelRanged, {month: 3, year: 2010}); Playtomic.Data.LevelMetricAveraged("Retries", level_number, this.OutputLevelAverage, {day: 22, month: 3, year: 2010}); function OutputLevelCounter(data:Object, response:Object):Void { if(response.Success) { // we have the data trace(data.Name + " - " + data.Metric + "on level " + data.Level + " has value " + data.Value + " for " + data.Month + "/" + data.Day + "/" + data.Year); } else { // request failed because of response.ErrorCode } } function OutputLevelRanged(data:Object, response:Object):Void { if(response.Success) { // we have the data trace(data.Name + " - " + data.Metric + "on level " + data.Level + " for " + data.Month + "/" + data.Day + "/" + data.Year); for(var i:int=0; i<data.Values; i++) { trace(" - Tracking value " + data[i].Value + " ocurred " + data[i].Occurances + " times"); } } else { // request failed because of response.ErrorCode } } function OutputLevelAverage(data:Object, response:Object):Void { if(response.Success) { // we have the data trace(data.Name + " - " + data.Metric + "on level " + data.Level + " has min " + data.Min + ", max " + data.Max + ", average " + data.Average + " for " + data.Month + "/" + data.Day + "/" + data.Year); } else { // request failed because of response.ErrorCode } }
When a Playtomic service is unreachable or has an error it will return a numeric error code. This table describes those errors:
These errors may be returned from any service.
| Code | Meaning |
|---|---|
| 0 | No error |
| 1 | General error, this typically means the player is unable to connect to the Playtomic servers |
| 2 | Invalid game credentials. Make sure you use your SWFID and GUID from the "API" section in the dashboard. |
| Code | Meaning |
|---|---|
| 100 | GeoIP API has been disabled. This may occur if your game is faulty or overwhelming the Playtomic servers. |
| Code | Meaning |
|---|---|
| 200 | Leaderboard API has been disabled. This may occur if your game is faulty or overwhelming the Playtomic servers. |
| 201 | The source URL or name weren't provided when saving a score. Make sure the player specifies a name and the game is initialized before anything else using the code in the "Set your game up" section. |
| 202 | Invalid auth key. You should not see this normally, players might if they tamper with your game. |
| 203 | No Facebook user id on a score specified as a Facebook submission. |
| 204 | Table name wasn't specified for creating a private leaderboard. |
| 205 | Permalink structure wasn't specified: http://website.com/game/whatever?leaderboard= |
| 206 | Leaderboard id wasn't provided loading a private leaderboard. |
| 207 | Invalid leaderboard id was provided for a private leaderboard. |
| Code | Meaning |
|---|---|
| 300 | GameVars API has been disabled. This may occur if your game is faulty or overwhelming the Playtomic servers. |
| Code | Meaning |
|---|---|
| 400 | Level sharing API has been disabled. This may occur if your game is faulty or overwhelming the Playtomic servers. |
| 401 | Invalid rating value (must be 1 - 10). |
| 402 | Player has already rated that level. |
| 403 | The level name wasn't provided when saving a level. |
| 404 | Invalid image auth. You should not see this normally, players might if they tamper with your game. |
| 405 | Invalid image auth (again). You should not see this normally, players might if they tamper with your game. |
| 406 | The level already exists. This is determined via a hash of the game id, level name, player ip address and name, and source url. |
| Code | Meaning |
|---|---|
| 500 | Data API has been disabled. This may occur if the Data API is not enabled for your game, or your game is faulty or overwhelming the Playtomic servers. |