Skip to main content

Advanced guide

Last updated 10/03/2026

1. Set user IDs​

By default, the SDK instance uses a random UUID as each user's default distinct ID, which serves as the user's identifier when they are 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 game has its own distinct ID management system, you can call SetDistinctId to set the distinct ID:

// Set the distinct ID to Thinker
UTDAnalytics::SetDistinctId("Thinker");

To get the distinct ID, call GetDistinctId:

FString distinctId = UTDAnalytics::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.

// The unique login identifier of the user, which corresponds to #account_id in the reported data. In this case, the value of #account_id is TA
UTDAnalytics::Login("TA");

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.

UTDAnalytics::Logout();

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

This method does not upload a logout event

2. Send 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 setting event properties and the conditions for sending events according to the document you prepared earlier. The following example tracks a user purchasing a product:

TSharedPtr<FJsonObject> Properties = MakeShareable(new FJsonObject);
Properties->SetStringField("product_name", "Product Name");
UTDAnalytics::Track("product_buy",Properties);

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 first event that occurs on a device; you can report this data as a first event.

TSharedPtr<FJsonObject> Properties = MakeShareable(new FJsonObject);
Properties->SetStringField("key", "value");
UTDAnalytics::TrackFirst("device_activation",Properties);

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:

TSharedPtr<FJsonObject> Properties = MakeShareable(new FJsonObject);
Properties->SetStringField("key", "value");
UTDAnalytics::TrackFirstWithId("account_activation", Properties,"TA");

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

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, assuming the event name is UPDATABLE_EVENT
// After reporting, the event property status is 3 and price is 100
TSharedPtr<FJsonObject> Properties = MakeShareable(new FJsonObject);
Properties->SetNumberField("status",3);
Properties->SetNumberField("price",100);
UTDAnalytics::TrackUpdate("UPDATABLE_EVENT", Properties,"test_event_id");

// After reporting, the event property status is 5 and price is 100
TSharedPtr<FJsonObject> NewProperties = MakeShareable(new FJsonObject);
NewProperties->SetNumberField("status",5);
UTDAnalytics::TrackUpdate("UPDATABLE_EVENT",NewProperties,"test_event_id");

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, assuming the event name is OVERWRITE_EVENT
// After reporting, the event property status is 3 and price is 100
TSharedPtr<FJsonObject> Properties = MakeShareable(new FJsonObject);
Properties->SetNumberField("status",3);
Properties->SetNumberField("price",100);
UTDAnalytics::TrackOverwrite("OVERWRITE_EVENT", Properties,"test_event_id");

// After reporting, the event property status is 5 and the price property is deleted
TSharedPtr<FJsonObject> NewProperties = MakeShareable(new FJsonObject);
NewProperties->SetNumberField("status",5);
UTDAnalytics::TrackOverwrite("OVERWRITE_EVENT",NewProperties,"test_event_id");

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 the user's membership level. After you set static super properties through SetSuperProperties, the SDK adds them to events as event properties when the events are collected.

TSharedPtr<FJsonObject> SuperProperties = MakeShareable(new FJsonObject);
SuperProperties->SetNumberField("vip_level",2);
UTDAnalytics::SetSuperProperties(SuperProperties);

Static super properties are saved in the cache, so you don't need to call this every time the app starts. If a property already exists, the new value overwrites the existing value; if the property did not exist before, it is created. Besides setting properties, we also provide other APIs for working with static super properties to meet day-to-day business needs.

//Get all super properties
TSharedPtr<FJsonObject> SuperProperties = UTDAnalytics::GetSuperProperties();

2.5.2 Set 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 property class through SetDynamicSuperProperties, the SDK automatically gets the dynamic super properties when an event is collected and adds them to the triggered event.

// Define the dynamic super property function
static FString TDReturnDyldParams() {
return "{\"dyld_property1\":\"value1\",\"dyld_property2\":\"value2\"}";
}
// Set dynamic super properties
void UMyDemoWidget::callSetDynamicSuperPropertiesFunction(){
// Before V1.5.0
UTDAnalytics::dynamicPropertiesMap.insert(pair<FString,FString(*)(void)>("inset your appid" ,&TDReturnDyldParams));
// Starting from V1.5.0
UTDAnalytics::SetDynamicSuperProperties(this, &UMyDemoWidget::TDReturnDyldParams, "your appid");
}

2.6 Track event duration​

To record the duration of an event, call TimeEvent to start timing and specify the name of the event you want to time. When you upload that event, the #duration property is automatically added to the event properties to indicate the recorded duration, in seconds. Note that only one timing task can run for the same event name.

//The following example measures how long a user stays on a product page
//The user enters the product page, and timing starts
UTDAnalytics::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
UTDAnalytics::Track("stay_shop", "");

Note: Windows/MacOS doesn't support recording event duration yet.

3. User properties​

The user property APIs that AE supports are UserSet, UserSetOnce, UserAdd, UserDelete, UserUnset, UserAppend, and UserUniqueAppend.

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:

//user_name is TA at this point
TSharedPtr<FJsonObject> Properties = MakeShareable(new FJsonObject);
Properties->SetStringField("user_name", "TA");
UTDAnalytics::UserSet(Properties);
//user_name is AE at this point
TSharedPtr<FJsonObject> NewProperties = MakeShareable(new FJsonObject);
NewProperties->SetStringField("user_name", "AE");
UTDAnalytics::UserSet(NewProperties);

3.2 UserSetOnce​

If the user property you want to upload only needs to be set once, call UserSetOnce. If the property already has a value, this record is ignored. The following example sets the first payment time

//first_payment_time is 2018-01-01 01:23:45.678
TSharedPtr<FJsonObject> Properties = MakeShareable(new FJsonObject);
Properties->SetStringField("first_payment_time","2018-01-01 01:23:45.678");
UTDAnalytics::UserSetOnce(Properties);
//first_payment_time is still 2018-01-01 01:23:45.678
TSharedPtr<FJsonObject> NewProperties = MakeShareable(new FJsonObject);
NewProperties->SetStringField("first_payment_time","2018-12-31 01:23:45.678");
UTDAnalytics::UserSetOnce(NewProperties);

3.3 UserAdd​

When you upload a numeric property, you can call UserAdd to accumulate its value. If the property has not been set yet, it is assigned 0 before the calculation. You can pass a negative value, which is equivalent to subtraction. The following example accumulates the total payment amount:

//total_revenue is 30 at this point
TSharedPtr<FJsonObject> Properties = MakeShareable(new FJsonObject);
Properties->SetNumberField("total_revenue",30);
UTDAnalytics::UserAdd(Properties);
//total_revenue is 678 at this point
TSharedPtr<FJsonObject> NewProperties = MakeShareable(new FJsonObject);
NewProperties->SetNumberField("total_revenue",648);
UTDAnalytics::UserAdd(NewProperties);

The property key is a string, and the Value can only be a number.

3.4 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.

UTDAnalytics::UserDelete();

3.5 UserUnset​

To reset a user property, call UserUnset to delete a property that has been set.

UTDAnalytics::UserUnset("userPropertyName");

The value passed to UserUnset is the Key of the property to clear.

3.6 UserAppend​

You can call UserAppend to append elements to a List-type user property.

TSharedPtr<FJsonObject> Properties = MakeShareable(new FJsonObject);
TArray< TSharedPtr<FJsonValue> > DataArray;
DataArray.Add(MakeShareable(new FJsonValueString("apple")));
DataArray.Add(MakeShareable(new FJsonValueString("ball")));
Properties->SetArrayField("user_list", DataArray);//Array
UTDAnalytics::UserAppend(Properties);

3.7 UserUniqueAppend​

You can call UserUniqueAppend to append to an array-type user property. UserUniqueAppend deduplicates the appended user property values, while UserAppend doesn't, so the user property can contain duplicates.

//The value of user_list is now ["apple","ball"]
TSharedPtr<FJsonObject> Properties = MakeShareable(new FJsonObject);
TArray< TSharedPtr<FJsonValue> > DataArray;
DataArray.Add(MakeShareable(new FJsonValueString("apple")));
DataArray.Add(MakeShareable(new FJsonValueString("ball")));
Properties->SetArrayField("user_list", DataArray);//Array
UTDAnalytics::UserAppend(Properties);

//The value of user_list is now ["apple","apple","ball","cube"]
TSharedPtr<FJsonObject> Properties1 = MakeShareable(new FJsonObject);
TArray< TSharedPtr<FJsonValue> > DataArray1;
DataArray1.Add(MakeShareable(new FJsonValueString("apple")));
DataArray1.Add(MakeShareable(new FJsonValueString("cube")));
Properties1->SetArrayField("user_list", DataArray1);//Array
UTDAnalytics::UserAppend(Properties1);

//The value of user_list is now ["apple","ball","cube"]
UTDAnalytics::UserUniqueAppend(Properties1);

4. Other features​

4.1 Get the device ID​

You can call GetDeviceId to get the device ID:

FString deviceId = UTDAnalytics::GetDeviceId();

4.2 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 and 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 as the time of occurrence.
// 1585633785954 is the current Unix timestamp in milliseconds, corresponding to Beijing time 2020-03-31 13:49:45
UTDAnalytics::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
UTDAnalytics::CalibrateTimeWithNtp("time.apple.com");

1. Time calibration with an NTP service involves some uncertainty. We recommend calibrating with a timestamp whenever possible.

2. Choose your NTP server address carefully so that user devices can quickly get the server time when the network is in good condition.

4.3 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

UTDAnalytics::Flush();
Was this page helpful?