Skip to main content

C

Last updated 10/03/2026
tip

Before you integrate the SDK, read Pre-integration preparation.

Latest version: v2.0.0

Update time: 2023-11-30

Downloads: Source code

Note

This document applies to v2.0.0 and later. For earlier versions, see C SDK Integration Guide (V1)

1. Integrate the SDK​

  1. Download the C SDK source code, modify the CMakeLists.txt file, and build a .a file in logconsumer mode
cmake_minimum_required(VERSION 3.12)
project(thinking_data_c)
message(STATUS "[ThinkingData] CMAKE_HOST_SYSTEM: ${CMAKE_HOST_SYSTEM} ")

include_directories(include)

#################################################################

# Product Library: logging consumer
if(WIN32)
add_compile_definitions(USE_WIN)
set(CMAKE_C_FLAGS "-std=c89 -pedantic-errors -m64")
else()
add_compile_definitions(USE_POSIX)
set(CMAKE_C_FLAGS "-std=c89")
endif()
SET(TE_LIB_NAME thinkingdata)
add_library(${TE_LIB_NAME} src/thinkingdata.c src/td_json.c src/td_list.c src/td_util.c src/td_logger_consumer.c)
if(WIN32)
include_directories(thirdparty/pcre/include)
link_directories(thirdparty/pcre/lib)
target_link_libraries(${TE_LIB_NAME} pcre_x64)
endif()

Build the project to get the libthinkingdata.a file.

  1. Install Logbus

We recommend using SDK + LogBus to collect and report server-side data. To install Logbus, see the following document: LogBus user guide

2. Initialization​

The following sample code initializes the SDK:

struct TDAnalytics* ta = NULL;
struct TDConsumer* consumer = NULL;

TDConfig* config = td_init_config();
char* logPath = "LOG_DIRECTORY";
TD_ASSERT(TD_OK == td_add_string("file_path", logPath, strlen(logPath), config));

if (TD_OK != td_init_consumer(&consumer, config)) {
fprintf(stderr, "Failed to initialize the consumer.");
return 1;
}
td_free_properties(config);

if (TD_OK != td_init(consumer, &ta)) {
fprintf(stderr, "Failed to initialize the SDK.");
return 1;
}

LOG_DIRECTORY is the local folder that data is written to. Set the folder that LogBus monitors to this path, and LogBus monitors and uploads the data.

3. Common features​

To make sure that the distinct ID and account ID can be bound correctly, if your game uses both the distinct ID and the account ID, we strongly recommend that you upload both IDs. Otherwise, accounts may fail to match and users may be counted more than once. For details on ID binding rules, see User identification rules.

3.1 Send events​

You can call td_track to upload events. We recommend setting event properties and the conditions for sending data according to the document you prepared earlier. The following sample code sends an event:

// Create custom properties
TDProperties *properties = td_init_properties();
// Set the user's IP address. AE parses the user's geographic location from the IP address
TD_ASSERT(TD_OK == td_add_string("#ip", "192.168.1.1", strlen("192.168.1.1"), properties));
// Add custom properties
TD_ASSERT(TD_OK == td_add_string("channel", "ta", strlen("ta"), properties));//String
TD_ASSERT(TD_OK == td_add_int("age", 1, properties)); //Number
TD_ASSERT(TD_OK == td_add_bool("is_success", TD_TRUE, properties));//Boolean
TD_ASSERT(TD_OK == td_add_date("birthday", time(NULL), 0, properties));//Time
// Array
TD_ASSERT(TD_OK == td_append_array("arr", "value", strlen("value"), properties));
TD_ASSERT(TD_OK == td_append_array("arr", "value1", strlen("value1"), properties));
// Object
TDProperties *object = td_init_custom_properties("object");
TD_ASSERT(TD_OK == td_add_string("key", "value", strlen("value"), object));
TD_ASSERT(TD_OK == td_add_property(object, properties));
// Object group
TDProperties *object1 = td_init_custom_properties("object1");
TD_ASSERT(TD_OK == td_add_string("key", "value", strlen("value"), object1));
TD_ASSERT(TD_OK == td_append_properties("object_arr", object1, properties));
// Report event data with custom properties. Likewise, at least one of account_id and distinct_id must be set
TD_ASSERT(TD_OK == td_track("account_id", "distinct_id", "payment", properties, ta));
td_free_properties(properties);
  • The event name is of the string type. It must start with a letter, can contain digits, letters, and underscores "_", and can be up to 50 characters long.
  • Key is the name of the property and is of the string type. It must start with a letter, can contain only digits, letters, and underscores "_", and can be up to 50 characters long. Keys are not case-sensitive; AE converts all letters to lowercase
  • Value is the value of the property. Supported types are string, number, Boolean, time, object, object group, and array

User properties have the same requirements as event properties

3.2 Set user properties​

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

// user_name is TA at this point
// At least one of account_id and distinct_id must be set
TDProperties *user_properties = td_init_properties();
TD_ASSERT(TD_OK == td_add_string("user_name", "TA", strlen("TA"), user_properties));
TD_ASSERT(TD_OK == td_user_set(account_id, distinct_id, user_properties,ta));
td_free_properties(user_properties);

// user_name is AE at this point
TDProperties *user_properties2 = td_init_properties();
TD_ASSERT(TD_OK == td_add_string("user_name", "AE", strlen("AE"), user_properties2));
TD_ASSERT(TD_OK == td_user_set(account_id, distinct_id, user_properties2,ta));
td_free_properties(user_properties2);

3.3 Send data​

When you initialize the SDK with td_init_consumer(), the SDK writes collected data to disk in real time.

td_flush() syncs the file system's default memory cache to disk in real time. You generally don't need to call it manually.

td_flush(ta);

3.4 Shut down the SDK​

td_free(ta);
td_consumer_free(consumer);

Shuts down and exits the SDK. Call this API before you shut down the server to avoid losing data in the cache

4. Best practices​

struct TDAnalytics* ta = NULL;
struct TDConsumer* consumer = NULL;

TDConfig* config = td_init_config();
char* logPath = "LOG_DIRECTORY";
TD_ASSERT(TD_OK == td_add_string("file_path", logPath, strlen(logPath), config));

if (TD_OK != td_init_consumer(&consumer, config)) {
fprintf(stderr, "Failed to initialize the consumer.");
return 1;
}
td_free_properties(config);

if (TD_OK != td_init(consumer, &ta)) {
fprintf(stderr, "Failed to initialize the SDK.");
return 1;
}

// Create custom properties
TDProperties *properties = td_init_properties();
// Set the user's IP address. AE parses the user's geographic location from the IP address
TD_ASSERT(TD_OK == td_add_string("#ip", "192.168.1.1", strlen("192.168.1.1"), properties));
// Add custom properties
TD_ASSERT(TD_OK == td_add_string("channel", "ta", strlen("ta"), properties));//String
TD_ASSERT(TD_OK == td_add_int("age", 1, properties)); //Number
TD_ASSERT(TD_OK == td_add_bool("is_success", TD_TRUE, properties));//Boolean
TD_ASSERT(TD_OK == td_add_date("birthday", time(NULL), 0, properties));//Time
// Array
TD_ASSERT(TD_OK == td_append_array("arr", "value", strlen("value"), properties));
TD_ASSERT(TD_OK == td_append_array("arr", "value1", strlen("value1"), properties));
// Object
TDProperties *object = td_init_custom_properties("object");
TD_ASSERT(TD_OK == td_add_string("key", "value", strlen("value"), object));
TD_ASSERT(TD_OK == td_add_property(object, properties));
// Object group
TDProperties *object1 = td_init_custom_properties("object1");
TD_ASSERT(TD_OK == td_add_string("key", "value", strlen("value"), object1));
TD_ASSERT(TD_OK == td_append_properties("object_arr", object1, properties));
// Report event data with custom properties. Likewise, at least one of account_id and distinct_id must be set
TD_ASSERT(TD_OK == td_track("account_id", "distinct_id", "payment", properties, ta));
td_free_properties(properties);

// user_name is TA at this point
// At least one of account_id and distinct_id must be set
TDProperties *user_properties = td_init_properties();
TD_ASSERT(TD_OK == td_add_string("user_name", "TA", strlen("TA"), user_properties));
TD_ASSERT(TD_OK == td_user_set("account_id", "distinct_id", user_properties,ta));
td_free_properties(user_properties);

// user_name is AE at this point
TDProperties *user_properties2 = td_init_properties();
TD_ASSERT(TD_OK == td_add_string("user_name", "AE", strlen("AE"), user_properties2));
TD_ASSERT(TD_OK == td_user_set("account_id", "distinct_id", user_properties2,ta));
td_free_properties(user_properties2);
Was this page helpful?