iOS SDK Quickstart

iOS and tvOS SDK for Treasure Data. With this SDK, you can import the events on your applications into Treasure Data easily. This SDK supports:

  • iOS 12 and up
  • tvOS 12 and up

Prerequisites and Requirements

  • Basic knowledge of iOS Development (Xcode, CocoaPods)
  • iOS 12 or later
  • Basic knowledge of Treasure Data
  • Access to Treasure Data iOS SDK releases
  • Ensure compliance with GDPR

tvOS

This SDK supports Apple tvOS version 12 and up. APIs and their behaviors are largely the same as being used in the iOS application, except:

  • In tvOS, cache storage is stored in the cache directory which can be purged at any time. It is recommended to call upload events APIs as frequently as possible to prevent loss of data.

Migration to Version 1.0.1

Version 1.0.1 has major changes that are not backward compatible with previous versions. If you are upgrading from version 0.9.0 or earlier, your code will not run correctly without performing the following steps:

  • The API endpoint has changed to the Ingestion endpoint. The default value is [ https://us01.records.in.treasuredata.com ] .
  • The initializeApiEndpoint API is no longer available, please use initializeWithApiKey:apiEndpoint: instead.
  • uuid is now a reserved column name. If you try to add a value to an event's uuid key, you won't see the column show up in the database.
  • Auto tracking of client id by adding td_ip field is no longer supported. Instead, use the new enableAutoTrackingIP and disableAutoTrackingIP APIs.

Usage in Swift

See this Treasure Data Swift Example Project for details.

Installation

There are several ways to install the library:

Option 1: CocoaPods

CocoaPods is needed to set up the SDK. If you've not installed it yet, install it first.

Copy
Copied
$ gem install cocoapods

Next, add this line in your Podfile.

Copy
Copied
pod 'TreasureData-iOS-SDK', '= 1.0.1'

If you use the SDK in Swift, add this line to your Podfile.

Copy
Copied
use_frameworks!

Finally, execute 'pod install'.

Copy
Copied
$ pod install

Remember to reopen your project by opening .xcworkspace file instead of .xcodeproj file.

Option 2: Swift Package Manager

You can install either via Xcode: File > Swift Packages > Add Package Dependency and enter https://github.com/treasure-data/td-ios-sdk.git.

Or add this line to dependencies array in the Package.swift file:

Copy
Copied
.package(url: "https://github.com/treasure-data/td-ios-sdk.git", .upToNextMajor(from: "1.0.1"))

Option 3: Framework

After version 0.9.0, Treasure Data no longer supports a standalone framework.

GDPR - Tracking of Personal Information

ATTENTION

You must review your data collection policy with your company's data privacy officer and legal counsel to determine what if any personal information you should collect. If you decide to enable tracking of individuals, we recommend that you also integrate a consent management system to track individual user opt-ins to tracking.

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:

Copy
Copied
// Opt-out of your own events
[[TreasureData sharedInstance] disableCustomEvent];
// Opt-out of TD generated events
[[TreasureData sharedInstance] disableAppLifecycleEvent];
[[TreasureData sharedInstance] disableInAppPurchaseEvent];

These can be opted back in by calling enableCustomEvent or enableAppLifecycleEvent. Note that these settings are saved persistently, so it survives across app launches. Generally these methods should be called when reflecting your user's choice, not on each instance initializing the SDK. 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_ios_event": "forget_device_id", "td_uuid": <old_uuid>} to the defaultTable .

In testing, review the information you are collecting to ensure that you have the personal information you intended and nothing more.

Basic Use: Objective-C

After the iOS SDK has been installed, the following steps will allow you to initialize a TreasureData object with a write-only API Key, add events to a local buffer, and upload the buffer of events.

Import SDK Header File

Copy
Copied
#import <TreasureData-iOS-SDK/TreasureData.h>

Register your Treasure Data API Key

Copy
Copied
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [TreasureData initializeWithApiKey:@"your_api_key"];
}
Warning

Treasure Data strongly recommends that you use a write-only API key for ingest and import operations and whenever using Treasure Data SDKs

Click here to see how to get a write-only API Key.

  1. Login to the Treasure Data Console and go to the API Key page .
  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.

Add an Event to the Local Buffer

To add an event to local buffer, call TreasureData's addEvent or addEventWithCallback API.

Copy
Copied
- (IBAction)clickButton:(id)sender {
    [[TreasureData sharedInstance] addEventWithCallback:@{
                       @"name": @"boo bar",
                       @"age": @42,
                       @"comment": @"hello world"
                   }
                   database:@"testdb"
                      table:@"demotbl"
                  onSuccess:^(){
                      NSLog(@"addEvent: success");
                  }
                    onError:^(NSString* errorCode, NSString* message) {
                        NSLog(@"addEvent: error. errorCode=%@, message=%@", errorCode, message);
                    }];
                    
    // Or, simply...
    //   [[TreasureData sharedInstance] addEvent:@{
    //                     @"name": @"boo bar",
    //                     @"age": @42,
    //                     @"comment": @"hello world"
    //                 }
    //                 database:@"testdb"
    //                    table:@"demotbl"];

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. Each table will cache no more than 10000 events.

Additionally, the length of key in event must not exceed 256 chars and the length of value in event must not exceed 10000 chars.

Upload Buffered Events to Treasure Data

To upload buffered events to Treasure Data, call TreasureData's uploadEvents or uploadEventsWithCallback API.

Copy
Copied
- (void)applicationDidEnterBackground:(UIApplication *)application {
	__block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
		[application endBackgroundTask:bgTask];
		bgTask = UIBackgroundTaskInvalid;
	}];

    // You can call this API to uplaod buffered events whenever you want.
	[[TreasureData sharedInstance] uploadEventsWithCallback:^() {
			[application endBackgroundTask:bgTask];
			bgTask = UIBackgroundTaskInvalid;
		}
		onError:^(NSString *code, NSString *msg) {
			[application endBackgroundTask:bgTask];
			bgTask = UIBackgroundTaskInvalid;
		}
	];

    // Or, simply...
    //  [[TreasureData sharedInstance] uploadEvents];

When and how often you should upload buffered events depends on the characteristic of your application. Treasure Data recommends the following windows as good times to upload buffered events:

  • When the current screen is closing or moving to background
  • When closing the application

Sent events will be be buffered for a few minutes before they are imported into Treasure Data storage.

In tvOS, cache storage is stored in cache directory which can be purged at any time. It is highly recommended to call upload events APIs as requently as possible to prevent loss of data.

Retry Uploading and Deduplication

This SDK imports events in the same way with a combination of these features:

  • The SDK keeps buffered events until it receives confirmation that the events have been 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). The deduplication window is one hour by default, so do not keep buffered events for longer than that to avoid duplicated events.

Default Values

Set a default value if you want an event added to a table, a database, or any table or database to automatically set value for a key. If you have multiple default values set to the same key, newly added events will have the default value applied and overriden in following order:

  1. Default value targeting all table and database will be applied first.
  2. Default value targeting all table in a database will then be applied.
  3. Default value targeting the table to which the event is added will then be applied.
  4. Default value targeting the table and database to which the event is added will then be applied.
  5. Finally, if the event has a value for the key, that value will override all default values.

To set the default value:

Copy
Copied
[[TreasureData sharedInstance] setDefaultValue:@"Value" forKey:@"key" database:nil table:nil]; // Targeting all databases and tables
[[TreasureData sharedInstance] setDefaultValue:@"Value" forKey:@"key" database:"database_name" table:nil]; // Targeting all tables of database "database_name"
[[TreasureData sharedInstance] setDefaultValue:@"Value" forKey:@"key" database:nil table:"table_name"]; // Targeting all tables with "table_name"
[[TreasureData sharedInstance] setDefaultValue:@"Value" forKey:@"key" database:"database_name" table:"table_name"]; // Targeting table "table_name" of database "database_name"

To get the default value:

Copy
Copied
NSString *defaultValue = [[TreasureData sharedInstance] defaultValueForKey:@"key" database:"database_name" table:"table_name"]; // Get default value for key targeting database "database_name" and table "table_name".

To remove the default value:

Copy
Copied
[[TreasureData sharedInstance] removeDefaultValueForKey:@"key" database:"database_name" table:"table_name"]; // Only remove default values targeting database "database_name" and table "table_name".

Start and End Session

When you call startSession method, the SDK generates a session ID that's kept until endSession is called. The session ID is output as a column name "td_session_id". Also, startSession and endSession methods add an event that includes {"td_session_event":"start" or "end"}.

Copy
Copied
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
	[TreasureData initializeWithApiKey:@"your_api_key"];
	[[TreasureData sharedInstance] setDefaultDatabase:@"testdb"];
	[[TreasureData sharedInstance] startSession:@"demotbl"];
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
	[[TreasureData sharedInstance] endSession:@"demotbl"];

	__block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
		[application endBackgroundTask:bgTask];
		bgTask = UIBackgroundTaskInvalid;
	}];

	[[TreasureData sharedInstance] uploadEventsWithCallback:^() {
			[application endBackgroundTask:bgTask];
			bgTask = UIBackgroundTaskInvalid;
		}
		onError:^(NSString *code, NSString *msg) {
			[application endBackgroundTask:bgTask];
			bgTask = UIBackgroundTaskInvalid;
		}
		// Outputs =>>
		//   [{"td_session_id":"cad88260-67b4-0242-1329-2650772a66b1",
		//		"td_session_event":"start", "time":1418880000},
		//
		//    {"td_session_id":"cad88260-67b4-0242-1329-2650772a66b1",
		//		"td_session_event":"end", "time":1418880123}
		//    ]
	];

If you want to handle the following case, use a pair of class methods startSession and endSession for global session tracking.

  • User opens the application and starts session tracking using startSession . For example, this might be called session#0
  • User moves to home screen and finishes the session using endSession
  • User reopens the application and restarts session tracking within the default 10 seconds. However, you want to deal with this new session as the same session as session#0
Copy
Copied
- (void)applicationDidBecomeActive:(UIApplication *)application
{
	[TreasureData startSession];
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
	[TreasureData endSession];
}

In this case, you can get the current session ID using getSessionId class method

Copy
Copied
- (void)applicationDidBecomeActive:(UIApplication *)application
{
	[TreasureData startSession];
    NSLog(@"Session ID=%@", [TreasureData getSessionId]);
}

Detect if Running for the First Time

You can detect if it's the first running isFirstRun method and then clear the flag with clearFirstRun.

Copy
Copied
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
		:
    if ([[TreasureData sharedInstance] isFirstRun]) {
        [[TreasureData sharedInstance] addEventWithCallback:@{ @"event": @"installed" }
                               database:@"testdb"
                                  table:@"demotbl"
                              onSuccess:^(){
                                  [[TreasureData sharedInstance] uploadEventsWithCallback:^() {
                                      [[TreasureData sharedInstance] clearFirstRun];
                                    }
                                    onError:^(NSString* errorCode, NSString* message) {
                                      NSLog(@"uploadEvents: error. errorCode=%@, message=%@", errorCode, message);
                                    }
                                   ];
                                }
                                onError:^(NSString* errorCode, NSString* message) {
                                    NSLog(@"addEvent: error. errorCode=%@, message=%@", errorCode, message);
                                }];
    }

Advanced Use

About Error Code

When using functions with callbacks, like addEventWithCallback or uploadEventWithCallback, these methods call the onError block with an errorCode argument. This argument is useful in determining the cause or type of error. Here are the error codes:

Error code Description
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 and from JSON.
storage_error Failed to read/write data in the storage.
network_error Failed to communicate with the server due to a network problem.
server_response The server returned an error response.

Additional Configuration

Endpoint

The default API endpoint, [ https://us01.records.in.treasuredata.com ] can be changed. For example:

Copy
Copied
[TreasureData initializeWithApiKey:@"your_api_key" apiEndpoint: @"https://specifying-another-endpoint.com"];

Encryption Key

If you've set an encryption key via TreasureData.initializeEncryptionKey, the SDK saves the event data as encrypted when called TreasureData#addEvent or TreasureData.addEventWithCallback.

Copy
Copied
[TreasureData initializeEncryptionKey:@"hello world"];
 
[[TreasureData sharedInstance] addEventWithCallback: ....];

Default Database

If you specify a default database, you can substitute the "@" symbol for the database name in subsequent calls.

Copy
Copied
[[TreasureData sharedInstance] setDefaultDatabase:@"testdb"];
 
[[TreasureData sharedInstance] addEventWithCallback:@{ @"event": @"clicked" } table:@"demotbl"]

Adding UUID of the Device To Each Event Automatically

UUID of the device will be added to each event automatically if you call TreasureData#enableAutoAppendUniqId(). This value won't change until the application is uninstalled.

Copy
Copied
[[TreasureData sharedInstance] enableAutoAppendUniqId];

It outputs the value as a column named td_uuid.

Get and Reset UUID

You can get the current UUID (td_uuid) using the following API. Remember that this UUID will change if resetUniqId is called.

Copy
Copied
NSString *td_uuid = [[TreasureData sharedInstance] getUUID];

You can also reset the UUID (td_uuid) using the following API.

Copy
Copied
[[TreasureData sharedInstance] resetUniqId];

Adding a UUID to Each Event Record Automatically

UUID will be added to each event record automatically if you call enableAutoAppendRecordUUID. Each event will have a different UUID.

Copy
Copied
[[TreasureData sharedInstance] enableAutoAppendRecordUUID];
 
// If you want to customize the column name, pass it to the API
[[TreasureData sharedInstance] enableAutoAppendRecordUUID:@"my_record_uuid"];

It outputs the value as a column name record_uuid by default.

Adding Advertising ID to Each Event Record Automatically

Call enableAutoAppendAdvertisingIdentifier to automatically add an advertising ID to each event record.

You must link the Ad Support framework in the "Link Binary With Libraries" build phase for this feature to work. Users must also not turn on the Limit Ad Tracking feature in their iOS device, otherwise, Treasure Data sends a zero-filled string as the advertising ID (the value returned from the Ad Support framework).

Starting in iOS 14, you must explicitly request the user's permission for advertising identifier using the AppTrackingTransparency framework. Consult Apple's official documentation for AppTrackingTransparency on how to implement this requirement. If you turn on this feature, keep in mind that you will have to declare the correct reason for getting an advertising identifier when you submit your app for review to the App Store.

Copy
Copied
[[TreasureData sharedInstance] enableAutoAppendAdvertisingIdentifier];
 
// If you want to customize the column name, pass it to the API
[[TreasureData sharedInstance] enableAutoAppendAdvertisingIdentifier:@"custom_ad_id_column"];

It outputs the value as a column name td_maid by default.

Adding Device Model Information to Each Event Automatically

Device model information will be added to each event automatically if you call TreasureData#enableAutoAppendModelInformation.

Copy
Copied
[[TreasureData sharedInstance] enableAutoAppendModelInformation];

It outputs the following column names and values:

  • td_device : UIDevice.model
  • td_model : UIDevice.model
  • td_os_ver : UIDevice.model.systemVersion
  • td_os_type : "iOS"

Adding Application Version Information to Each Event Automatically

Call enableAutoAppendAppInformation to automatically add application version information to each event.

Copy
Copied
[[TreasureData sharedInstance] enableAutoAppendAppInformation];

It outputs the following column names and values:

  • td_app_ver : Core Foundation key CFBundleShortVersionString
  • td_app_ver_num : Core Foundation key CFBundleVersion

Adding Locale Configuration Information to Each Event Automatically

Locale configuration information will be added to each event automatically if you call TreasureData#enableAutoAppendLocaleInformation.

Copy
Copied
[[TreasureData sharedInstance] enableAutoAppendLocaleInformation];

It outputs the following column names and values:

  • td_locale_country : [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode]
  • td_locale_lang : [[NSLocale currentLocale] objectForKey: NSLocaleLanguageCode]

Auto tracking device IP

Device IP will be added to each event automatically in td_ip column if you call enableAutoTrackingIP. Note that the tracked IP address is the one when you upload the events to Treasure Data, not the one when you add the event.

Copy
Copied
[[TreasureData sharedInstance] enableAutoTrackingIP];

To disable auto tracking IP:

Copy
Copied
[[TreasureData sharedInstance] disableAutoTrackingIP];

Enable and Disable Debug Log

objectivecobjectivec
Copy
Copied
[TreasureData enableLogging];
Copy
Copied
[TreasureData disableLogging];

Automatically Track App Lifecycle Events

App lifecycle event tracking is optional and not enabled by default. You can track app lifecycle events automatically using : enableAppLifecycleEvent().

Copy
Copied
[[TreasureData sharedInstance] enableAppLifecycleEvent];

There are three types of app lifecycle events that are tracked:

  • TD_IOS_APP_OPEN
  • TD_IOS_APP_INSTALL
  • TD_IOS_APP_UPDATE (which is written to the td_ios_event column).

Here is an example of a tracked install event:

Copy
Copied
"td_ios_event" = "TD_IOS_APP_INSTALL";
"td_app_ver" = "1.1";
"td_app_ver_num" = 2;

Automatically Track In-App Purchase Events

In-app purchase event tracking is optional and not enabled by default.

The Treasure Data SDK is able to automatically track IAP SKPaymentTransactionStatePurchased events without requiring you to write your own transaction observer.

Copy
Copied
[[TreasureData sharedInstance] enableInAppPurchaseEvent];

There is a subtle difference between InAppPurchaseEvent, AppLifecycleEvent, and customEvent. The other two are persistent settings; their statuses are saved across app launches. inAppPurchaseEvent behaves like an ordinary object option and is not saved. You have to enable it after initialize your new TreasureData instance (only sharedInstance with initializeWithApiKey()). The following is an example of an IAP event.

Copy
Copied
- "td_ios_event" : "TD_IOS_IN_APP_PURCHASE",
- "td_iap_transaction_identifier" : "1000000514091400",
- "td_iap_transaction_date" : "2019-03-28T08:44:12+07:00",
- "td_iap_quantity" : 1,
- "td_iap_product_identifier" : "com.yourcompany.yourapp.yourproduct", ,
- "td_iap_product_price" : 0.99,
- "td_iap_product_localized_title" : "Your Product Title",
- "td_iap_product_localized_description" : "Your Product Description",
- "td_iap_product_currency_code" : "USD", // this is only available on iOS 10 and above

Treasure Data will do a separate SKProductsRequest to get the full information about the product. If the request fails, fields with the td_iap_product_ prefix will be null. The currency_code is only available in iOS 10 and up.

Profiles API

This feature is not enabled on accounts by default; contact Customer Support or your Customer Success representative for more information.

info

You must set cdpEndpoint property of TreasureData's sharedInstance.

Here is an example of how to look up profiles using the Profiles API.

Copy
Copied
// Set cdpEndpoint when initialize TreasureData
[[TreasureData sharedInstance] setCdpEnpoint: @"[your cdp endpoint goes here]"]
 
// Call fetchUserSegments to get user segments as NSArray
 
NSArray *audienceTokens = @[@"Your Profile API (Audience) Token here"];
NSDictionary *keys = @{@"your_key": @"your_value"};
NSDictionary<TDRequestOptionsKey, id> *options = @{
    TDRequestOptionsTimeoutIntervalKey: [NSNumber numberWithInteger: 10],
    TDRequestOptionsCachePolicyKey: [NSNumber numberWithUnsignedInteger: NSURLRequestReloadIgnoringCacheData]
};
[[TreasureData sharedInstance] fetchUserSegments:audienceTokens
                                            keys:keys
                                        options:options
                               completionHandler:^(NSArray * _Nullable jsonResponse, NSError * _Nullable error) {
    NSLog(@"fetchUserSegments jsonResponse: %@", jsonResponse);
    NSLog(@"fetchUserSegments error: %@", error);
}];

Further Reading

For additional information, refer to the iOS SDK Github Repo.