# Cocos2d-x SDK 使用指南

提示

在接入前, 请先阅读接入前准备

您可以在 GitHub (opens new window) 获取Cocos2d-x SDK 源码。

Cocos2d-x SDK 支持在iOS、Android平台运行,大小约为 6.4M

最新版本为: v1.1.0

更新时间为: 2021-08-24 下载地址 (opens new window)

# 一、初始化 SDK

# 1.1 集成 SDK

  1. 下载 Cocos2d-x SDK (opens new window) 资源文件,解压文件,把ThinkingAnalytics文件夹放入Classes文件夹

  2. CMakeLists.txt 添加如下配置

list(APPEND GAME_SOURCE
     Classes/ThinkingAnalytics/Common/TDJSONObject.cpp
     )
list(APPEND GAME_HEADER
     Classes/ThinkingAnalytics/Common/TDJSONObject.h
     Classes/ThinkingAnalytics/Common/ThinkingAnalyticsAPI.h
     )
if(ANDROID)
    list(APPEND GAME_SOURCE
         Classes/ThinkingAnalytics/Android/ThinkingAnalyticsAPI.cpp
         )
  1. 添加Android端配置
  • 在proj.android中的app目录下添加libs文件夹,把thinkingsdk.aar放入libs文件夹
  • proj.android中app目录下的build.gradle添加如下配置
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
}

  1. 添加iOS端配置
  • 使用XCode打开iOS项目,直接拖拽ThinkingAnalytics下面的iOS文件夹放入Classes/ThinkingAnalytics目录下

  • Build Setting->Other Linker Flags中的Debug和Release分别添加-all_load

  • Build Phases->Compile Sources中的ThinkingAnalytics.mm添加-fobjc-arc

# 1.2 初始化SDK

#include "./ThinkingAnalytics/Common/ThinkingAnalyticsAPI.h"
using namespace thinkingdata;
ThinkingAnalyticsAPI::init(TA_APP_ID, TA_SERVER_URL);
//支持初始化多个APPID实例
ThinkingAnalyticsAPI::init(TA_APP_ID_1, TA_SERVER_URL_1);

或者
// 获取 TDConfig 实例
Config config(TA_APP_ID, TA_SERVER_URL);
// 设置运行模式为 Debug 模式
config.setModel(DEBUG);
// 初始化 SDK
ThinkingAnalyticsAPI::init(config);
或者

注意:由于一些设备默认禁止明文传输,因此强烈建议您使用 HTTPS 格式的接收端地址。

# 二、设置用户 ID

在使用Cocos2d-x SDK 之后,SDK 默认会使用随机 UUID 作为每个用户的访客 ID,该 ID 将会作为用户在未登录状态下身份识别 ID。需要注意的是,默认访客 ID 在用户重新安装游戏以及更换设备时将会变更。

# 2.1 设置访客 ID(可选)

如果您的游戏对每个用户有自己的访客 ID 管理体系,则您可以调用 identify 来设置访客 ID:

ThinkingAnalyticsAPI::identify("cocos2dx_id");

如果需要获得访客 ID,可以调用 getDistinctId 获取:

ThinkingAnalyticsAPI::getDistinctId();

# 2.2 设置与清除账号 ID

在用户进行登录时,可调用 login 来设置用户的账号 ID,在设置完账号 ID 后,将会以账号 ID 作为用户标识 ID,并且设置的账号 ID 将会在调用 logout 之前一直保留:

// 设置账号 ID
ThinkingAnalyticsAPI::login("cocos2dx_user");

// 清除账号 ID
ThinkingAnalyticsAPI::logout();

注意:该方法不会上传用户登录、用户登出等事件。

# 三、上传事件

通过 ThinkingAnalyticsAPI::track() 可以上报事件及其属性。一般情况下,您可能需要上传十几到上百个不同的事件,如果您是第一次使用 TA 后台,我们推荐您先上传几个关键事件。

我们也支持了若干自动采集事件,包括游戏启动、关闭、安装等事件。

# 3.1 上传事件

建议您根据先前梳理的文档来设置事件的属性以及发送信息的条件。事件名称是 string 类型,只能以字母开头,可包含数字,字母和下划线 "_",长度最大为 50 个字符,对字母大小写不敏感。

TDJSONObject eventProperties;
eventProperties.setString("role", "战士");
eventProperties.setNumber("coin",1);
ThinkingAnalyticsAPI::track("thinkingdata",eventProperties);
  • 事件属性是 TDJSONObject 类型,其中每个元素代表一个属性;
  • 事件属性 Key 为属性名称,为 string 类型,规定只能以字母开头,包含数字,字母和下划线 "_",长度最大为 50 个字符,对字母大小写不敏感;
  • 属性值支持四种类型:字符串、数值类、boolList 类型。

# 3.2 设置静态公共属性

对于一些重要的属性,譬如玩家的区服和渠道等,这些属性需要设置在每个事件中,此时您可以将这些属性设置为公共事件属性。公共事件属性指的就是每个事件都会带有的属性,您可以调用 setSuperProperties 来设置公共事件属性,我们推荐您在发送事件前,先设置公共事件属性。

 TDJSONObject userProperties;
 userProperties.setString("level", "100");
 userProperties.setDateTime("dateTime","2020-01-02 10:52:52.290");
 ThinkingAnalyticsAPI::setSuperProperties(userProperties);

公共事件属性将会被保存到缓存中,无需每次启动 APP 时调用。如果调用 setSuperProperties 上传了先前已设置过的公共事件属性,则会覆盖之前的属性。如果公共事件属性和 track() 上传的某个属性的 Key 重复,则该事件的属性会覆盖公共事件属性。

如果您需要删除某个公共事件属性,可以调用 unsetSuperProperty() 清除其中一个公共事件属性;如果您想要清空所有公共事件属性,则可以调用 clearSuperProperties();如果您想要获取所有公共事件属性,可以调用getSuperProperties;

// 清除属性名为 CHANNEL 的公共属性
ThinkingAnalyticsAPI::unsetSuperProperty("CHANNEL");

// 清空所有公共属性
ThinkingAnalyticsAPI::clearSuperProperties();

// 获取所有公共属性
ThinkingAnalyticsAPI::getSuperProperties();

# 3.3 设置动态公共属性

在 v1.1.0 版本中,新增了动态公共属性的特性,即公共属性可以上报时获取当时的值,使得诸如会员等级之类的可变公共属性可以被便捷地上报。通过 setDynamicSuperProperties 设置动态公共属性类之后,SDK 将会在事件上报时自动获取属性,并添加到触发的事件中。以下例子是每次上报时将时间加入到事件中,当事件触发时,就会将 dynamicProperties 的返回值加入到事件属性中。

// 设置动态公共属性,在事件上报时动态获取事件发生时刻
TDJSONObject dynamicProperties()
{
    TDJSONObject obj;
    obj.setNumber("num",1);
    return obj;
}
ThinkingAnalyticsAPI::setDynamicSuperProperties(dynamicProperties);

# 3.4 记录事件时长

如果您需要记录某个事件持续时长,您可以调用 timeEvent() 来开始计时,配置您想要计时的事件名称,当您上传该事件时,将会自动在您的事件属性中加入 #duration 这一属性来表示记录的时长,单位为秒。

// 调用 TimeEvent 开启对 TIME_EVENT 事件的计时
ThinkingAnalyticsAPI::timeEvent("TIME_EVENT");

// do some thing...

// 通过 Track 上传 TIME_EVENT 事件时,会在属性中添加 #duration 属性
ThinkingAnalyticsAPI::track("TIME_EVENT");

# 四、用户属性

TA 平台目前支持的用户属性设置接口为 user_setuser_setOnceuser_adduser_unsetuser_deleteuser_append.

# 4.1 user_set

对于一般的用户属性,您可以调用 user_set 来进行设置,使用该接口上传的属性将会覆盖原有的属性值,如果之前不存在该用户属性,则会新建该用户属性。

TDJSONObject userProperties;
userProperties.setString("role", "战士");
userProperties.setNumber("coin",1);
ThinkingAnalyticsAPI::user_set(userProperties);

与事件属性类似:

  • 事件属性是 TDJSONObject 类型,其中每个元素代表一个属性;
  • 事件属性 Key 为属性名称,为 string 类型,规定只能以字母开头,包含数字,字母和下划线 "_",长度最大为 50 个字符,对字母大小写不敏感;
  • 属性值支持四种类型:字符串、数值类、boolList 类型。

# 4.2 user_setOnce

如果您要上传的用户属性只要设置一次,则可以调用 user_setOnce 来进行设置,当该属性之前已经有值的时候,将会忽略这条信息:

TDJSONObject userProperties;
userProperties.setString("role", "战士");
userProperties.setNumber("coin",1);
ThinkingAnalyticsAPI::user_setOnce(userProperties);

注意:user_setOnce设置的用户属性类型及限制条件与 user_set 一致。

# 4.3 user_add

当您要上传数值型的属性时,您可以调用 user_add 来对该属性进行累加操作,如果该属性还未被设置,则会赋值 0 后再进行计算,可传入负值,等同于相减操作。

TDJSONObject userProperties;
userProperties.setNumber("coin",1);
ThinkingAnalyticsAPI::user_add(userProperties);

注意: user_add 中的属性类型以及 Key 值的限制与 user_set 一致,但 Value 只允许上报数值类型属性。

# 4.4 user_unset

如果您需要重置用户的某个属性,可以调用 user_unset 将该用户指定用户属性的值清空,此接口支持传入字符串或者列表类型的参数:

ThinkingAnalyticsAPI::user_unset("coin");

# 4.5 user_delete

如果您要删除某个用户,可以调用 user_delete 将这名用户删除,您将无法再查询该名用户的用户属性,但该用户产生的事件仍然可以被查询到。

ThinkingAnalyticsAPI::user_delete();

# 4.6 user_append

您可以调用 UserAppendList 类型的用户属性追加元素:

TDJSONObject userProperties;
vector<string> listValue;
listValue.push_back("XX");
userProperties.setList("test",listValue);
ThinkingAnalyticsAPI::user_append(userProperties);

# 五、自动采集事件

ThinkingAnalytics SDK 提供了三种事件的自动采集:

  • ta_app_install: 游戏安装,当安装后首次打开游戏会采集该事件
  • ta_app_start: 游戏进入前台的时候采集该事件
  • ta_app_end: 游戏退到后台的时候采集该事件

通过调用 enableAutoTrack 接口可以开启自动采集:

// 开启自动采集
ThinkingAnalyticsAPI::enableAutoTrack();

注意: 如果您需要自定义访客 ID,请务必在开启自动采集功能之前调用 Identify 接口设置访客 ID.

# 六、其他配置选项

# 6.1 获取设备 ID

SDK 在初始化完成后,会自动生成设备 ID,并记录在本地缓存,对于同一应用/游戏,一台设备的设备 ID 是不变的,可以调用getDeviceId()获取设备 ID:

ThinkingAnalyticsAPI::getDeviceId();

// 以设备ID作为访客ID
// ThinkingAnalyticsAPI::identify(ThinkingAnalyticsAPI::getDeviceId());

# 6.2 打印上传数据 Log

ThinkingAnalyticsAPI::enableTrackLog(true);

# 6.3 暂停/停止数据上报

  1. 暂停 SDK 上报(enableTracking)

您可能希望在一些场景下,暂时停止 SDK 的数据采集以及上报,比如用户处于测试环境中、或者用户登录了一个测试账号,此时您可以调用下列接口,暂时停止 SDK 的上报。

您可以通过某一实例(包括主要实例以及轻实例)调用enableTracking,传入false来暂停 SDK 的上报,该实例已经设置的#distinct_id#account_id、公共属性等将保留;该实例已经采集但还未上报成功的数据将继续尝试上报;后续该实例不能采集以及上报任何新数据、不能设置访客 ID、账户 ID 以及公共属性等,但是可以读取该实例已经设置的公共属性和设备 ID、访客 ID、账号 ID 等信息。

实例的停止状态将会被保存在本地缓存,直到调用enableTracking、传入true,SDK 实例将会重新恢复数据采集以及上报,需要注意轻实例因为不进行缓存,因此每次打开 APP 后,轻实例的暂停状态不会被保留,将重新开启上报。

// 暂停默认实例的上报,已缓存数据和已经设置的信息不被清除
ThinkingAnalyticsAPI::enableTracking(false);

// 恢复默认实例的上报
ThinkingAnalyticsAPI::enableTracking(true);
  1. 停止 SDK 上报(optOutTracking)

在一些特殊场景下,您可能需要完全停止 SDK 的功能,比如在适用 GDPR 的地区,用户选择不提供数据采集权限,则您可以调用如下接口完全关闭 SDK 的功能。

optOutTracking只能通过主要实例调用,与enableTracking的最大区别在于,其将会清空该实例的本地缓存,包括本实例的访客 ID,账号 ID,公共属性,以及未上报的数据队列。之后再关闭该实例的采集和上报功能。

// 停止默认实例的上报, 并清空本地缓存
ThinkingAnalyticsAPI::optOutTracking();

如果您希望关闭 SDK 功能的同时,删除该用户在 TA 集群中的用户数据,可以调用optOutTrackingAndDeleteUser,这将会在停止 SDK 实例的功能前,上报一条 user_delete数据,以删除该用户的用户数据。

// 停止默认实例的上报,并发送 user_del
ThinkingAnalyticsAPI::optOutTrackingAndDeleteUser();

实例的停止状态也将保存在本地缓存,直到调用optInTracking,后续可以继续上报,但此时相当于一个全新的实例

// 重新开启上报
ThinkingAnalyticsAPI::optInTracking();

# 6.4 SDK 运行模式

SDK 支持在三种模式下运行:

  • NORMAL: 普通模式,数据会存入缓存,并依据一定的缓存策略上报
  • DEBUG: Debug 模式,数据逐条上报。当出现问题时会以日志和异常的方式提示用户
  • DEBUG_ONLY: Debug Only 模式,只对数据做校验,不会入库

注意: DEBUG 模式仅仅用于集成阶段数据校验,不要在生产模式下使用。

为了避免 Debug 模式在生产环境上线,规定只有指定的设备才能开启 Debug 模式。只有在客户端开启了 Debug 模式,并且设备 ID 在 TA 后台的"埋点管理"页的"Debug 数据"板块中配置了的设备才能开启 Debug 模式。

设备 ID 可以通过以下三种方式获取:

  • TA 平台中事件数据中的 #device_id 属性
  • 客户端日志:SDK 初始化完成后会打印设备 DeviceId
  • 通过实例接口调用:获取设备 ID

# 6.5 校准时间

SDK 默认会使用本机时间作为事件发生时间上报,如果用户手动修改设备时间会影响到您的业务分析,您可以使用从服务端获取的当前时间戳对 SDK 的时间进行校准。此后,所有未指定时间的调用,包括事件数据和用户属性设置操作,都会使用校准后的时间作为发生时间。

// 1585633785954 为当前 unix 时间戳,单位为毫秒,对应北京时间 2020-03-31 13:49:45
ThinkingAnalyticsAPI::calibrateTime(1585633785954);

我们也提供了从 NTP 获取时间对 SDK 校准的功能。您需要传入您的用户可以访问的 NTP 服务器地址。之后 SDK 会尝试从传入的 NTP 服务地址中获取当前时间,并对 SDK 时间进行校准。如果在默认的超时时间(3 秒)之内,未获取正确的返回结果,后续将使用本地时间上报数据。

// 使用苹果公司 NTP 服务对时间进行校准
ThinkingAnalyticsAPI::calibrateTimeWithNtp("time.apple.com");

注意:

  • 您需要谨慎地选择您的 NTP 服务器地址,以保证网络状况良好的情况下,用户设备可以很快的获取到服务器时间。
  • 使用 NTP 服务进行时间校准存在一定的不确定性,建议您优先考虑用时间戳校准的方式。

# 七、相关预置属性

# 7.1 获取预置属性

服务端埋点需要 App 端的一些预置属性时,可以通过此方法获取 App 端的预置属性,再传给服务端。

   //获取属性对象
   PresetProperties* presetProperties =  ThinkingAnalyticsAPI::getPresetProperties();

   //生成事件预置属性
   TDJSONObject* properties = presetProperties->toEventPresetProperties();
   /*
   {
	"#carrier": "中国电信",
	"#os": "Android",
	"#device_id": "abb8e87bfb5ce66c",
	"#screen_height": 2264,
	"#bundle_id": "com.sw.thinkingdatademo",
	"#manufacturer": "realme",
	"#device_model": "RMX1991",
	"#screen_width": 1080,
	"#system_language": "zh",
	"#os_version": "10",
	"#network_type": "WIFI",
	"#zone_offset": 8
    }
   */

    //获取某个预置属性
    string bundleId = presetProperties->bundleId;//包名
    string os =  presetProperties->os;//os类型,如Android
    string systemLanguage = presetProperties->systemLanguage;//手机系统语言类型
    int screenWidth = presetProperties->screenWidth;//屏幕宽度
    int screenHeight = presetProperties->screenHeight;//屏幕高度
    string deviceModel = presetProperties->deviceModel;//设备型号
    string deviceId = presetProperties->deviceId;//设备唯一标识
    string carrier = presetProperties->carrier;//手机SIM卡运营商信息,双卡双待时,取主卡的运营商信息
    string manufacture = presetProperties->manufacturer;//手机制造商 如HuaWei
    string networkType = presetProperties->networkType;//网络类型
    string osVersion = presetProperties->osVersion;//系统版本号
    double zoneOffset = presetProperties->zoneOffset;//时区偏移值

IP,国家城市信息由服务端解析生成,客户端不提供接口获取这些属性

# 八、进阶功能

Cocos2d-x SDK 支持上报三种特殊类型事件: 首次事件、可更新事件、可重写事件。

# 8.1 首次事件

首次事件是指针对某个设备或者其他维度的 ID,只会记录一次的事件。例如在一些场景下,您可能希望记录在某个设备上第一次发生的事件,则可以用首次事件来上报数据。

// 示例:上报设备首次事件, 假设事件名为 DEVICE_FIRST
TDJSONObject jsonObject;
jsonObject.setString("role","战士");
TDFirstEvent *firstEvent = new TDFirstEvent("DEVICE_FIRST",jsonObject);
ThinkingAnalyticsAPI::track(firstEvent);

如果您希望以设备以外的其他维度来判断是否首次,则可以为首次事件设置 FIRST_CHECK_ID. 例如您需要记录某个账号的首次事件,可以将账号 ID 设置为首次事件的 FIRST_CHECK_ID:

// 示例:上报用户账号的首次事件, 假设事件名为 USER_FIRST
TDJSONObject jsonObject;
TDFirstEvent *firstEvent = new TDFirstEvent("USER_FIRST",jsonObject);
//firstEvent->setFirstCheckId("YOUR_ACCOUNT_ID");
ThinkingAnalyticsAPI::track(firstEvent);

注意:由于在服务端完成对是否首次的校验,首次事件默认会延时 1 小时入库。

# 8.2 可更新事件

您可以通过可更新事件实现特定场景下需要修改事件数据的需求。可更新事件需要指定标识该事件的 ID,并在创建可更新事件对象时传入。TA 后台将根据事件名和事件 ID 来确定需要更新的数据。

// 示例: 上报可被更新的事件,假设事件名为 UPDATABLE_EVENT

TDJSONObject jsonObject;
jsonObject.setNumber("status", 3);
jsonObject.setNumber("price", 100);
TDUpdatableEvent *updatableEvent = new TDUpdatableEvent("UPDATABLE_EVENT",jsonObject,"test_event_id");
// 上报后事件属性 status 为 3, price 为 100
ThinkingAnalyticsAPI::track(updatableEvent);


TDJSONObject jsonObject_new;
jsonObject_new.setNumber("status", 5);
// 上报后事件属性 status 被更新为 5, price 不变
TDUpdatableEvent *updatableEvent = new TDUpdatableEvent("UPDATABLE_EVENT",jsonObject_new,"test_event_id");
ThinkingAnalyticsAPI::track(updatableEvent);

# 8.3 可重写事件

可重写事件与可更新事件类似,区别在于可重写事件会用最新的数据完全覆盖历史数据,从效果上看相当于删除前一条数据,并入库最新的数据。TA 后台将根据事件名和事件 ID 来确定需要更新的数据。

// 示例: 上报可被重写的事件,假设事件名为 OVERWRITABLE_EVENT
TDJSONObject jsonObject;
jsonObject.setNumber("status", 3);
jsonObject.setNumber("price", 100);
TDOverWritableEvent *overWritableEvent = new TDOverWritableEvent("OVERWRITABLE_EVENT",jsonObject,"test_event_id");
ThinkingAnalyticsAPI::track(overWritableEvent);


TDJSONObject jsonObject_new;
jsonObject_new.setNumber("status", 5);
TDOverWritableEvent overWritableEvent_new =  new TDOverWritableEvent("OVERWRITABLE_EVENT",jsonObject,"test_event_id");
// 上报后事件属性 status 被更新为 5, price 属性被删除
ThinkingAnalyticsAPI::track(overWritableEvent_new);

# Release Note

# v1.1.0 2021/08/24

  • 优化初始化API
  • 支持动态公共属性
  • 支持多实例,轻实例
  • 支持时间校准

# v1.0.1 2021/06/28

  • 支持预制属性获取
  • 优化对Debug模式的支持

# v1.0.0 2021/04/15

  • 支持 访客 ID 和 用户账号 的设置
  • 支持事件和用户属性上报
  • 支持启动/关闭/安装事件的自动上报
  • 支持公共属性接口
  • 支持 timeEvent 接口