Skip to main content

Advanced guide

Last updated 10/03/2026

1. Set user IDs​

By default, the SDK uses DeviceID_InstallCount as each user's default distinct ID. The distinct ID is used as the user's identifier while the user is not logged in. Note that the distinct ID changes when the user reinstalls the App or switches devices.

1.1 Set the distinct ID​

tip

In general, you don't need to customize the distinct ID. Make sure you understand the user identification rules before you set a distinct ID.

If you need to replace the distinct ID, call the method immediately after the SDK is initialized. Do not call it multiple times, to avoid creating useless accounts.

If your app has its own distinct ID management system for each user, you can call setDistinctId to set the distinct ID:

[TDAnalytics setDistinctId:@"Thinker"];

To get the current distinct ID, call getDistinctId:

NSString *distinctId = [TDAnalytics getDistinctId];

1.2 Set the account ID​

When a user logs in, you can call login to set the user's account ID. The AE platform uses the account ID as the identifier, and the account ID you set is kept until logout is called. Calling login multiple times overwrites the previous account ID.

[TDAnalytics login:@"TD"];

This method does not upload a login event

1.3 Clear the account ID​

After a user logs out, you can call logout to clear the account ID. Until login is called again, the distinct ID is used as the identifier.

[TDAnalytics logout];

We recommend calling logout only on explicit logout events, for example when the user deletes their account, rather than when the app is closed.

This method does not upload a logout event

2. Track events​

After the SDK is initialized, you can start tracking data to collect user behavior. In most cases, regular events meet business needs. You can also use first events, updatable events, and other event types based on your actual business scenarios.

2.1 Regular events​

You can call track to upload events. We recommend that you set event properties and the conditions for sending events based on your tracking plan. The following example tracks a user purchasing a product:

NSDictionary *eventProperties = @{@"product_name": @"book"};
[TDAnalytics track:@"product_buy" properties:eventProperties];

2.2 First events​

A first event is an event that is recorded only once for a given device or an ID of another dimension. For example, in some scenarios you may want to record the activation event on a device; you can report this data as a first event.

TDFirstEventModel *firstModel = [[TDFirstEventModel alloc] initWithEventName:@"device_activation"];
firstModel.properties = @{@"key":@"value"};
[TDAnalytics trackWithEventModel:firstModel];

If you want to determine whether an event is the first one based on a dimension other than the device, you can customize first_check_id for the first event:

TDFirstEventModel *firstModel = [[TDFirstEventModel alloc] initWithEventName:@"device_activation" firstCheckID:@"TD"];
firstModel.properties = @{@"key":@"value"};
[TDAnalytics trackWithEventModel:firstModel];

Note: Because the first-event check is performed on the server, first events are stored with a 1-hour delay.

2.3 Updatable events​

You can use updatable events to modify event data in specific scenarios. An updatable event requires an ID that identifies the event, which you pass in when you create the updatable event object. The AE backend determines which data to update based on the event name and event ID.

// Example: Report an updatable event. Assume the event name is UPDATABLE_EVENT
// After reporting, the event property status is 3 and price is 100
TDUpdateEventModel *updateModel = [[TDUpdateEventModel alloc] initWithEventName:@"UPDATABLE_EVENT" eventID:@"test_event_id"];
updateModel.properties = @{@"status": @3, @"price": @100};
[TDAnalytics trackWithEventModel:updateModel];

// After reporting, the event property status is updated to 5, and price is unchanged
TDUpdateEventModel *updateModelNew = [[TDUpdateEventModel alloc] initWithEventName:@"UPDATABLE_EVENT" eventID:@"test_event_id"];
updateModelNew.properties = @{@"status": @5};
[TDAnalytics trackWithEventModel:updateModelNew];

2.4 Overwritable events​

Overwritable events are similar to updatable events, except that an overwritable event completely overwrites historical data with the latest data. In effect, the previous record is deleted and the latest data is ingested. The AE backend determines which data to update based on the event name and event ID.

// Example: Report an overwritable event. Assume the event name is OVERWRITE_EVENT
// After reporting, the event property status is 3 and price is 100
TDOverwriteEventModel *overwriteModel = [[TDOverwriteEventModel alloc] initWithEventName:@"OVERWRITE_EVENT" eventID:@"test_event_id"];
overwriteModel.properties = @{@"status": @3, @"price": @100};
[TDAnalytics trackWithEventModel:overwriteModel];

// After reporting, the event property status is 5, and the price property is deleted
TDOverwriteEventModel *overwriteModel_new = [[TDOverwriteEventModel alloc] initWithEventName:@"OVERWRITE_EVENT" eventID:@"test_event_id"];
overwriteModel_new.properties = @{@"status": @5};
[TDAnalytics trackWithEventModel:overwriteModel_new];

2.5 Super properties​

Super properties are properties that are uploaded with every event. Based on how often they are updated, super properties are divided into static super properties and dynamic super properties. You can choose different ways to set super properties based on your business scenarios. We recommend setting super properties before sending events. For the same event, when a super property, a custom event property, and a preset property have the same key, values are assigned in the following order of priority: custom properties > dynamic super properties > static super properties > preset properties.

2.5.1 Static super properties​

Static super properties are properties that change infrequently and are carried by every event, such as a user's membership level. After you set static super properties through setSuperProperties, the SDK adds them to each event as event properties when the event is collected.

[TDAnalytics setSuperProperties:@{@"vip_level": @(2)}];

Static super properties are saved in the cache, so you don't need to set them every time the App starts. If a property already exists, the newly set value overwrites the original value. If the property doesn't exist, a new property is created. In addition to setting properties, we also provide other APIs for working with static super properties to meet everyday business needs.

// Clear one super property: clear the previously set "isTest" property
[TDAnalytics unsetSuperProperty:@"isTest"];

// Clear all super properties
[TDAnalytics clearSuperProperties];

//Get all super properties
[TDAnalytics getSuperProperties];

2.5.2 Dynamic super properties​

Dynamic super properties are properties that change frequently and are carried by every event, such as the number of coins a user has. After you set the dynamic super properties with setDynamicSuperProperties, the SDK gets the dynamic super properties when an event is collected and adds them to the triggered event.

// Set dynamic super properties to get the time of the event dynamically when the event is reported
[TDAnalytics setDynamicSuperProperties:^NSDictionary * _Nonnull{
return @{@"now": [NSDate date]};
}];

2.6 Track event duration​

To record how long an event lasts, call timeEvent to start timing. Specify the name of the event you want to time; when you upload that event, the #duration property is automatically added to its event properties to indicate the recorded duration in seconds. Note that only one timing task can run for the same event name at a time.

// The following example measures how long a user stays on a product page
[TDAnalytics timeEvent:@"stay_shop"];
/*
do someting .......
*/
// The user leaves the product page and timing ends. The "stay_shop" event carries the #duration property, which indicates the event duration
[TDAnalytics track:@"stay_shop"];

3. User properties​

The user property APIs supported by the AE platform are userSet, userSetOnce, userAdd, userUnset, userDelete, userAppend, and userUniqAppend.

3.1 userSet​

For general user properties, you can call userSet to set them. Properties uploaded through this API overwrite the original values. If the user property doesn't exist yet, it is created with the same type as the value passed in. The following example sets the username:

//Now "username" is "ThinkingData"
[TDAnalytics userSet:@{@"username": @"ThinkingData"}];
//Now "username" is "TA"
[TDAnalytics userSet:@{@"username": @"TA"}];

3.2 userSetOnce​

If a user property only needs to be set once, you can call userSetOnce to set it. If the property already has a value, this call is ignored. The following example sets the first payment time:

// first_payment_time is 2018-01-01 01:23:45.678
[TDAnalytics userSetOnce:@{@"first_payment_time": @"2018-01-01 01:23:45.678"}];
// first_payment_time is still 2018-01-01 01:23:45.678
[TDAnalytics userSetOnce:@{@"first_payment_time": @"2018-12-31 01:23:45.678"}];

3.3 userAdd​

To upload a numeric property, you can call userAdd to accumulate it. If the property hasn't been set yet, it is assigned 0 before the calculation. You can pass in a negative value, which is equivalent to subtraction. The following example accumulates the total payment amount:

//Now total_revenue is 30
[TDAnalytics userAdd:@{@"total_revenue": @30}];

//Now total_revenue is 678
[TDAnalytics userAdd:@{@"total_revenue": @648}];

3.4 userUnset​

To clear the value of a user property, you can call userUnset to clear the specified property. If the property hasn't been created in the cluster yet, userUnset doesn't create it

// Clear the user's total payment amount property value
[TDAnalytics userUnset:@"total_revenue"];

3.5 userDelete​

To delete a user, you can call userDelete. After that, you can no longer query this user's user properties, but the events generated by the user can still be queried.

[TDAnalytics userDelete];

3.6 userAppend​

You can call userAppend to append elements to an array-type user property.

// Call userAppend to append elements to the user property product_buy. If the property doesn't exist, it's created
[TDAnalytics userAppend:@{@"product_buy": @[@"apple", @"ball"]}];

3.7 userUniqAppend​

Starting from v2.8.0, you can call userUniqAppend to append elements to user properties of the array type.

userUniqAppend deduplicates the appended user property values. userAppend doesn't deduplicate, so the user property can contain duplicates.

// Now the value of user_list is ["apple","ball"]
[TDAnalytics userAppend:@{@"user_list":@[@"apple", @"ball"]}];
// Now the value of user_list is ["apple","apple","ball","cube"]
[TDAnalytics userAppend:@{@"user_list":@[@"apple", @"cube"]}];
// Now the value of user_list is ["apple","ball","cube"]
[TDAnalytics userUniqAppend:@{@"user_list":@[@"apple", @"cube"]}];

4. Encryption​

Starting from v2.8.0, the SDK supports encrypting data with AES+RSA. Data encryption requires cooperation between the client and the server. For details, contact your customer success representative.

TDConfig *sdkConfig = [[TDConfig alloc] initWithAppId:appid serverUrl:url];
NSString *publicKey = @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzA......QIDAQAB";
// Configure key information such as the version number and public key
[sdkConfig enableEncryptWithVersion:1 publicKey:publicKey];
[TDAnalytics startAnalyticsWithConfig:sdkConfig];

5. Integrate with H5 pages​

To connect with the JavaScript SDK that collects data from H5 pages, call the following API. For details, see the Connect H5 with the app SDK section

WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.applicationNameForUserAgent = [NSString stringWithFormat:@"%@ %@", config.applicationNameForUserAgent ?: @"", @"/td-sdk-ios"];

6. Other features​

6.1 Get the device ID​

You can call getDeviceId to get the device ID:

[TDAnalytics getDeviceId];

6.2 Set the default time zone​

By default, the SDK reports the local device time at the moment of the API call as the event time. You can also specify a default time zone through the API for setting the default time zone, so that the event time of all events is aligned to the time zone you set:

TDConfig *config = [[TDConfig alloc] init];
// Set the default time zone to UTC
config.defaultTimeZone = [NSTimeZone timeZoneWithName:@"UTC"];
[TDAnalytics startAnalyticsWithConfig:config];

Note: Aligning the event time to a specified time zone discards the device's local time zone information. To keep the device's local time zone information, you currently need to add the relevant properties to events yourself.

6.3 Calibrate time​

By default, the SDK uses the local device time as the event time. If users manually change the device time, your business analysis may be affected. In this case, you can calibrate the time to keep the event time accurate. We provide two time calibration methods: timestamp, NTP.

  • You can calibrate the SDK time with the current timestamp obtained from the server. After that, all calls that don't specify a time, including event data and user property operations, use the calibrated time.
// 1585633785954 is the current Unix timestamp in milliseconds, which corresponds to 2020-03-31 13:49:45 Beijing time
[TDAnalytics calibrateTime:1585633785954];
  • You can also set an NTP server address. The SDK then tries to get the current time from that NTP server and calibrates the SDK time. If no correct response is received within the default timeout (3 seconds), data is reported with the local time afterward.
// Calibrate the time with Apple's NTP service
[TDAnalytics calibrateTimeWithNtp:@"time.apple.com"];
  • Time calibration with an NTP service involves some uncertainty. We recommend that you calibrate with a timestamp first
  • Choose your NTP server address carefully, so that user devices can get the server time quickly when the network is in good condition

6.4 Flush data immediately​

In some business scenarios, if you want data to be reported to the AE server immediately, you can call the flush API

[TDAnalytics flush];

6.5 Get the country/region code​

In some business scenarios, if you need to know the country/region code of the user's device, you can get it through getLocalRegion

[TDAnalytics getLocalRegion];

6.6 Report data via IP​

To prevent or resolve issues where client data can't be reported to the server because of DNS hijacking, the SDK resolves the ServerUrl to get the IP and then reports data directly to the server via the IP. The following example shows how to enable it:

NSString *appId = @"appId";
NSString *serverUrl = @"serverUrl";
TDConfig *config = [[TDConfig alloc] initWithAppId:appId serverUrl:serverUrl];

[config enableDNSServcie:@[TDDNSServiceCloudALi, TDDNSServiceCloudGoogle, TDDNSServiceCloudFlare]];

[TDAnalytics startAnalyticsWithConfig:config];

6.7 SDK error callback​

note

Requires SDK version >= 3.3.0

In some scenarios, you may want to perform custom actions when a network request fails. In this case, you can register an errorCallback, as shown in the following example:

[TDAnalytics registerErrorCallback:^(NSInteger code, NSString * _Nullable errorMsg, NSString * _Nullable ext) {

}];

Error codes for code

Error codeDescription
1001Network request failed

6.8 Disable fetching configuration on initialization​

Starting from version 3.4.0, if you don't need to fetch configuration when the SDK is initialized, you can turn it off through disableRConfig. The code is as follows:

#import <ThinkingSDK/ThinkingSDK.h>

NSString *appid = @"APPID";
NSString *url = @"SERVER_URL";

TDConfig *config = [[TDConfig alloc] init];
config.appid = appid;
config.serverUrl = url;
config.disableRConfig = true;
[TDAnalytics startAnalyticsWithConfig:config];

6.9 Configure backup reporting URLs​

Starting from version 3.4.0, if you need to configure multiple reporting URLs, you can configure them through backupUrlList. Sample code:

#import <ThinkingSDK/ThinkingSDK.h>

NSString *appid = @"APPID";
NSString *url = @"SERVER_URL";

TDConfig *config = [[TDConfig alloc] init];
config.appid = appid;
config.serverUrl = url;
config.backupUrlList = @[@"serverUrl1", @"serverUrl2"];
[TDAnalytics startAnalyticsWithConfig:config];
Was this page helpful?