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

To send an event, remember to include the namespace GameAnalyticsSDK:

using GameAnalyticsSDK;
info

If you are new to GameAnalytics and our Events, please read our event guide here. You will get the most benefit of GameAnalytics when understanding what and how to track events.


caution

Remember to only send events from main thread as the SDK internally uses some Unity functions which can only be used from main thread.

Business Events

With validation

Receipt validation in Unity is supported for the following stores:

  • App Store (iOS)
  • Google Play Store (Android)
// Android - Google Play
#if (UNITY_ANDROID)
GameAnalytics.NewBusinessEventGooglePlay (string currency, int amount, string itemType, string itemId, string cartType, string receipt, string signature)
#endif

// iOS - with receipt
#if (UNITY_IOS)
GameAnalytics.NewBusinessEventIOS (string currency, int amount, string itemType, string itemId, string cartType, string receipt)
#endif

// iOS - with autoFetchReceipt
#if (UNITY_IOS)
GameAnalytics.NewBusinessEventIOSAutoFetchReceipt (string currency, int amount, string itemType, string itemId, string cartType)
#endif

Without Validation

It is also possible to send business events without validation.

GameAnalytics.NewBusinessEvent (string currency, int amount, string itemType, string itemId, string cartType)
FieldTypeDescriptionExample
currencystringCurrency code in ISO 4217 formatUSD
amountintegerAmount in cents99 is $0.99
itemTypestringThe type/category of the itemGoldPacks
itemIdstringSpecific item bought1000GoldPack
cartTypestringThe game location of the purchase. Max 10 unique valuesEndOfLevel

iOS Only

FieldTypeDescription
receiptbase64 stringThe App Store receipt. Null allowed. Read about App Store receipt here.

Android Only

FieldTypeDescription
receiptstringINAPP_PURCHASE_DATA. Null allowed. Read about Android receipt here
signaturebase64 stringINAPP_DATA_SIGNATURE. Null allowed. Read about Android signature here.

Android Receipt Contents

This json describes the android receipt sent over to GameAnalytics.

{
"orderId": "<order_id>",
"packageName": "<package_name>",
"productId": "<product_id>",
"purchaseTime": 1484080095335,
"purchaseState": 0,
"purchaseToken": "<purchase_token>"
}
info

The receipt assigned to the Android business event method should not be base64 encoded. The GameAnalytics Android library will encode the receipt for you.

iOS with AutoFetchReceipt

The method NewBusinessEventIOSAutoFetchReceipt will attempt to locate the latest receipt in iOS native code and submit the event if found Retrieving Receipts with Unity IAP service

The IStoreController object that you used to initialize the Unity IAP service contains all the products available for purchase declared by you as well as the receipts.

The receipts can be accessed as follows:

private IStoreController controller;
private IExtensionProvider extensions;

//..
public class Receipt {

public string Store;
public string TransactionID;
public string Payload;

public Receipt()
{
Store = TransactionID = Payload = "";
}

public Receipt(string store, string transactionID, string payload)
{
Store = store;
TransactionID = transactionID;
Payload = payload;
}
}

public class PayloadAndroid
{
public string json;
public string signature;

public PayloadAndroid()
{
json = signature = "";
}

public PayloadAndroid(string _json, string _signature)
{
json = _json;
signature = _signature;
}
}

//...
public PurchaseProcessingResult ProcessPurchase (PurchaseEventArgs args)
{
if (String.Equals (args.purchasedProduct.definition.id, kProductIDConsumable, StringComparison.Ordinal)) {
//...
var product = m_StoreController.products.WithID(kProductIDConsumable);
string receipt = product.receipt;
string currency = product.metadata.isoCurrencyCode;
int amount = decimal.ToInt32 (product.metadata.localizedPrice * 100);
#if UNITY_ANDROID
Receipt receiptAndroid = JsonUtility.FromJson<Receipt>(receipt);
PayloadAndroid receiptPayload = JsonUtility.FromJson<PayloadAndroid>(receiptAndroid.Payload);
GameAnalytics.NewBusinessEventGooglePlay(currency, amount, "my_item_type", kProductIDConsumable, "my_cart_type", receiptPayload.json, receiptPayload.signature);
#endif
#if UNITY_IPHONE
Receipt receiptiOS = JsonUtility.FromJson<Receipt> (receipt);
string receiptPayload = receiptiOS.Payload;
GameAnalytics.NewBusinessEventIOS (currency, amount, "my_item_type", kProductIDConsumable, "my_cart_type", receiptPayload);
#endif
}

On iOS you need to send the entire payload while for Android GameAnalytics should receive only the contents of the json field inside the payload. Information about these can be found in the Unity documentation about the receipts.

For parsing the receipt JSON and getting the data listed under the json field we recommend a JSON parser such as JSON Object.

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:

Dictionary<string, object> fields = new Dictionary<string, object>();
fields.put("test", 100);
fields.put("test_2", "hello_world");

GameAnalytics.NewBusinessEventGooglePlay(currency, amount, "my_item_type", kProductIDConsumable, "my_cart_type", receiptPayload.json, receiptPayload.signature, fields);
tip

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

caution

We do not support purchase validation for any of the other platforms listed by Unity IAP (Mac App store or Windows store).


tip

For more information on Business Events go here.

Ad Events

caution

Ad Events are supported only for the Android and iOS! platforms


The GameAnalytics ad event needs to be called when certain ad events have been triggered. Ad SDKs usually have callback methods for certain events (like when showing an ar or when an ad has been clicked).


To use the ad event it is need to call the GameAnalytics SDK when these delegates are called. The examples below describe how to implement this for the following ad-types:

  • rewarded video
  • interstitial
  • bannner

All code examples use AdMob SDK to showcase example usage.

Other ad networks might differ in naming/structure, but the overall process should be applicable to all.

The ad SDK name argument for the ad event needs to be all lower-case with no spaces or underscore used. Here some examples of valid values to use for ad SDK names:

  • admob
  • unityads
  • ironsource
  • applovin

Rewarded Videos

Showing a Rewarded video

It is possible that the ad SDK cannot return an ad for your app. You can track if the rewarded video has failed to show with the following event.

if (this.rewardedAd.IsLoaded()) {
// show the ad
this.rewardedAd.Show();

// send ad event
GameAnalytics.NewAdEvent(GAAdAction.Show, GAAdType.RewardedVideo, "admob", "[AD_PLACEMENT_OR_UNIT_ID]");
}
else
{
GameAnalytics.NewAdEvent(GAAdAction.FailedShow, GAAdType.RewardedVideo, "admob", "[AD_PLACEMENT_OR_UNIT_ID]");
}

Track time spent inside the ad

If you want to track how much time it took the user to watch the ad you can start a timer and keep track of current rewarded video ad when OnAdOpening delegate is called. The following example is a method for how you could handle this.

public void HandleRewardedAdOpening(object sender, EventArgs args)
{
// keep track of current rewarded video ad
currentRewardedVideoPlacement = "[AD_PLACEMENT_OR_UNIT_ID]";
// start timer for this ad identifier
GameAnalytics.StartTimer(currentRewardedVideoPlacement);
}

// when application goes to background (during the display of a rewarded video ad) then the timer needs to stop.
// therefore we need to call code in Unity method OnApplicationPause.
void OnApplicationPause(bool paused) {
if(paused)
{
if(currentRewardedVideoPlacement != null)
{
GameAnalytics.PauseTimer(currentRewardedVideoPlacement);
}
}
else
{
if(currentRewardedVideoPlacement != null)
{
GameAnalytics.ResumeTimer(currentRewardedVideoPlacement);
}
}
}

Track when the ad has finished

It is useful to track when the ad has finished and the user returns to the game. For admob this delegate is called OnAdClosed and the following example is a method for how you could handle this.

public void HandleRewardedAdClosed(object sender, EventArgs args) {
if(currentRewardedVideoPlacement != null)
{
long elapsedTime = GameAnalytics.StopTimer(currentRewardedVideoPlacement);
// send ad event for tracking elapsedTime
GameAnalytics.NewAdEvent(GAAdAction.Show, GAAdType.RewardedVideo, "admob", "[AD_PLACEMENT_OR_UNIT_ID]", elapsedTime);
currentRewardedVideoPlacement = null;

// OR if you do not wish to track time

// send ad event without tracking elapsedTime
GameAnalytics.NewAdEvent(GAAdAction.Show, GAAdType.RewardedVideo, "admob", "[AD_PLACEMENT_OR_UNIT_ID]");
}
}

Interstitials

Showing an Interstitial ad

As in the example for the rewarded video, you can also send an event when the ad has failed to load.

if (this.interstitial.IsLoaded()) {
// show the ad
this.interstitial.Show();
// send ad event
GameAnalytics.NewAdEvent(GAAdAction.Show, GAAdType.Interstitial,"admob", "[AD_PLACEMENT_OR_UNIT_ID]");
}
else
{
GameAnalytics.NewAdEvent(GAAdAction.FailedShow, GAAdType.Interstitial, "admob", "[AD_PLACEMENT_OR_UNIT_ID]");
}
Closing an Interstitial ad

This event should be called when the interstitial ad has been finished. The equivalent for the admob sdk is OnAdLeavingApplication.

public void HandleInterstitialLeftApplication(object sender, EventArgs args) {
// send ad event - ad click
GameAnalytics.NewAdEvent(GAAdAction.Clicked, GAAdType.Interstitial,"admob", "[AD_PLACEMENT_OR_UNIT_ID]");
}

Banners

Showing a Banner Ad

It is possible to track when a banner ad has been loaded by using the following event. For admob this callback would be used when OnAdLoaded is called.

public void HandleAdLoaded(object sender, EventArgs args) {
GameAnalytics.NewAdEvent(GAAdAction.Show, GAAdType.Banner,"admob", "[AD_PLACEMENT_OR_UNIT_ID]");
}

Track banner clicks

If you wish to track when an user is clicking on a banner ad you have to use this event. For admob this should be triggered on OnAdOpening.

public void HandleAdOpened(object sender, EventArgs args) {
// send ad event
GameAnalytics.NewAdEvent(GAAdAction.Clicked, GAAdType.Banner, "admob", "[AD_PLACEMENT_OR_UNIT_ID]");
}

Custom Banner Event Fields

It is possible to append extra information to this event as a map of key-value pairs.

caution

The custom information will only be available through raw data export!

The sample below will show you how to add custom fields:

Dictionary<string, object> fields = new Dictionary<string, object>();
fields.put("test", 100);
fields.put("test_2", "hello_world");

GameAnalytics.NewAdEvent(GAAdAction.Clicked, GAAdType.Banner, "admob", "[AD_PLACEMENT_OR_UNIT_ID], fields");
}
tip

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

Ad Event Info

In the table below you can find all the values supported for ad events.

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

Impression Events

Impression events are used to get impression data from different ad networks. Currently the following ad networks are supported:

  • Fyber
  • IronSource
  • TopOn
  • MAX
  • Aequus
  • AdMob

Fyber

To use impression data from Fyber add the following code inside the Start function and the SDK will then automatically send the impression events for you:

void Start ()
{
// ... code
GameAnalyticsILRD.SubscribeFyberImpressions();
}

IronSource

To use impression data from IronSource add the following code inside the Start function and the SDK will then automatically send the impression events for you:

void Start ()
{
// ... code
GameAnalyticsILRD.SubscribeIronSourceImpressions();
}

TopOn

To use impression data from TopOn add the following code inside the Start function and the SDK will then automatically send the impression events for you:

void Start ()
{
// ... code
GameAnalyticsILRD.SubscribeTopOnImpressions();
}

MAX

To use impression data from MAX add the following code inside the Start function and the SDK will then automatically send the impression events for you:

void Start ()
{
// ... code
GameAnalyticsILRD.SubscribeMaxImpressions();
}

Aequus

To use impression data from Aequus add the following code inside the Start function and the SDK will then automatically send the impression events for you:

void Start ()
{
// ... code
GameAnalyticsILRD.SubscribeAequusImpressions();
}

AdMob

To use impression data from AdMob add the following code for each ad you create and the SDK will then automatically send the impression events for you:

// BannerView
bannerView = new BannerView(adUnitId, AdSize.SmartBanner, AdPosition.Top);
GameAnalyticsILRD.SubscribeAdMobImpressions(adUnitId, bannerView);

// InterstitialAd
interstitialAd = new InterstitialAd(adUnitId);
GameAnalyticsILRD.SubscribeAdMobImpressions(adUnitId, interstitialAd);

// RewardedAd
rewardedAd = new RewardedAd(adUnitId);
GameAnalyticsILRD.SubscribeAdMobImpressions(adUnitId, rewardedAd);

// RewardedInterstitialAd
RewardedInterstitialAd.LoadAd(adUnitId, CreateAdRequest(), (rewardedInterstitialAd, error) =>
{
if(error == null)
{
GameAnalyticsILRD.SubscribeAdMobImpressions(adUnitId, rewardedInterstitialAd);
}
});
tip

For more information on Impression Events go here.

Resource Events

To add a resource event call the following function:

GameAnalytics.NewResourceEvent (GA_Resource.GAResourceFlowType flowType, string currency, float amount, string itemType, string itemId)
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)

caution

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 completes or fails the level.


Here are some examples and best practices for structuring the events:

GameAnalytics.NewResourceEvent(GA_Resource.GAResourceFlowType.GAResourceFlowTypeSource, “Gems”, 400, “IAP”, “Coins400”);

GameAnalytics.NewResourceEvent(GA_Resource.GAResourceFlowType.GAResourceFlowTypeSink, “Gems”, 400, “Weapons”, “SwordOfFire”);

GameAnalytics.NewResourceEvent(GA_Resource.GAResourceFlowType.GAResourceFlowTypeSink, “Gems”, 100, “Boosters”, “BeamBooster5Pack”);

GameAnalytics.NewResourceEvent(GA_Resource.GAResourceFlowType.GAResourceFlowTypeSource, “BeamBooster”, 5, “Gems”, “BeamBooster5Pack”);

GameAnalytics.NewResourceEvent(GA_Resource.GAResourceFlowType.GAResourceFlowTypeSink, “BeamBooster”, 3, “Gameplay”, “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:

Dictionary<string, object> fields = new Dictionary<string, object>();
fields.put("test", 100);
fields.put("test_2", "hello_world");

GameAnalytics.NewResourceEvent(GA_Resource.GAResourceFlowType.GAResourceFlowTypeSink, “BeamBooster”, 3, “Gameplay”, “BeamBooster5Pack”, fields);

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

Progression Events

Progression events are used to track user's progression in the game, for example a new level, high score or dungeon. In the unity sdk you can register such events with the following api:

// Using 1 progression part (01) and no score
GameAnalytics.NewProgressionEvent(GA_Progression.GAProgressionStatus progressionStatus, string progression01)

// Using 1 progression part (01) and score
GameAnalytics.NewProgressionEvent(GA_Progression.GAProgressionStatus progressionStatus, string progression01, int score)

// Using 2 progression parts (01+02) and no score
GameAnalytics.NewProgressionEvent(GA_Progression.GAProgressionStatus progressionStatus, string progression01, string progression02)

// Using 2 progression parts (01+02) and score
GameAnalytics.NewProgressionEvent(GA_Progression.GAProgressionStatus progressionStatus, string progression01, string progression02, int score)

// Using 3 progression parts (01+02+03) and no score
GameAnalytics.NewProgressionEvent(GA_Progression.GAProgressionStatus progressionStatus, string progression01, string progression02, string progression03, int score)

// Using 3 progression parts (01+02+03) and score
GameAnalytics.NewProgressionEvent(GA_Progression.GAProgressionStatus progressionStatus, string progression01, string progression02, string progression03, int score)

The progression event accepts the following parameters:

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.

If you do not need progression02 or progression03 do not make any references to these parameters when calling the method. Below you can learn from an example of progression event that uses only progression01 and progression02:

GameAnalytics.NewProgressionEvent (GAProgressionStatus.Start, "World1");
GameAnalytics.NewProgressionEvent (GAProgressionStatus.Complete, "World1", score);
GameAnalytics.NewProgressionEvent (GAProgressionStatus.Start, "World1", "Level1");
GameAnalytics.NewProgressionEvent (GAProgressionStatus.Complete, "World1", "Level1", score);
GameAnalytics.NewProgressionEvent (GAProgressionStatus.Start, "World1", "Level1", "Phase1");
GameAnalytics.NewProgressionEvent (GAProgressionStatus.Complete, "World1", "Level1", "Phase1", score);

Error Events

To add a custom error event you can call the following function:

GameAnalytics.NewErrorEvent (GAErrorSeverity severity, string message)

The arguments for this event are described below:

FieldTypeRequiredDescriptionExample
severityenumyesSeverity of error (critical, debug, error, info, warning).GAErrorSeverity.Warning
messagestringyesErrormessage (Optional, can be null).

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:

Dictionary<string, object> fields = new Dictionary<string, object>();
fields.put("test", 100);
fields.put("test_2", "hello_world");

GameAnalytics.NewErrorEvent (severity, message, fields);

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

Design Events

To add a design event call the following function:

GameAnalytics.NewDesignEvent (string eventName, float eventValue)
FieldTypeRequiredDescription
eventNamestringyesThe event string can have 1 to 5 parts. The parts are separated by ‘:’ with a max length of 64 each. e.g. “world1:kill:robot:laser”. The parts can be written only with a-zA-Z, 0-9, -_.,:()!? characters.
eventValuefloatnoNumber value of event.

Custom Design 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:

Dictionary<string, object> fields = new Dictionary<string, object>();
fields.put("test", 100);
fields.put("test_2", "hello_world");

GameAnalytics.NewDesignEvent (eventName, eventValue, fields);

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