Skip to main content

Event Tracking

GameAnalytics features the following event types:

EventDescription
AdAds shown and clicked, fill rate.
BusinessIn-App Purchases supporting receipt validation on GA servers.
DesignSubmit custom event id’s. Useful for tracking metrics specifically needed for your game.
ErrorSubmit exception stack traces or custom error messages.
HealthAutomatically submits health metrics related to your game such as FPS.
ImpressionImpression data from different ad networks
ProgressionLevel attempts with Start, Fail & Complete event.
ResourceManaging the flow of virtual currencies - like gems or lives
tip

Read more about events here

Event ids are strings separated by colons defining an event hierarchy – like “kill:robot:large”.

danger

A bad implementation example. [level_name]:[weapon_used]:[damage_done] level_name could be 100 values, weapon_used could be 300 values and damage_done could be 1-5000 perhaps. This will generate an event hierarchy with: 100 * 300 * 5000 = 150M possible nodes. This is far too many. Also the damage should be put as a value and not in the event string. The processing will perhaps be blocked for a game doing this and cause other problems when browsing our tool. The maximum amount of unique nodes generated should be around 10k.

It is important to not generate an excessive amount of unique nodes possible in the event hierarchy tree.

Business

Business events are used to track (and validate) real-money transactions.

Many games are hacked and distributed illegally. Hacking an app will often involve faking/simulating all purchase requests. This will result in several Business events being sent to GameAnalytics for transactions that never occurred.

GameAnalytics provide the option of receipt validation for each purchase sent to GA servers. This process can ensure that revenue metrics reflect the actual spending in your game.

Some configuration is needed before receipt validation will be active.

tip

Read information about validation and requirements for different platforms here.

Getting receipts

To get receipts from In-App purchases in Android and iOS please look this integration guide and especially look here as you need the IAP receipts to send with your business events. Android

Android Receipt

When submitting a Business Event supply the following from the IAP procedure:

  • receipt (INAPP_PURCHASE_DATA)
  • signature (INAPP_DATA_SIGNATURE)
tip

Read more about retrieving these needed fields at the Google documentation here.

Add a business event when an in-app purchase is completed (Google Play Store only supported at the moment).

// iOS - with validation
GameAnalytics.addBusinessEvent({
"currency": "USD",
"amount": 99,
"itemType": "weapons",
"itemId": "shotgun",
"cartType": "end_of_level"
});

// Android - with validation
GameAnalytics.addBusinessEvent({
"currency": "USD",
"amount": 99,
"itemType": "weapons",
"itemId": "shotgun",
"cartType": "end_of_level",
"receipt": "test_receipt",
"signature": "test_signature"
});

FieldTypeDescriptionExample
currencystringCurrency code in ISO 4217 format.USD
amountintegerAmount in cents.99 is 0.99$
itemTypestringThe type / category of the item.GoldPacks
itemIdstringSpecific item bought.1000GoldPack
cartTypestringThe game location of the purchase. Max 10 unique values.EndOfLevel
receiptbase64 stringThe transaction receipt. Null allowed.null
signaturebase64 stringThe transaction receipt signature. Null allowed.null
caution

If the receipt/signature is null (or is an invalid receipt) then it will be submitted to the GA server but will register as not validated.

info

The encoding of the receipt will be done by the GameAnalytics native Android library.

iOS receipt

FieldTypeDescriptionExample
currencystringCurrency code in ISO 4217 format.USD
amountintegerAmount in cents.99 is 0.99$
itemTypestringThe type / category of the item.GoldPacks
itemIdstringSpecific item bought.1000GoldPack
cartTypestringThe game location of the purchase. Max 10 unique values.EndOfLevel
receiptbase64 stringThe transaction receipt. Null allowed.null
caution

If the receipt is null (or is an invalid receipt) then the GA servers will register that amount as not validated. Business event with auto fetch receipt (iOS7+)

Custom Event Fields

It is possible to use a set of key-value pairs to add extra fields but it will only be available through raw data export. Here is an example of how to use it:

var fields = new Map();
fields["test"] = 100;
fields["test_2"] = "hello_world";

GameAnalytics.addBusinessEvent({ "currency": "USD", "amount": 99, "itemType": "weapons", "itemId": "shotgun", "cartType": "end_of_level", "receipt": "test_receipt", "signature": "test_signature", "customFields": jsonEncode(fields) });

Ad Events

The GameAnalytics ad event needs to be called when certain events happen for the implemented ad sdk’s. An ad sdk has callback methods activating code when certain things are activated (like ad show or ad clicked).

To use the ad event it is need to call the GameAnalytics SDK when these delegates are called.

Rewarded Videos

Showing a rewarded video

If a rewarded video has failed to be shown due to some reason, you can track this by using the following method:

if (rewardedVideoAd != null && rewardedVideoAd.isLoaded())
{
// ...show ad
}
else
{
GameAnalytics.addAdEvent({
"adAction": EGAAdAction.FailedShow,
"adType": EGAAdType.RewardedVideo,
"adSdkName": "admob",
"adPlacement": "[AD_PLACEMENT_OR_UNIT_ID]"
});
}
// TRACKING ERRORS
// if you want to track errors then we recommend defining this method
// to map the error message stored earlier in the "latestRewardedVideoError" variable.
function GAAdError getLatestAdError(rror)
{
GameAnalytics.GAAdError result = GameAnalytics.GAAdError.Unknown;

// implementation

return result;
}

Tracking rewards

Once the player has finished watching the video, you can use the following method to register that the reward has been received:

function onRewarded(reward) {
// send ad event - reward recieved
GameAnalytics.addAdEvent({
"adAction": EGAAdAction.RewardReceived,
"adType": EGAAdType.RewardedVideo,
"adSdkName": "admob",
"adPlacement": "[AD_PLACEMENT_OR_UNIT_ID]"
});
}

And subsequently track that the rewarded ad has been closed:

function onRewardedVideoAdClosed() {
if(currentRewardedVideoPlacement != null)
{
GameAnalytics.addAdEvent({
"adAction": EGAAdAction.Show,
"adType": EGAAdType.RewardedVideo,
"adSdkName": "admob",
"adPlacement": "[AD_PLACEMENT_OR_UNIT_ID]"
});
}
}

Interstitials

Showing an Interstitial Ad

If the ad has failed to load or be shown due to some reason, it is recommended to track it using the following method:

if (interstitialAd != null && interstitialAd.isLoaded()) {
interstitialAd.show();
}
else
{
GameAnalytics.addAdEvent({
"adAction": EGAAdAction.FailedShow,
"adType": EGAAdType.Interstitial,
"adSdkName": "admob",
"adPlacement": "[AD_PLACEMENT_OR_UNIT_ID]"
});
}

If the interstitial has been showed succesfully it can be tracked by using the next method:

function onAdOpened() {
// send ad event
GameAnalytics.addAdEvent({
"adAction": EGAAdAction.Show,
"adType": EGAAdType.Interstitial,
"adSdkName": "admob",
"adPlacement": "[AD_PLACEMENT_OR_UNIT_ID]"
});
}

Tracking Interstitial Clicks

You can track if an user has clicked an interstitial ad and has subsequently left the application to visit the advertiser's site with the following method:

function onAdLeftApplication() {
// send ad event
GameAnalytics.addAdEvent({
"adAction": EGAAdAction.Clicked,
"adType": EGAAdType.Interstitial,
"adSdkName": "admob",
"adPlacement": "[AD_PLACEMENT_OR_UNIT_ID]"
});
}

In similiar fashion to rewarded video ads & interstitial ads, you can track if the ad has been shown succesfully or not. The example below will show how you could track this:

function onAdLoaded() {
GameAnalytics.addAdEvent({
"adAction": EGAAdAction.Show,
"adType": EGAAdType.Banner,
"adSdkName": "admob",
"adPlacement": "[AD_PLACEMENT_OR_UNIT_ID]"
});
}

And if the banner has failed to load:

function onAdFailedToLoad(int errorCode) {
// OR .. if you don't want to track errors
GameAnalytics.addAdEvent({
"adAction": EGAAdAction.FailedShow,
"adType": EGAAdType.Banner,
"adSdkName": "admob",
"adPlacement": "[AD_PLACEMENT_OR_UNIT_ID]"
});
}

Track banner clicks

You can track if an user has clicked a banner ad by sending a GAAdAction.Clicked event as shown below:

function onAdOpened() {
// send ad event
GameAnalytics.addAdEvent({
"adAction": EGAAdAction.Clicked,
"adType": EGAAdType.Banner,
"adSdkName": "admob",
"adPlacement": "[AD_PLACEMENT_OR_UNIT_ID]"
});
}

Custom Ad Event Fields

It is possible to use a set of key-value pairs to add extra fields but it will only be available through raw data export. Here is an example of how to use it:

var fields = new Map();
fields["test"] = 100;
fields["test_2"] = "hello_world";

GameAnalytics.addAdEvent({
adAction: EGAAdAction.Clicked,
adType: EGAAdType.Banner,
adSdkName: "admob",
adPlacement: "[AD_PLACEMENT_OR_UNIT_ID]",
customFields: jsonEncode(fields),
});
FieldTypeDescriptionExample
adActionenumA defined enum for ad action (for example clicked).GAAdAction.Clicked
GAAdAction.Show
GAAdAction.FailedShow
GAAdAction.RewardReceived
adTypeenumA defined enum for ad type (for example interstitial).GAAdType.Video
GAAdType.RewardedVideo
GAAdType.Playable
GAAdType.Interstitial
GAAdType.OfferWall
GAAdType.Banner
adSdkNamestringName of the Ad/Ad mediation SDK.admob
adPlacementstringIdentifier of ad in the game or the placement of it.level_complete_ad
adPlacementstringIdentifier of ad in the game or the placement of it.level_complete_ad
durationintOptional. Only used for video ads to track how long the user watched the video for.10
noAdReasonenumOptional. Used to track the reason for not being able to show an ad when needed (for example no fill).GAAdError.Unknown
GAAdError.Offline
GAAdError.NoFill
GAAdError.InternalError
GAAdError.InvalidRequest
GAAdError.UnableToPrecache
tip

For more information on Ad Events go here.

Resource Events

Resource events are used to register the flow of your in-game economy (virtual currencies) – the sink (subtract) and the source (add) for each virtual currency.

caution

Before calling the resource event it is needed to specify what discrete values can be used for currencies and item types in the Configuration phase.

Source (add)

Source (add) gem currency from an in-app purchase.

GameAnalytics.addResourceEvent({
"flowType": EGAResourceFlowType.Source,
"currency": "Gems",
"amount": 400,
"itemType": "IAP",
"itemId": "Coins400"
});

Sink (subtract)

Sink (subtract) example of substracting a Gem currency to buy an item.

GameAnalytics.addResourceEvent({
"flowType": EGAResourceFlowType.Sink,
"currency": "Gems",
"amount": 400,
"itemType": "IAP",
"itemId": "Coins400"
});

Sink (subtract) gem currency to source (buy) some amount of another virtual currency.

GameAnalytics.addResourceEvent({
"flowType": EGAResourceFlowType.Sink,
"currency": "Gems",
"amount": 100,
"itemType": "Boosters",
"itemId": "BeamBooster5Pack"
});
GameAnalytics.addResourceEvent({
"flowType": EGAResourceFlowType.Source,
"currency": "BeamBooster",
"amount": 5,
"itemType": "Gems",
"itemId": "BeamBooster5Pack"
});

Custom Resource Event Fields

It is possible to use a set of key-value pairs to add extra fields but it will only be available through raw data export. Here is an example of how to use it:

var fields = new Map();
fields["test"] = 100;
fields["test_2"] = "hello_world";

GameAnalytics.addResourceEvent({ "flowType": EGAResourceFlowType.Sink, "currency": "BeamBooster", "amount": 3, "itemType": "Gameplay", "itemId": "BeamBooster5Pack", "customFields": jsonEncode(fields) });
FieldTypeRequiredDescription
flowTypeenumyesAdd (source) or subtract (sink) resource.
currencystringyesOne of the available currencies set in GA_Settings (Setup tab).This string can only contain [A-Za-z] characters.
amountfloatyesAmount sourced or sunk.
itemTypestringyesOne of the available item types set in GA_Settings (Setup tab).
itemIdstringyesItem id (string max length = 32)

danger

Be careful to not call the resource event too often! In a game where the user collect coins fairly fast you should not call a Source event on each pickup. Instead you should count the coins and send a single Source event when the user either complete or fail the level.


tip

For more information on Resource Events go here.

Progression Events

Progression events are used to track attempts at completing some part of a game (level, area). A defined area follow a 3 tier hierarchy structure (could be world:stage:level) to indicate what part of the game the player is trying to complete.

When a player is starting a progression attempt a start event should be added.

When the player then finishes the attempt a fail or complete event should be added along with a score if needed.

Add a progression start event.

GameAnalytics.addProgressionEvent({
"progressionStatus": EGAProgressionStatus.Start,
"progression01": "world01",
"progression02": "stage01",
"progression03": "level01"
});

It is not required to use all 3 if your game does not have them:

  • progression01
  • progression01 and progression02
  • progression01 and progression02 and progression03

Custom Progression Event Fields

It is possible to use a set of key-value pairs to add extra fields but it will only be available through raw data export. Here is an example of how to use it:

var fields = new Map();
fields["test"] = 100;
fields["test_2"] = "hello_world";

GameAnalytics.addProgressionEvent({ "progressionStatus": EGAProgressionStatus.Start, "progression01": "world01", "progression02": "stage01", "progression03": "level01", "customFields": jsonEncode(fields) });
FieldTypeRequiredDescription
progressionStatusenumyesStatus of added progression (start, complete, fail).
progression01stringyes1st progression (e.g. world01).
progression02stringno2nd progression (e.g. level01).
progression03stringno3rd progression (e.g. phase01).
scoreintnoThe player’s score.
tip

For more information Progression Events go here.

Error Events

Error events are used to track errors in the game code. You can group the events by severity level and attach a message.

To add a custom error event call the following function:

GameAnalytics.addErrorEvent({
"severity": EGAErrorSeverity.Critical,
"message": "Something went bad!"
});

Custom Error Event Fields

It is possible to use a set of key-value pairs to add extra fields but it will only be available through raw data export. Here is an example of how to use it:

var fields = new Map();
fields["test"] = 100;
fields["test_2"] = "hello_world";

GameAnalytics.addErrorEvent({ "severity": EGAErrorSeverity.Critical, "message": "Something went bad!", "customFields": jsonEncode(fields) });
tip

For more information on custom event fields & raw export go here.

FieldTypeDescriptionExample
severityenumSeverity of errorEGAErrorSeverity.Debug
EGAErrorSeverity.Info
EGAErrorSeverity.Warning
EGAErrorSeverity.Error
EGAErrorSeverity.Critical
messagestringError message (can be null)“Error when entering level12”
tip

For more information on Error Events go here.

Design Events

Every game is special. Therefore some tracking needs might not be covered by our other event types. The design event is available for you to add your own event-id hierarchy.

Please note that custom dimensions and progression filters will not be added on design and error events. Therefore you cannot (at the moment) filter by these when viewing design or error metrics.

GameAnalytics.addDesignEvent({
"eventId": "Kill:Sword:Robot"
})

It is also possible to add a float value to the event. This will (in addition to count) make the mean and sum aggregation available in the tool.

GameAnalytics.addDesignEvent({
"eventId": "BossFights:FireLord:KillTimeUsed",
"value": 234
})
FieldTypeDescriptionExample
eventIdstringThe eventId is a hierarchy string that can consist of 1-5 segments separated by ‘:’. Each segment can have a max length of 32.“StartGame:ClassLevel1_5”, “StartGame:ClassLevel6_10
valuefloatA float event tied to the eventId. Will result in sum & mean values being available.34.5
danger

It is important to not generate an excessive amount of unique nodes possible in the event hierarchy tree.

A bad implementation example: [level_name]:[weapon_used]:[damage_done], level_name could be 100 values, weapon_used could be 300 values and damage_done could be 1-5000 perhaps. This will generate an event hierarchy with: 100 * 300 * 5000 = 1.5M possible nodes.

This is far too many. Also the damage should be put as a value and not in the event string. The processing will perhaps be blocked for a game doing this and cause other problems when browsing our tool.

The maximum amount of unique nodes generated should be around 10k.

tip

For more information on Design Events go here.