# Treasure Data Unity SDK Quickstart The Unity SDK for [Treasure Data](https://www.treasuredata.com/). With this SDK, you can import the events on your applications into Treasure Data easily. # Setup Download this [Unity package](https://github.com/treasure-data/td-unity-sdk-package/raw/master/TD-Unity-SDK-0.1.10.unitypackage) and import it into your Unity project using **Assets -> Import Package -> Custom Package**. ## For iOS Application Development On Xcode, the following steps are needed: 1. Add Treasure Data iOS SDK to your `Podfile` as following: ``` platform :ios, '12.0' target 'Unity-iPhone' do use_frameworks! inherit! :search_paths end target 'UnityFramework' do use_frameworks! pod 'TreasureData-iOS-SDK', '= 1.0.1' end ``` # Basic Usage ## Instantiate the TreasureData object with your API Key ``` public class MyTreasureDataPlugin : MonoBehaviour { #if UNITY_IPHONE || UNITY_ANDROID [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] static void OnRuntimeInitialization() { TreasureData.InitializeApiEndpoint("https://us01.records.in.treasuredata.com"); TreasureData.InitializeApiKey("YOUR_API_KEY"); } #endif } ``` Warning Treasure Data strongly recommends that you use a write-only API key for ingest and import operations and whenever using Treasure Data SDKs details summary b Click here to see how to get a write-only API Key. p div iframe script 1. Login to the Treasure Data Console and go to the [API Key page](https://console.treasuredata.com/app/mp/ak). 2. If you dont already have a write-only API key, then create one. From the top right, select **Actions > Create API Key**. 3. Name the new API Key. 4. From the Type drop-down menu, select **Write-only**. 5. Select **Save**. 6. Copy your new Write-Only API Key and use it authenticate the APIs in your project. p ## Add an Event to a Local Buffer To add a event to a local buffer, use the `AddEvent` function. ```C Simple TreasureData.Instance.AddEvent("testdb", "unitytbl", ev); ``` ```C Advanced Dictionary ev = new Dictionary(); ev["str"] = "strstr"; ev["int"] = 12345; ev["long"] = 12345678912345678; ev["float"] = 12.345; ev["double"] = 12.3459832987654; ev["bool"] = true; TreasureData.Instance.AddEvent("testdb", "unitytbl", ev, delegate() { Debug.LogWarning ("AddEvent Success!!!"); }, delegate(string errorCode, string errorMsg) { Debug.LogWarning ("AddEvent Error!!! errorCode=" + errorCode + ", errorMsg=" + errorMsg); } ); ``` Specify the database and table to which you want to import the events. The total length of database and table must be shorter than 129 chars. ## Upload Events to Treasure Data To upload buffered events to Treasure Data, use the `UploadEvents` function. You can call this API to upload buffered events whenever you want. ```C Simple TreasureData.Instance.UploadEvents(); ``` ```C Advanced TreasureData.Instance.UploadEvents ( delegate() { Debug.LogWarning ("UploadEvents Success!!! "); }, delegate(string errorCode, string errorMsg) { Debug.LogWarning ("UploadEvents Error!!! errorCode=" + errorCode + ", errorMsg=" + errorMsg); } ); ``` The characteristics of your application will determine when and how often to upload buffered events. Treasure Data recommends that you upload at the following times: - When the current screen is closing or moving to background - When closing the application `UploadEvents` buffers for a few minutes before the import into Treasure Data storage begins. ## Retry uploading and deduplication This SDK imports events in exactly once style with the combination of these features. - This SDK keeps buffered events with adding unique keys and retries to upload them until confirming the events are uploaded and stored on server side (at least once) - The server side remembers the unique keys of all events within the past hour by default and prevents duplicated imports (at most once) Info The deduplication window is one hour by default, so it's important not to keep buffered events longer than that to avoid duplicated events. ## Start/End session When you call `StartGlobalSession` method, the SDK generates a session that's kept until `EndGlobalSession` is called. The session id will be output as a column name "`td_session_id`" in Treasure Data. Also, you can get the session id with `GetGlobalSessionId`. ```C TreasureData.InitializeDefaultDatabase("testdb"); td = new TreasureData("your_api_key"); print("Session ID = " + TreasureData.GetSessionId()); // >>> (null) TreasureData.StartGlobalSession(); print("Session ID = " + TreasureData.GetSessionId()); // >>> cad88260-67b4-0242-1329-2650772a66b1 : TreasureData.Instance.AddEvent("testdb", "unitytbl", ev); : TreasureData.EndGlobalSession(); print("Session ID = " + TreasureData.GetSessionId()); // >>> (null) : TreasureData.Instance.AddEvent("testdb", "unitytbl", ev); // Outputs =>> // [{"td_session_id":"cad88260-67b4-0242-1329-2650772a66b1", // ..., "time":1418880000}, // : // {..., "time":1418880123} // ] ``` The session continues from when `StartGlobalSession` is called until `EndGlobalSession` is called. If `StartGlobalSession` is called within 10 seconds of an `EndGlobalSession` call, then the previous session resumes; a new session is not created. If you want to use instance-level, fine-grained sessions, you can use `TreasureData#StartSession(tableName)` / `TreasureData#EndSession(tableName)` / `TreasureData#GetSessionId()`, which add a session event at calling `StartSession` / `EndSession` and don't have the session resume feature. # Advanced Usage ## Tracking Application Lifecycle Events The SDK can be optionally enabled to automatically captures app lifecycle events (disabled by default). You must explicitly enable this option. You can set the target table through `DefaultTable`: ```C [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] static void OnRuntimeInitialization() { // TreasureData client setup... TreasureData.DefaultTable = "app_lifecycles"; TreasureData.Instance.EnableAppLifecycleEvent(); } ``` There are three kinds of events that are tracked automatically: - Application Open - Install - Update ```json Application Open { "td_unity_event": "TD_UNITY_APP_OPEN", "td_app_ver": "1.0", ... } ``` ```json Application Install { "td_unity_event": "TD_UNITY_APP_INSTALL", "td_app_ver": "1.0", ... } ``` ```json Application Update { "td_unity_event": "TD_UNITY_APP_UPDATE", "td_app_ver": "1.1", "td_app_previous_ver": "1.0", ... } ``` ## Tracking In-App Purchase Events If enabled, the Treasure Data SDK can automatically tracks IAP events without having to listen and call `addEvent` yourself. Enable or disable this feature using the following: ```C enableInAppPurchaseEvent TreasureData.sharedInstance.enableInAppPurchaseEvent(); ``` ```C disableInAppPurchaseEvent TreasureData.sharedInstance.disableInAppPurchaseEvent(); ``` Info In-App purchase event tracking is disabled by default. Depending on the native platform your application is running on, the event's schema might be different: | Android | iOS | | --- | --- | | - `td_android_event`- `td_iap_product_id`- `td_iap_order_id`- `td_iap_product_price`- `td_iap_quantity`- `td_iap_product_price_amount_micros`- `td_iap_product_currency`- `td_iap_purchase_time`- `td_iap_purchase_token`- `td_iap_purchase_state`- `td_iap_purchase_developer_payload`- `td_iap_product_type`- `td_iap_product_title`- `td_iap_product_description`- `td_iap_package_name`- `td_iap_subs_auto_renewing`- `td_iap_subs_status`- `td_iap_subs_period`- `td_iap_free_trial_period`- `td_iap_intro_price_period`- `td_iap_intro_price_cycless`- `td_iap_intro_price_amount_micros` | - `td_ios_event`- `td_iap_transaction_identifier`- `td_iap_transaction_date`- `td_iap_quantity`- `td_iap_product_identifier`- `td_iap_product_price`- `td_iap_product_localized_title`- `td_iap_product_localized_description`- `td_iap_product_currency_code` | For the more details of these columns' value please see the Android / iOS SDK documentation. - [Android SDK - IAP Tracking](https://github.com/treasure-data/td-android-sdk#track-in-app-purchase-events-automatically) - [iOS SDK - IAP Tracking](https://github.com/treasure-data/td-ios-sdk#app-lifecycle-events) # Additional Configuration ## Endpoint The API endpoint (default: [ https://us01.records.in.treasuredata.com ]) is modified using the `InitializeApiEndpoint`: ```C TreasureData.InitializeApiEndpoint("https://us01.records.in.treasuredata.com"); ``` ## Encryption Key If you've set an encryption key via `TreasureData.InitializeEncryptionKey()`, the SDK saves the event data as encrypted when it calls `AddEvent`. ```C TreasureData.InitializeEncryptionKey("hello world"); : TreasureData.Instance.AddEvent("testdb", "unitytbl", ev); ``` ## Default Database ```C TreasureData.InitializeDefaultDatabase("testdb"); : TreasureData.Instance.AddEvent("unitytbl", ev); ``` ## Adding the UUID of the Device Automatically to Each Event The UUID of the device is added to each event automatically if you call `EnableAutoAppendUniqId`. This value won't change until the application is uninstalled. ```C TreasureData.Instance.EnableAutoAppendUniqId(); : TreasureData.Instance.AddEvent("unitytbl", "name", "foobar"); // Outputs =>> // {"td_uuid_id":"cad88260-67b4-0242-1329-2650772a66b1", "name":"foobar", ... } ``` It outputs the value as a column name `td_uuid`. ## Adding an UUID to Each Event Record Automatically The UUID will be added to each event record automatically if you call `EnableAutoAppendRecordUUID`. Each event has different UUID. ```C TreasureData.Instance.EnableAutoAppendRecordUUID(); // If you want to customize the column name, pass it to the API // TreasureData.Instance.EnableAutoAppendRecordUUID("my_record_uuid"); : TreasureData.Instance.AddEvent(...); ``` It outputs the value as a column name `record_uuid` by default. ## Adding the Device Model Information to Each Event Automatically Device model information is added to each event automatically if you call `EnableAutoAppendModelInformation`. ```C TreasureData.Instance.EnableAutoAppendModelInformation(); : TreasureData.Instance.AddEvent("unitytbl", "name", "foobar"); // Outputs =>> // {"td_device":"iPod touch", "name":"foobar", ... } ``` It outputs the following column names and values: - iOS - `td_device` : UIDevice.model - `td_model` : UIDevice.model - `td_os_ver` : UIDevice.model.systemVersion - `td_os_type` : "iOS" - Android - `td_board` : android.os.Build#BOARD - `td_brand` : android.os.Build#BRAND - `td_device` : android.os.Build#DEVICE - `td_display` : android.os.Build#DISPLAY - `td_model` : android.os.Build#MODEL - `td_os_ver` : android.os.Build.VERSION#SDK_INT - `td_os_type` : "Android" ## Adding Application Package Version Information to Each Event Automatically Application package version information is added to each event automatically if you call `EnableAutoAppendAppInformation`. ```C TreasureData.Instance.EnableAutoAppendAppInformation(); : TreasureData.Instance.AddEvent("unitytbl", "name", "foobar"); // Outputs =>> // {"td_app_ver":"1.2.3", "name":"foobar", ... } ``` It outputs the following column names and values: - iOS - `td_app_ver` : Core Foundation key `CFBundleShortVersionString` - `td_app_ver_num` : Core Foundation key `CFBundleVersion` - Android - `td_app_ver` : android.content.pm.PackageInfo.versionName (from Context.getPackageManager().getPackageInfo()) - `td_app_ver_num` : android.content.pm.PackageInfo.versionCode (from Context.getPackageManager().getPackageInfo()) ## Adding Locale Configuration Information to Each Event Automatically Locale configuration information will be added to each event automatically if you call `EnableAutoAppendLocaleInformation`. ```C TreasureData.Instance.EnableAutoAppendLocaleInformation(); : td.AddEvent("unitytbl", "name", "foobar"); // Outputs =>> // {"td_locale_lang":"en", "name":"foobar", ... } ``` It outputs the following column names and values: - iOS - `td_locale_country` : [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode] - `td_locale_lang` : [[NSLocale currentLocale] objectForKey: NSLocaleLanguageCode] - Android - `td_locale_country` : java.util.Locale.getCountry() (from Context.getResources().getConfiguration().locale) - `td_locale_lang` : java.util.Locale.getLanguage() (from Context.getResources().getConfiguration().locale) ## Enable/Disable Debug Log ```C EnableLogging TreasureData.EnableLogging(); ``` ```C DisableLogging TreasureData.DisableLogging(); ``` # Error codes The `TreasureData.Instance.AddEvent` and `TreasureData.Instance.UploadEvents` call the `onError` delegate method with an `errorCode` argument. This argument is useful for determining the cause or type of the error. Here are the error code arguments: - `init_error` : The initialization failed. - `invalid_param` : The parameter passed to the API was invalid - `invalid_event` : The event was invalid - `data_conversion` : Failed to convert the data to/from JSON - `storage_error` : Failed to read/write data in the storage - `network_error` : Failed to communicate with the server due to network problem - `server_response` : The server returned an error response # GDPR Compliance The SDK provide some convenient methods to easily opt-out of tracking the device entirely without having to resort to many cluttered if-else statements: ```C .DisableCustomEvent() // Opt-out of your own events .DisableAppLifecycleEvent() // Opt-out of TD generated events ``` These can be opted back in by calling `EnableCustomEvent()` or `EnableAppLifecycleEvent()`. Note that these settings persist across application restarts. Generally these methods should be called when reflecting your user's choice, not every time the SDK is initialized. By default custom events are enabled and app lifecycles events are disabled. - Use `ResetUniqId()` to reset the identification of device on subsequent events. `td_uuid` will be randomized to another value and an extra event is captured with `{"td_unity_event": "forget_device_id", "td_uuid": }` to the `DefaultTable`. # Development mode to run application without real devices Different behaviors from normal mode - In development mode, - buffered events are stored in memory not in persistent storages. - when running into an upload failure, buffered events get lost. This SDK works as an Unity Native Plugin. So you need to run your application with the SDK on a real device especially when you want to run it on iOS platform. If you want to run your application with the SDK without real devices, you can do that with a special mode for development that emulates the behavior with a pure C# implementation. ## Configuration - On PC / iOS / Android / other platforms - Add a symbol `TD_SDK_DEV_MODE` to **Player Settings > Scripting Define Symbols** - On Unity Editor - Always enabled. No action required. ## Modify source code - Create `SimpleTDClient` instance by calling `SimpleTDClient.Create()` static method in `MonoBehaviour#Start` method - Attach the instance to `TreasureData` instance ```C public class TreasureDataExampleScript : MonoBehaviour { private static TreasureData td = null; // private TreasureData tdOnlyInTheScene = null; : void Start () { td = new TreasureData("YOUR_WRITE_APIKEY"); /* Optional configurations SimpleTDClient.SetDummyAppVersionNumber("77"); SimpleTDClient.SetDummyBoard("bravo"); SimpleTDClient.SetDummyBrand("htc_asia_wwe"); SimpleTDClient.SetDummyDevice("bravo"); SimpleTDClient.SetDummyDisplay("ERE27"); SimpleTDClient.SetDummyModel("HTC Desire"); SimpleTDClient.SetDummyOsVer("2.1"); SimpleTDClient.SetDummyOsType("android"); SimpleTDClient.SetDummyLocaleCountry("JP"); SimpleTDClient.SetDummyLocaleLang("ja"); */ // If you want to use a TDClient over scenes, pass `true` to `SimpleTDClient.Create` to prevent it from being removed. td.SetSimpleTDClient(SimpleTDClient.Create(true)); // If you want to use a TDClient only within a scene, don't pass `true` to `SimpleTDClient.Create` so that you can prevent object leaks. // tdOnlyInTheScene.SetSimpleTDClient(SimpleTDClient.Create()); : ``` # Further Reading - [Unity SDK API Reference](/en/sdk/unity-sdk/api)