Introduction

The deltaDNA SDK for Unity allows your Unity-developed games to send information on in-game events and player actions to deltaDNA for visualisation, analysis and gameplay personalisation.

Events are sent to the deltaDNA platform as JSON objects, these events are managed and tracked using the online dashboard.

When your game triggers events the SDK will store them locally and upload them at regular intervals when a connection is available – or at a time of your choosing.  This allows the SDK to collect events regardless of connectivity and gives you control over the timing and frequency of uploads.

Events vary in complexity but are all derived from a common event schema. This document and the accompanying demo application provide examples of increasingly complex events.

The source code for the SDK, written in C#, is provided as a packaged Unity asset and has no external dependencies. Games successfully send data to deltaDNA using the Unity SDK from a wide range of Unity target platforms including Xbox One, PS4, Web GL, iOS, Android etc.  It should be noted that deltaDNA is not currently a certified Xbox or Sony technology partner so there may be some support scenarios where we will be unable to replicate or debug individual customer implementations.

This page will cover the following aspects of the deltaDNA Unity SDK:

Important changes: previous versions of the SDK and release notes are available on the Releases Notes page and from version 4 onwards in the change log on our GitHub page

Initializing the SDK

The SDK should be imported into your Unity project as a package and initialized with the following parameters:

Initialization Parameters

  • environmentKey – a unique 32 character string assigned to your application. You will be assigned separate application keys for development and production builds of your game.
  • collectURL – the address of the server that will be collecting your events.
  • engageURL – the address of the server that will provide real-time A/B Testing and Targeting. This is only required if your game uses these features.
  • userID (optional) – every user needs to have a unique userID. If your game can provide a unique userID you can use it. If you start the SDK without specifying a userID the SDK will generate a unique userID automatically and maintain it across subsequent sessions or until you provide your own userID in the start method.

These parameters can be found on your game details page. Please note that there are different environmentKey values for your DEV & LIVE environments. You will need to change the environment key that you initialize the SDK with as you move from development and testing onto production. There is also an auto-generated code snippet on the game details page, use this to integrate the SDK with a single copy & paste.

118

Example initialization code:

 

This is the minimum amount of code required to initialize the Unity SDK and start sending events. It will automatically send the newPlayer event the first time the SDK is run and the gameStarted and clientDevice event each time the game runs. Read on to find out how to go beyond recording a few automated events and start unlocking the power of deltaDNA with additional events, parameters, you own custom events, A/B tests and targeted campaigns.

Anatomy of an Event

All events are recorded as JSON documents with a shared basic schema. The document will be different for every event type but all of them should adhere to the following minimal schema:

The Unity SDK will automatically populate the userID, sessionID, eventTimestamp, eventUUID,  platform & sdkVersion parameters for every event you send. When you add parameters to an event they will all be placed inside the eventParams object.

The order of the parameters in your JSON event doesn’t matter.

You can inspect the parameters that each event expects, there type and any formatting or enumeration rules in the Event Manager.

Parameters can be either Optional or Required. Any parameters that are are optional don’t have to be included in your event if you don’t have a valid value to put in them. It is better to leave them out completely, than set their value to null or empty.

This basic event structure provides great flexibility for recording events with varying levels of complexity, from simple events like the one above to complex events containing nested arrays. The following code examples will show a variety of events from simple to complex.

Please note that all events are validated and will be rejected if they don’t match the schema in the Event Manager 

Settings

The simple initialization code, copied from your game details page and shown above, is the minimum code required to start collecting analytics data from your players. You will quickly want to start adding more events and fine tuning your implementation. Be sure to check further down this page for a full list of settings, methods and helpers. In the meantime here’s the same initialization code with a couple of useful settings added.


These two additional settings will:

  1. Tell the SDK to output detailed debug on the events you are collecting and communications with deltaDNA. This is particularly useful when used in conjunction with the QA – Interactive Validator during development, as it will help you resolve any issues that are causing any of your events to fail validation.
  2. Set the clientVersion of your game. This is advisable and can very useful for identifying behavioural differences between players on different builds of your game. Especially when a client version update is option that many mobile users don’t bother with. You may even have spotted a warning about the client version not being set when you ran the simple initialization code, setting the ClientVersion will resolve it.
There are many other useful settings that will help you with push notification messages, device IDs, event hashing, automated event collection and automated communications, be sure to check them out.

Example 1 – A Simple Event

The initialization code that we have seen already will send the newPlayer, clientDevice and gameStarted events to deltaDNA automatically. In the following code we will add an event ourselves in code.

When we added our game to deltaDNA some default events were automatically added, these events tend to be standard across all games and are used to drive many of the dashboards. For now we will just use one of those standard events, the options event. Other standard events can be seen by visiting Setup > View Events and any of these events can be sent to us so long as the schema in your game matches the schema on the platform.

The following JSON event would be uploaded

Example 2 – Adding a New Template Event

The previous example used one of our seven standard events, this time we will do something a bit more ambitious, we will add a custom parameter to an an event, then trigger the event from our code.   This example will just show the event creation as initialization and uploading was shown in the previous example.

If the missionStarted event isn’t already in your event list, add it by selecting it from the event template list, then add a new missionDifficulty parameter of type STRING to the eventParams section.

The code to trigger the missonStarted event:

The following JSON event would be uploaded:

Pasting event JSON into the Interactive Event Validator can help resolve errors, our missionStarted event passed validation first time.

119

Example 3 – A Complex Event

The previous examples have been pretty straightforward and haven’t required much explanation. However, the following one is a bit more complex as it introduces nesting, arrays and some special objects that you will encounter when the player buys, trades, wins, exchanges currency and items with the game or other players.  The good news is, the structure for this is fairly standard and the following event is as complex as it gets.

We are going to trigger a transaction event that records the player using some real world currency to purchase to purchase a treasure chest containing some virtual currency and multiple items. We will also take advantage of deltaDNA revenue validation with the Apple store to check that the transaction is valid.

As you can see the structure of the transaction event is a bit more complex. It contains a couple of Product objects for recording productsSpent and productsReceived.

Our JSON event will end up looking like

and the following code was is required to create it using the Transaction helper class.

 

Or you can use a GameEvent helper.

It is also worth noting that the currency value is always sent as an integer in the minor currency unit and the realCurrencyType  is an ISO-4217,  3 character currency code.

The above snippet is $4.99 USD

This event may be more complex but the structure is logical, flexible and provides a mechanism for players spending or receiving any combination of currencies and items.

Transaction Validation

The platform can undertake transaction receipt validation with various Stores in order to ensure that any revenue displayed in your dashboards is genuine revenue and not the result of a hacked or Jail broken game.

If you wish to use transaction validation you will need to add a couple of details to the “Edit Game Details” page that can be reached from the “Manage Games” link on the left of the Welcome Screen.
e.g. for Apple you would set your 9 digit Apple StoreID. 971883677 and the URL to the Apple Receipt Validation service https://buy.itunes.apple.com/verifyReceipt 

You also need to send additional parameters along with each transaction event to tell deltaDNA that the transaction should be validated.

e.g. To validate an Apple store IAP

The transactionReceipt is the BASE 64 encoded receipt data that was returned from Apple. Please refer to the Apple developer website for details on Apple Receipt Validation

To validate Google Play IAP send the transactionServer, the purchase data as the transactionReceipt and the ‘in app data signature’ as transactionReceiptSignature

N.b. since the transactionReceiptSignature is generated from the transaction receipt and a private key in order to validate the receipt this will need to be exactly the string as provided by Google and passed as a string, not a nested JSON object.

deltaDNA will then validate your revenue and add an additional revenueValidated parameter, containing the following potential values, to your transaction event.

  • 0 – no validation performed
  • 1 – revenue passed validation check
  • 2 – revenue failed validation check
  • 3 – revenue validation attempted, but result unknown (validation service may have been unavailable)

Transactions that fail validation with status code 2 or 3 will be excluded from your Measure Revenue charts and user metrics.

There is a webinar and accompanying powerpoint presentation covering revenue validation in more detail on the Webinars page.

Example 4 – Engage

Games can retrieve time sensitive information from Engage to determine if a particular action should be taken for the user at a specific time, based on the results of an in-game Campaign or A/B Test. Essentially your game should make engage requests at predetermined decision points in your game and the response will allow you to personalise the gameplay for that user instantly.

The following example shows how you can use Engage targeting to change an IAP offer made to the player :

  1. Create a targeted campaign on the deltaDNA platform
  2. Make an Engage request 
  3. And react to the response in a callback.

For code snippets regarding engage calls see our GitHub documentation page.

For all engage calls a JSON response will be returned to you in under 200ms. However, your game should be structured in such a way that is won’t stall if the user is on a high latency connection.

The engage response contains a transactionID and a parameters object containing any parameters relevant to this player at this point in time.

If the device doesn’t have internet connectivity at the time of the Engage request a cached response from the last successful Engage request for the same decision point will be contained in the response. The isCachedResponse parameter will indicate that this is a cached response.

You may receive a response containing a transactionID but no parameters with personalisation values. This indicates that the player has failed to meet any qualification criteria or has been allocated to a control group.

If there was an error processing your Engage request at the server your response will contain a statusCode parameter containing the relevant status code.

  • 400 – inputs malformed or incorrect in some way, or you are sending real-time parameters that haven’t been added to your Game Parameter list.
  • 403 – secret hash key incorrect or Engage is not enabled on your account.
    Please check that you have the “On-Demand” package enabled on your Game -> Packages page, you may need to get the Account Owner for your deltaDNA account to do this for you.
  • 404 – incorrect URL or unknown environmentKey

Image Messaging

Engage Campaigns can deliver popup messages to your game at run-time. Re-usable Image Messages are created in the Action Manager (Engage->Actions) and assigned in the Campaign Manager (Engage->Campaigns). The Unity SDK has a Popup class that draws the image message over your game. The popup is event driven so you are able to control when the image is downloaded from our servers, and when it is presented to the player.

Each message consists of two parts, a sprite map contains images for the background and a number of buttons, and a layout describing how to display these parts. The layout uses constraints to workout how to scale and where to place the popup. This means we don’t have to worry about screen sizes, but we can also protect parts of the screen from being covered up. The image is drawn as large as possible within those constraints whilst still maintaining the original aspect
ratio.

An Image Messaging Engage Request is the same as any other Engage campaign request.

The response message contains the image and layout information for the popup as well as information on any actions assigned to the images.

  • The url is the location of the sprite map image file. The width and height are the size of the image, and the format is the image format.
  • The spritemap object describes the location of the image assets in the sprite map. The buttons are optional depending on the number of buttons in the message.
  • The layout object describes how the background is to appear on the screen. It contains landscape and/or portrait keys depending on preferred layout. If only one key is present the rules are applied whatever the orientation.The layout orientation contains rules for the background and the location of the buttons. For the background two modes are valid:
    cover which scales the background image so it’s as large as possible, and
    contain which makes the image as large as possible such that all the constraints are satisfied.
  • Each background and button object can have an action. The action type can be none, dismiss, link or action.
    If the type is link or action a value field will provide a string value to pass back to the callback associated with the button. If a link, then the browser is opened automatically by the SDK.

  • The shim field describes how the remainder of the screen behind the message should be handled. The mask can be either
    none, in which case nothing is added so any buttons behind the popup can still be clicked,
    clear which will have the effect of preventing background buttons from being clicked, and
    dimmed which greys out the screen.The shim also supports actions so clicking on it can dismiss the popup too.

See our GitHub page on how to implement the image engagement and handle the optional parameters returned along with the image.

SmartAds

The Unity SDK enables you to implement ads within your Android or iOS application in a way that optimizes the ad revenue by requesting ads from the most valuable ad network.

See the following webinar for an introduction to SmartAds

SmartAds Webinar

For more details on how to implement SmartAds see our Github page.

Unity Cloud Build with SmartAds for iOS.

Since our SmartAds SDK uses Cocoapods to manage its dependencies for iOS, the machine building will need to have Cocoapods installed. Unfortunately Unity’s build servers do not have Cocoapods installed and therefore it is not possible to build for iOS with SmartAds using the Unity Cloud Build solution. When Unity supports Cocoapods this problem will be resolved. You can vote for the feature on the following unity page: https://feedback.unity3d.com/suggestions/cocoapod-support-dependency-management

Android Push Notifications

The deltaDNA SDK can request an Android registration ID for a player’s device and communicate it to the deltaDNA platform using a notificationServices event – although you may need to add this event to your game in the Event Manager. This ID can be used by deltaDNA to send targeted push notification messages to the device.

The Firebase Cloud Messaging service is used by deltaDNA to send push notifications as part of an out of game campaign.

Before the SDK can be used to register the device for push notifications there are a couple of steps you must first complete. These are:

  • Retrieve the sender ID and application ID from Firebase. More information about retrieving these values and setting up FCM can be found in our FCM Setup guide)
  • Configure these values in your project in the configuration screen – this can be accessed from the Unity Editor menu under DeltaDNA > Notifications > Android Configure

The following line of code can then be used to register the device for push notifications:

This will retrieve the Android registration ID from the device and send it to the deltaDNA platform to be used as a target for push notifications. In order for the platform to use this device ID as a target you must configure your Google API key in the platform – the process for this can be seen in the FCM Guide under Retrieving Configuration Values.

More information on Android push notifications and Unity SDK integration in general can be found in our Unity SDK GitHub page.

It is recommended that you make use of Firebase Cloud Messaging however some older applications may still use Google Cloud Messaging – information about retrieving configuration values from GCM can be found in our GCM Setup guide

Apple (iOS) Push Notifications

The deltaDNA SDK for Unity can store the Apple Push Notification Token and send it to deltaDNA allowing the deltaDNA platform to send targeted push notification messages to players.  Your application will be responsible for requesting a push notification from Apple.

To request a push notification token from Apple:

The token will be sent to deltaDNA in a notificationServices event. You may need to add the notificationServices event to your game using the Event Manager.

You will also need to upload your iOS Certificate to the deltaDNA platform in order for Apple to accept push notification requests from deltaDNA, you can do this in the SETUP -> TOOLS – NOTIFICATIONS -> Manage Identity Page. Your certificate from Apple needs to contain both your certificate and key and be saved as a .p12 file.CertificateIcon

Check out our Apple Certificate Guide, for more information on how to provision your App to receive Push Notification Messages, create a certificate and save the it in the correct format.

Apple Identifiers

Apple Advertising Identifier and VendorID deltaDNA no longer automatically retrieves the apple advertising identifier or vendorID as of Unity SDK v3.0.6

If you wish to record these parameters in deltaDNA you are responsible for retrieving them from the device and sending them as custom parameters with any events you wish to attach them to. You will also need to add these custom parameters in the event management tool.

NB: As of February 2014 Apple have started rejecting Apps that collect the advertising Identifier parameter but don’t display Ads.

Event Timestamps

The Unity SDK will automatically timestamp events using the clock on the client device. This can cause inaccuracies when the device is not set to the correct time or date and even cause events to get rejected if the time is too far out. However the local timestamping behaviour can be overridden and you can provide your own timestamping method that will be used to timestamp events.

It is also possible to completely disable timestamping on the device and send events without a timestamp, this will result in the event being timestamped with the Collect server time when the event is received. We don’t recommend this approach though as there are a couple of undesirable side effects.

  • The Unity SDK caches player events locally to ensure they are not lost if the devices loses connectivity. It is therefore possible for events to be received many days after they occurred.
  • Events are uploaded in batches containing multiple events as this is much more efficient than sending them one at a time. If you were to use Collect server timestamping this would make it look like the player is playing in frantic bursts. Events would look like they all happened within a few milliseconds of each other and then nothing until the next batch is uploaded.

If you must use Collect server timestamping you can do so by setting  DDNA.Instance.UseCollectTimestamp(true);

Appendix 1 – Class Reference

DDNA.Instance

using DeltaDNA;

The SDK class contains the following public methods and properties.

Methods

StartSDK

void StartSDK(string environmentKey, string collectServerURL, string engageServerURL, string userID)

void StartSDK(string environmentKey, string collectServerURL, string engageServerURL)

Initializes and starts the SDK. If the userID is provided deltaDNA will create a unique userID for the player.

StopSDK

void StopSDK()

Sends a gameEnded event and disables background uploading of events.

NewSession

void NewSession()

Changes the sessionID for the current user. This can be useful if your app has resumed from the background after a prolonged period.

RecordEvent

void RecordEvent(string eventName)

void RecordEvent(string eventName, Dictionary<string, object> eventParams)

void RecordEvent(GameEvent gameEvent)

Records an event and stores it to the event buffer.

Upload

void Upload();

Starts a Unity coroutine to Upload events. This can be called at any point and will only begin uploading if there are events waiting to send and if we’re not already processing them. This tends to be called from menu screens, reward screens and other low intensity parts of the game.  However, the communication to the server is performed in its own thread so in normal operating mode it should not cause a noticeable effect on game performance.

Please note, the SDK will default to automatically upload events at regular intervals. If you want to control when the SDK sends it data to deltaDNA you should disable automatic uploading DDNA.Instance.Settings.BackgroundEventUpload = false; and call the Upload()  method yourself.

RequestEngagement

void RequestEngagement(Engagement engagement, Action<Dictionary<string, object>> callback)Starts a Unity coroutine to make a request to Engage. Communication with the server is performed in its own thread. You should create your own callback to react accordingly to the response from Engage.

RequestImageMessage

void RequestImageMessage(Engagement engagement, IPopup popup)

void RequestImageMessage(Engagement engagement, IPopup popup, Action<Dictionary<string, object>> callback)

Requests an image based Engagement with either the default or user custom popup behaviour. An optional callback can be given, which will also received the server response and will be called at the same time as launching the popup.

RecordPushNotification

void RecordPushNotification(Dictionary<string, object> payload)

Records that the game received a push notification. It is safe to call this method before calling StartSDK, the ‘notificationOpened’ event will be sent at that time.

ClearPersistantData

void ClearPersistentData();

Clears any stored data including userID etc.. Useful during development if you want to erase all stored settings.

SetTimestampFunc

SetTimestampFunc();

Allows you to provide your own eventTimestamping function to timestamp events on the local device .

e.g.

UseCollectTimestamp

UseCollectTimestamp(bool); Disables local event timestamping in favour of setting the event timestamp on the Collect server when the event is received. Is set to false by default. Only use this if you understand the potential consequences.

SetLoggingLevel

void SetLoggingLevel();
Set the debugger logging level, default level is WARNING.
  • DeltaDNA.Logger.Level.DEBUG
  • DeltaDNA.Logger.Level.INFO
  • DeltaDNA.Logger.Level.WARNING
  • DeltaDNA.Logger.Level.ERROR

Properties

AndroidRegistrationID

(string) AndroidRegistrationID 

The Android registration ID that is associated with this device if it’s running on the Android platform.

ClientVersion

(string) ClientVersion

A version string for your game that will be reported to us. This must be set before calling  Init()

CollectURL

(string)CollectServerURL

Get the collect server URL the SDK was initialized with.

 EngageURL

(string)EngageServerURL()

Get the engage server URL the SDK was initialized with.

EnvironmentKey

(string)EnvironmentKey

Get the environment key the SDK was initialized with.

HashSecret

(string)HashSecret

To enable hashing of your event and engage data, set this value to your unique hash secret. You must also enable hashing for the environment in the deltaDNA platform.
To disable hashing set it to null, which is the default.
This must be set before calling   Init()

HasStarted

(bool)HasStarted

Gets a value indicating whether this instance is initialized.

IsUploading

(bool)IsUploading

Gets a value indicating whether an event upload is in progress.

Platform

(string)Platform

Gets the platform.

PushNotificationToken

(string)PushNotificationToken

The push notification token from Apple that is associated with this device if it’s running on the iOS platform. This must be set before calling   StartSDK()

SessionID

(string)SessionID 

Get the Session ID as a string. The SDK generates a fresh session ID each time it is initialized.

Settings

(Settings)Settings
Controls default behaviour of the SDK.  Set prior to initialization.
UserID

(string)UserID; 

Gets the userID

GameEvent

Methods

The GameEvent object helps you to build events and add parameters to them

GameEvent

GameEvent(string eventName)

The GameEvent Constructor.

AddParam

AddParam(string key, object value)

Add Parameters to your GameEvent object.

e.g.

AsDictionary

Dictionary<string, object> AsDictionary()

Returns an GameEvent object as a Dictionary.

Product

The Product object helps you build product structures that are commonly used in events where the player is receiving or spending items, real currencies or virtualCurrencies.

Methods

ProductBuilder

Product()

The product constructor.

SetRealCurrency

Product SetRealCurrency(string currencyType, int currencyAmount)

Adds a RealCurrency object to the product.

  • The currency type should be an ISO-4217 three character currency code.
  • The currency amount should be expressed as an Integer in the minor currency amount. e.g. $4.99 in American Dollars would be  .AddRealCurrency("USD", 499) 

AddVirtualCurrency

Product AddVirtualCurrency(string currencyName, string currencyType, int currencyAmount)

Adds a Virtual Currency Object to the product

  • The currencyName should match the name of the currency in your game , e.g. “GEMS”, “GOLD”, DIAMONDS” etc..
  • The currencyType should be PREMIUM, GRIND or PREMIUM_GRIND
  • The currencyAmount should be expressed as an Integer in the minor currency amount.

AddItem

ProductBuilder AddItem(string itemName, string itemType, int itemAmount)

Adds an Item object to the product

  • The item name should match the name of the item in the game e.g. “Mighty Sword of the First Age”
  • The item type shoulf describe the category the item belongs to in the game, or store e.g. “Weapon”, “Decoration”, “Pet” etc..
  • The item amount should be recorded as an integer.

Product example

Params

The Params object is used to help you build parameter objects to attach to GameEvents

Methods

Params

Params()

The Params object constructor

AddParam

Params AddParam(string key, object value)

Add parameters to your Params object

GetParam

object GetParam(string key)

Returns a parameter object for the given parameter key.

AsDictionary

Dictionary<string, object> AsDictionary()

Returns an Params object as a Dictionary.

Appendix 2 – Configuration options

The SDK singleton may be configured to best accommodate your game’s needs and provides a straight-forward mechanism for configuring various options.

As the SDK instance is created as a singleton before the StartSDK call is made, settings should be set prior to calling StartSDK().

Configuration settings are simply made my updating the properties of the DDNA.Instance.Settings object. The available configuration options are detailed below:

bool OnFirstRunSendNewPlayerEvent 
Defaults to true. The SDK will send a newPlayer event to deltaDNA the first time it is initialized. Change this setting to false to prevent this happening automatically.
You will most likely want to change this if you want to add additional detail to the parameters in the newPlayer event than the SDK can pick up automatically. e.g. gender, location, age, acquisition channel etc..
bool OnInitSendClientDeviceEvent
Defaults to true. The SDK will automatically populate the clientDevice as best it can, and send each time a game play session commences.
bool OnInitSendGameStartedEvent
Defaults to true. The SDK will automatically send a gameStarted event each time a game play session commences.
NB: The clientVersion, pushNotificationToken and androidRegistration parameters will be sent with the gameStarted event. Remember to set them if you want to use them in deltaDNA.
bool DebugMode
Defaults to false.  Switches on debug statements when set to true, and off if set to false.
Note that important errors (such as connectivity errors) will be logged in the debug console regardless of this setting.
float HttpRequestRetryDelaySeconds
Defaults to 2. Sets the number of seconds the SDK should wait after a failed upload attempt before trying again.
int HttpRequestMaxRetries
Defaults to 5. The number of retries the SDK should make per Upload.
int HttpRequestCollectTimeoutSeconds
Controls the default timeout for uploading events to Collect.
int HttpRequestEngageTimeoutSeconds
Controls the default timeout for Engage requests.
bool BackgroundEventUpload 
Defaults to true. Enabled or Disabled automated event uploading. Turn this off if you want to control when events are uploaded rather than having the SDK schedule them at regular intervals.
int BackgroundEventUploadStartDelaySeconds 
Defaults to zero. The number of seconds to wait after initialization before attempting to upload events.
int BackgroundEventUploadRepeatRateSeconds
Defaults to 60. The number of seconds to wait between uploads when automated background event uploading is enabled.
bool UseEventStore
Controls if the event store should be used or not. The default is for TRUE unless UNITY_WEBPLAYER or UNITY_WEBGL is defined. This property should be used if the device you are targeting does not have local storage.

Example

To turn on debug mode and turn off the automatic upload events, so we can control when the game performs Uploads ourselves..