Skip to main content

Advanced guide

Last updated 10/03/2026

1. Send events​

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

1.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:

//Set event properties
Map<String,Object> properties = new HashMap<String,Object>();
properties.put("product_name","Product Name");//String
try {
te.track("account_id","distinct_id","product_buy",properties);
} catch (Exception e) {
System.out.println("except:"+e);
}

1.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. To use the first-event check feature, you must set the #first_check_id field in properties, and its type must be string.

// Report a first event named device_activation, with first_check_id set to device_id
Map<String, Object> properties = new HashMap<>();
properties.put("price",100);
properties.put("status",3);
properties.put("#first_check_id","device_id");
te.trackFirst("account_id", "distinct_id", "device_activation", properties);

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

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

// Report an updatable event named UPDATABLE_EVENT
// After reporting, the event property status is 3 and price is 100
Map<String, Object> properties = new HashMap<>();
properties.put("price",100);
properties.put("status",3);
te.trackUpdate("account_id","distinct_id","UPDATABLE_EVENT","test_event_id",properties);

// After reporting, the same event property status is updated to 5, and price stays the same
Map<String, Object> protertiesNew = new HashMap<>();
protertiesNew.put("status",5);
te.trackUpdate("account_id", "distinct_id", "UPDATABLE_EVENT", "test_event_id", protertiesNew);

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

// Report an overwritable event named OVERWRITE_EVENT
// After reporting, the event property status is 3 and price is 100
Map<String, Object> properties = new HashMap<>();
properties.put("price",100);
properties.put("status",3);
te.trackOverwrite("account_id","distinct_id", "OVERWRITE_EVENT","test_event_id", properties);

// After reporting, the event property status is updated to 5, and the price property is deleted
Map<String, Object> protertiesNew = new HashMap<>();
protertiesNew.put("status",5);
te.trackOverwrite("account_id", "distinct_id", "OVERWRITE_EVENT", "test_event_id", protertiesNew);

2. User properties​

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

2.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 now TA
Map<String,Object> userProperties = new HashMap<String,Object>();
userProperties.put("user_name", "TA");
try {
te.userSet("account_id","distinct_id",userProperties);
} catch (Exception e) {
System.out.println("except:"+e);
}

//user_name is now AE
Map<String,Object> newUserProperties = new HashMap<String,Object>();
newUserProperties.put("user_name", "AE");
try {
te.userSet("account_id","distinct_id",newUserProperties);
} catch (Exception e) {
System.out.println("except:"+e);
}

2.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
Map<String,Object> userProperties = new HashMap<String,Object>();
userProperties.put("first_payment_time","2018-01-01 01:23:45.678");
try {
te.userSetOnce("account_id","distinct_id",userProperties);
} catch (Exception e) {
System.out.println("except:"+e);
}

//first_payment_time is still 2018-01-01 01:23:45.678
Map<String,Object> newUserProperties = new HashMap<String,Object>();
newUserProperties.put("first_payment_time","2018-12-31 01:23:45.678");
try {
te.userSetOnce("account_id","distinct_id",newUserProperties);
} catch (Exception e) {
System.out.println("except:"+e);
}

2.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:

Map<String,Object> userProperties = new HashMap<String,Object>();
userProperties.put("total_revenue",30);
//Upload a user property. The value of "total_revenue" is now 30
try {
te.userAdd("account_id","distinct_id",userProperties);
} catch (Exception e) {
System.out.println("except:"+e);
}

//Upload the user property again. The value of "total_revenue" is accumulated to 678
Map<String,Object> newUserProperties = new HashMap<String,Object>();
newUserProperties.put("total_revenue",648);
try {
te.userAdd("account_id","distinct_id",newUserProperties);
} catch (Exception e) {
System.out.println("except:"+e);
}

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

2.4 userAppend​

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

Map<String,Object> properties = new HashMap<String,Object>();
List<String> list = new ArrayList<>();
list.add("apple");
list.add("ball");
properties.put("user_list",list);
try{
//The value of user_list is now ["apple","ball"]
te.userAppend("account_id", "distinct_id", properties);
} catch (Exception e) {
System.out.println("except:"+e);
}

2.5 userUniqAppend​

You can call userUniqAppend to append elements to array-type user properties. Calling userUniqAppend deduplicates the appended user property values, whereas the userAppend API doesn't deduplicate, so the user property may contain duplicates.

Map<String,Object> properties = new HashMap<String,Object>();
List<String> list = new ArrayList<>();
list.add("apple");
list.add("ball");
properties.put("user_list",list);

Map<String,Object> newProperties = new HashMap<String,Object>();
List<String> newList = new ArrayList<>();
newList.add("apple");
newList.add("cube");
newProperties.put("user_list", newList);
try{
//The value of user_list is now ["apple","ball"]
te.userAppend("account_id", "distinct_id", properties);
//The value of user_list is now ["apple","apple","ball","cube"]
te.userAppend("account_id", "distinct_id",newProperties);
//The value of user_list is now ["apple","ball","cube"]
te.userUniqAppend("account_id", "distinct_id",newProperties);
} catch (Exception e) {
System.out.println("except:"+e);
}

2.6 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

// Reset multiple user properties
try {
te.userUnset("account_id", "distinct_id", "key1", "key2", "key3");
} catch (Exception e) {
System.out.println("except:"+e);
}

user_unset: The value passed in is the Key of the property to clear.

2.7 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. This operation may have irreversible consequences, so use it with caution

try{
te.userDelete("account_id","distinct_id");
} catch (Exception e) {
System.out.println("except:"+e);
}

3. Other features​

3.1 TDBatchConsumer​

Note

When the data volume is too large or the network is abnormal, data may be lost. We don't recommend using it in the production environment

Transmits data to the AE server in batches in real time, without a transmission tool. If sending fails because of network issues, the SDK retries 3 times. If it still fails, the data is stored in the buffer. You can set the buffer size, which defaults to 50, meaning that the buffer holds at most 50*20 records (20 is the batch size of each upload and can be configured).

TDAnalytics te = null;
try {
te = new TDAnalytics(new TDBatchConsumer("SERVER_URL", "APPID"));
} catch (Exception ignored){

}

Parameters:

  • APPID: The APPID of your project, which you can find on the Project Settings page in the AE backend

  • SERVER_URL: The URL that data is uploaded to

    • If you use the cloud service, enter: https://global-receiver-ta.thinkingdata.cn
    • If you use an on-premises deployment, bind a domain name to the data collection URL and configure an HTTPS certificate: https://your-domain-for-data-collection

3.2 Scheduled flush​

You can configure the interval and autoFlush parameters in Config to enable scheduled data reporting.

TDAnalytics te = null;

// e.g. TDLogConsumer
try {
TDLoggerConsumer.Config config = new TDLoggerConsumer.Config("./log");
// The cache event is reported every 10 seconds
config.setAutoFlush(true);
config.setInterval(10);
te = new TDAnalytics(new TDLoggerConsumer(config));
} catch (Exception ignored){}

// e.g. TDBatchConsumer
try {
TDBatchConsumer.Config config = new TDBatchConsumer.Config();
// The cache event is reported every 10 seconds
config.setAutoFlush(true);
config.setInterval(10);
te = new TDAnalytics(new TDBatchConsumer("url", "appId", config));
} catch (Exception ignored){}
Was this page helpful?