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. Technically, this library supports iOS 7 and later, but we only execute OS coverage tests for iOS 8, 9, 10, 11, 12, 13 and 14. This SDK also support Apple tvOS 12 and up.

Also, there is an alternative SDK written in Swift https://github.com/recruit-lifestyle/TreasureDataSDK. Note, however, that it does not support current GDPR functionality in the mainstream TD SDKs.

Setup

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

Copy
Copied
$ gem install cocoapods

Next, add this line in your Podfile.

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

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: Framework

Download TreasureData.framework and add it and libz library into your project.

Basic Use :Objective-C

Now that you have the iOS SDK installed we are going to cover the basic usage. Name initializing an td object with your write-only API Key, add events to local buffer and upload the buffer of events.

Initialize Object

First import the Treasure Data iOS SDK library.

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

Next create the Treasure Data object and initialize it with a TD write-only API Key.

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

It is strongly reccomended to use a write-only API Key.

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

1) Login to Treasure Data Console and go to the API Key page.

2) If you dont already have a write-only API Key then create one by clicking on the Top Right, click on Actions -> Create API Key.

3) Name the new API Key and make sure to select Write-Only as the type.

4) Copy / Paste your new Write-Only API Key into the project.

Add an event to local buffer

To add an event to local buffer, you can 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.

On top of that, 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 TreasureData

To upload events buffered events to Treasure Data, you can 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];

The charachteristics of your application determine when to upload and how ofen to upload buffered events. We recommend uploading at the following intervals.

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

The sent events buffer for a few minutes before they get imported into Treasure Data storage.

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

Retry uploading and deduplication

This SDK imports events in exactly one 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 1 hours by default and prevents duplicated imports (at most once).

The deduplication window is 1 hour by default, so it's important not to keep buffered events more than 1 hour 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, a newly added event will have the default value applied and override 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 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 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 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/End session

When you call startSession method, the SDK generates a session ID that's kept until endSession is called. The session id is outputs 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 . Let's call this session session#0
  • User moves to home screen and finishes the session using endSession
  • User reopens the application and restarts session tracking within default 10 seconds. But 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 it's the first running

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

Both addEventWithCallback and uploadEventsWithCallback methods call back onError block with errorCode argument. This argument is useful to know the cause type of the error. The error codes are as follows.

  • 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:

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 .

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.

Troubleshooting

With "Data Protection" enabled, TD iOS SDK occasionally crashes

  • If your app calls the SDK's API such as TreasureData#endSession in UIApplicationDelegate applicationDidEnterBackground , check if it's likely the app calls the SDK's API several seconds after iOS is locked. If so, please make other tasks that take time and are called prior to the SDK's API run in background.
Copy
Copied
- (void)applicationWillResignActive:(UIApplication *)application
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // Some tasks that can take more than 10 seconds.
    });
}

Swift

For best practice on using Treasure Data iOS SDK with Swift please see the Swift example project.

Further Reading

Now that you have the basics down, here are some further reading materials for your reference.

Support
Copyright © 2021 Treasure Data, Inc. (or its affiliates). All rights reserved.