ⓘ 提示
Flutter 版本 >= 3.0.0
Dart Sdk 版本 >= 3.0.0 <4.0.0
Android 要求最低系统版本为 Android 4.4
iOS 要求最低系统版本为 iOS 11.0
⚠️ 迁移须知
目前 SDK 的全部功能已完成迁移(3.0.0+)? 如何迁移到新 SDK?
请查看《快速迁移指南》。
最新版本(包含 Beta 版):
(Android ONLY)
在项目根目录下 pubspec.yaml 文件中添加 SDK 依赖:
dependencies:
...
datatower_ai_core: ^{上面的最新版本}
...
或,Flutter 命令行:
$ flutter pub add datatower_ai_core
DataTower.ai Core SDK 初始化入口
static void initSDK(
String appId,
String url,
{
String channel = "",
bool isDebug = false,
int logLevel = DTLogLevel.DEBUG,
bool manualEnableUpload = false,
}
)
参数名 | 类型 | 是否必传 | 说明 | 示例 |
---|---|---|---|---|
appId | String | 是 | 项目唯一标识,创建项目后 DT 后台自动分配,请在【项目设置-项目详情】中获取 | dt_test |
url | String | 是 | 数据上报地址,创建项目后 DT 后台自动分配,请在【项目设置-项目详情】中获取 | https://xxx.roiquery.com |
channel | String | 否 | 渠道,打多渠道包时需要用到,可使用 SDK 内部提供的实现, 默认为“” | "gp" |
isDebug | bool | 否 | 是否打开调试,调试模式下将打印 log, 默认为 false,log 标签为 DataTower | true/false |
logLevel | int | 否 | log 的级别,默认为 DEBUG,仅在 isDebug 为 true 时有效 | DTLogLevel.DEBUG、DTLogLevel.INFO、DTLogLevel.WARN、DTLogLevel.ERROR |
manualEnableUpload | bool | 否 | 是否手动启动上报, 如设为 true, 则需要自行调用 enableUpload 开启上报 | true/false |
// DT SDK 初始化
DT.initSDK("app id", "serverUrl", channel: DTChannel.GP, isDebug: ture, logLevel: Log.DEBUG, manualEnableUpload: false)
可以在用户每一次登录时,调用 setAccountId
设置用户的账号 ID, DT 系统将会以账号 ID 作为身份识别 ID,多次调用 setAccountId
将覆盖先前的账号 ID。传 null 相当于登出操作。
若您的应用没有账号体系可以不设置
static Future<void> setAccountId(String? id)
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
id | String? | 是 | 自有用户系统的 id |
DTAnalytics.setAccountId("123456");
异步获取由 SDK 生成的设备标识 DT ID
static Future<String?> getDataTowerId()
final dt_id = await DTAnalytics.getDataTowerId();
// 或
DTAnalytics.getDataTowerId().then((dt_id) {
// ...
});
调用 track
设置自动上报的埋点事件和事件属性
static void track(
String eventName,
{ Map<String, Object?>? properties }
)
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
eventName | String | 是 | 事件名称 |
properties | Map<String, Object?> | 否 | 自定义事件属性 |
HashMap<String, Object> properties = {};
properties["test_property_3"] = false;
properties["test_property_4"] = 2.3;
DTAnalytics.track("test_track", properties: properties);
// or 不传属性
DTAnalytics.track("test_track");
DT 系统支持的用户属性设置类型总览说明如下
操作 | 对应事件名 | 处理规则 |
---|---|---|
覆盖用户属性 | #user_set |
对用户表进行操作,覆盖用户的原有属性值,如果之前不存在该用户属性,则会新建该用户属性,类型与覆盖操作传入属性的类型一致 |
初始化用户属性 | #user_set_once |
对用户表进行操作,初始化用户属性,如果该属性已有值存在,系统忽略本次操作 |
累加用户属性 | #user_add |
对用户表进行操作,对数值型的用户属性做累加计算,如果该属性还未被设置,则会赋值 0 后再进行计算,可传入负值等同于相减操作 |
清空用户属性值 | #user_unset |
对用户表进行操作,清空用户属性的属性值,即设置成 NULL,如果被清空的属性不存在也不会新建该属性 |
追加列表型用户属性的元素 | #user_append |
对用户表进行操作,对列表类型的用户属性追加元素,如果被追加的列表属性不存在,系统将自动生成并进行追加 |
追加并去重列表类型用户属性的元素 | #user_uniq_append |
对用户表进行操作,对列表类型的用户属性值追加元素,并会进行一次全列表去重(去重保证前后原有的元素顺序不变),如果被追加的列表属性不存在,系统将自动生成并进行追加再去重 |
对于一般的用户属性,您可以调用 userSet
来进行设置,使用该接口上传的属性将会覆盖原有的属性值,如果之前不存在该用户属性,则会新建该用户属性,类型与覆盖操作传入属性的类型一致
static void userSet(Map<String, Object?> properties)
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
properties | Map<String, Object?> | 是 | 事件属性 |
final Map<String, Object?> pro = {};
pro["user_sex_man"] = false;
pro["user_pwd"] = "1111111";
pro["user_age"] = 23;
DTAnalytics.userSet(pro);
如果您要上传的用户属性只要设置一次,则可以调用 userSetOnce
来进行设置,当该属性之前已经有值的时候,将会忽略这条信息
static void userSetOnce(Map<String, Object?> properties)
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
properties | Map<String, Object?> | 是 | 事件属性 |
final Map<String, Object?> pro = {};
pro["user_first_paid_time"] = "2020-09-23";
DTAnalytics.userSetOnce(pro);
当您要上传数值型的属性时,您可以调用 userAdd
来对该属性进行累加操作,如果该属性还未被设置,则会赋值 0 后再进行计算,可传入负值,等同于相减操作
static void userAdd(Map<String, Object?> properties)
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
properties | Map<String, Object?> | 是 | 事件属性 设置的属性 key 为字符串,Value 只允许为数值,否则操作不生效 |
Map<String, Object?> properties = {};
properties["TotalRevenue"] = 30;
DTAnalytics.userAdd(properties);
// 此时"TotalRevenue"为30
Map<String, Object?> newProperties = {};
newProperties["TotalRevenue"] = 648;
DTAnalytics.userAdd(newProperties);
// 此时"TotalRevenue"为678
当您要清空用户的用户属性值时,您可以调用 userUnset
来对指定属性进行清空操作,如果该属性还未创建,则 userUnset
不会创建该属性
static void userUnset(List<String> properties)
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
properties | List |
是 | 用户属性名称集 |
// 重置单个用户属性
DTAnalytics.userUnset(["key1"]);
// 重置多个用户属性
DTAnalytics.userUnset(["key1", "key2", "key3"]);
// 重置多个用户属性,传入字符串数组
List<String> keys = ["key1", "key2"];
DTAnalytics.userUnset(keys);
user_delete
将这名用户删除,您将无法再查询该名用户的用户属性,但该用户产生的事件仍然可以被查询到。static void userDelete()
您可以调用 userAppend
对列表类型的用户数据追加元素。
static void userAppend(Map<String, Object?> properties)
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
properties | Map<String, Object?> | 是 | 用户属性,value 仅支持 list |
ta.userAppend({ "user_list": ["apple", "ball"] });
您可以调用 userUniqAppend
对列表类型的用户数据追加唯一元素。调用 userUniqAppend
接口会对追加的用户属性进行去重, userAppend
接口不做去重,用户属性可存在重复。
static void userUniqAppend(Map<String, Object?> properties)
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
properties | Map<String, Object?> | 是 | 用户属性,value 仅支持 list |
// 此时user_list的属性值为["apple","ball"]
ta.userAppend({ "user_list": ["apple", "ball"] });
// 此时user_list的属性值为["apple","apple","ball","cube"]
ta.userAppend({ "user_list": ["apple", "cube"] });
// 此时user_list的属性值为["apple","ball","cube"]
ta.userUniqAppend({ "user_list": ["apple", "cube"] });
接口名 |
---|
reportShow |
reportPaid |
reportClick |
reportRewarded |
reportConversionByClick |
reportConversionByRewarded |
reportConversionByLeftApp |
接口名 |
---|
reportToShow |
reportShow |
reportClick |
reportRewarded |
// 上报广告开始加载事件
static void reportLoadBegin(
String id, AdTypeDart type, AdPlatformDart platform, AdMediationDart mediation, String mediationId, String seq,
{JsonMap? properties}
)
// 上报广告结束加载事件
static void reportLoadEnd(
String id, AdTypeDart type, AdPlatformDart platform, AdMediationDart mediation, String mediationId, int duration, bool result, String seq,
{int errorCode = 0, String errorMessage = "", JsonMap? properties}
)
// 上报广告预展示事件,在想展示广告之前调用
static void reportToShow(
String id, AdTypeDart type, AdPlatformDart platform, AdMediationDart mediation, String mediationId, String location, String seq,
{JsonMap? properties, String? entrance}
)
// 上报广告展示事件,在展示广告时调用
static void reportShow(
String id, AdTypeDart type, AdPlatformDart platform, AdMediationDart mediation, String mediationId, String location, String seq,
{JsonMap? properties, String? entrance}
)
// 上报广告展示失败事件,在展示广告失败时调用
static void reportShowFailed(
String id,
AdTypeDart type,
AdPlatformDart platform,
AdMediationDart mediation,
String mediationId,
String location,
String seq,
int errorCode,
String errorMessage,
{
JsonMap? properties,
String? entrance
}
)
// 上报广告关闭事件,在广告被关闭时调用
static void reportClose(
String id, AdTypeDart type, AdPlatformDart platform, AdMediationDart mediation, String mediationId, String location, String seq,
{JsonMap? properties, String? entrance}
)
// 上报广告点击事件,在广告被点击时调用
static void reportClick(
String id, AdTypeDart type, AdPlatformDart platform, AdMediationDart mediation, String mediationId, String location, String seq,
{JsonMap? properties, String? entrance}
)
// 上报广告获得奖励事件,在激励广告获取奖励后调用
static void reportRewarded(
String id, AdTypeDart type, AdPlatformDart platform, AdMediationDart mediation, String mediationId, String location, String seq,
{JsonMap? properties, String? entrance}
)
// 上报广告收益转化事件,在点击广告时调用(#ad_conversion_source = by_click)
static void reportConversionByClick(
String id, AdTypeDart type, AdPlatformDart platform, AdMediationDart mediation, String mediationId, String location, String seq,
{JsonMap? properties, String? entrance}
)
// 上报广告收益转化事件,在获得广告激励时调用(#ad_conversion_source = by_rewarded)
static void reportConversionByRewarded(
String id, AdTypeDart type, AdPlatformDart platform, AdMediationDart mediation, String mediationId, String location, String seq,
{JsonMap? properties, String? entrance}
)
// 上报广告收益转化事件,在点击广告后跳出App时调用(#ad_conversion_source = by_left_app)
static void reportConversionByLeftApp(
String id, AdTypeDart type, AdPlatformDart platform, AdMediationDart mediation, String mediationId, String location, String seq,
{JsonMap? properties, String? entrance}
)
// 上报广告展示价值事件,在广告SDK回调时调用
static void reportPaid(
String id,
AdTypeDart type,
AdPlatformDart platform,
AdMediationDart mediation,
String mediationId,
String location,
String seq,
String value,
String currency,
String precision,
{
JsonMap? properties,
String? entrance
}
)
static void _reportPaidWithCountry_(
String id,
AdTypeDart type,
AdPlatformDart platform,
String location,
String seq,
AdMediationDart mediation,
String mediationId,
String value,
String precision,
String country,
{
JsonMap? properties,
}
)
// 上报离开app事件,在点击广告链接,离开当前app(页面)时调用
static void reportLeftApp(
String id, AdTypeDart type, AdPlatformDart platform, AdMediationDart mediation, String mediationId,String location, String seq,
{JsonMap? properties, String? entrance}
)
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
seq | String | 是 | 广告系列事件的标识,需要调用 DTAdReport.generateUUID()生成 |
id | String | 是 | Network 广告单元 ID |
type | AdTypeDart | 是 | UNKNOWN = -1 // 未知 BANNER = 0 // 横幅 INTERSTITIAL = 1 // 插屏 NATIVE = 2 // 原生 REWARDED = 3 // 激励 REWARDED_INTERSTITIAL = 4 // 插屏激励 APP_OPEN = 5 // 开屏广告 MREC=6 // 中等矩形广告 |
platform | AdPlatformDart | 是 | UNDISCLOSED = -2 // 未授权 UNKNOWN = -1 // 未知 ADMOB = 0 MOPUB = 1 ADCOLONY = 2 APPLOVIN = 3 CHARTBOOST = 4 FACEBOOK = 5 INMOBI = 6 IRONSOURCE = 7 PANGLE = 8 SNAP_AUDIENCE_NETWORK = 9 TAPJOY = 10 UNITY_ADS = 11 VERIZON_MEDIA = 12 VUNGLE = 13 ADX = 14 COMBO = 15 BIGO = 16 HISAVANA = 17 APPLOVIN_EXCHANGE = 18 MINTEGRAL = 19 LIFTOFF = 20 A4G = 21 GOOGLE_AD_MANAGER = 22 FYBER = 23 MAIO = 24 CRITEO = 25 MYTARGET = 26 OGURY = 27 APPNEXT = 28 KIDOZ = 29 SMAATO = 30 START_IO = 31 VERVE = 32 LOVINJOY_ADS = 33 YANDEX = 34 REKLAMUP = 35 |
entrance | String | 否 | 广告展示入口 |
result | bool | 是 | 广告加载结果,true 为广告加载成功 |
duration | int | 是 | 广告加载时长 |
location | String | 是 | 广告位置,通常为在广告平台配置的位置值 |
errorCode | int | 否 | 失败码,值为应用接入的对应的广告平台给出的错误码 |
errorMessage | String | 否 | 失败信息,应用接入的对应的广告平台给出的错误信息 |
value | double | 是 | 广告价值,应用接入的对应的广告平台给出的广告价值信息 |
currency | String | 是 | 广告价值对应的货币单位,请传入 USD |
precision | String | 是 | 精确度,广告价值所对应的精确度 |
country | String | 是 | 广告展示所在的国家/地区信息 |
mediation | AdMediationDart | 是 | 如果不使用聚合广告平台,请传入-1 MOPUB = 0 MAX = 1 HISAVANA = 2 COMBO = 3 TOPON = 4 TRADPLUS = 5 TOBID = 6 |
mediationId | String | 是 | 聚合平台广告单元 ID |
properties | Map<String, Object?> | 否 | 应用自定义的额外属性 |
场景一:独立广告平台
可参考:Android
场景二:聚合广告平台(Mediation)
由于聚合广告平台展示广告的时候,通常没有返回具体是哪个广告平台(Network)的广告和对应信息,所以需要在回调中判断,如 onAdShowed 回调
// 聚合广告平台一般会返回广告相关的信息 AdInfo
@override
void onAdShowed(ad: AdInfo){
// 需自行实现 getAdPlatform() 、getAdUnit()方法
final adPlatform = getAdPlatform(ad)
final adUnit = getAdUnit(ad)
// 4. 广告展示成功
DTAdReport.reportShow(adUnit, AdTypeDart.INTERSTITIAL, adPlatform,location, seq)
}
其他回调类似
DT 平台提供两种方式进行三方归因集成
如果您需将 DT 数据从服务端发送至三方平台,请初始化三方 SDK 之后获取三方设备 ID,然后使用 DT SDK 进行数据上报。传入 null 可进行清空。
// 需先获取对应 id
// Firebase
DTAnalytics.setFirebaseAppInstanceId("");
// AppsFlyer
DTAnalytics.setAppsFlyerId("");
// Adjust
DTAnalytics.setAdjustId("");
// Kochava
DTAnalytics.setKochavaId("");
// Tenjin
DTAnalytics.setTenjinId("");
调用接口 | 对应三方平台 | 公共事件属性 | 用户属性 |
---|---|---|---|
setFirebaseAppInstanceId() | Firebase | #firebase_iid | #latest_firebase_iid |
setAppsFlyerId() | AppsFlyer | #appsflyer_id | #latest_appsflyer_id |
setAdjustId() | Adjust | #adjust_id | #latest_adjust_id |
setKochavaId() | Kochava | #kochava_id | #latest_kochava_id |
setTenjinId() | Tenjin | #tenjin_id | #latest_tenjin_id |
如果您需要在 DT 系统中接入 Adjust 归因数据,则需要在 DT SDK 初始化完成后,获取 DataTower Id 并调用 Adjust.addSessionCallbackParameter
将 DataTower Id 进行上报即可
// 假设有个初始化 Adjust SDK 的方法 foo
Future<void> foo(String appToken, AdjustEnvironment environment) {
return DTAnalytics.getDataTowerId().then((dataTowerId) {
// ...
// 请注意:下面一行代码必须要在 Adjust.start() 之前调用.
Adjust.addSessionCallbackParameter('dt_id', 'dataTowerId');
// 初始化 Adjust SDK
AdjustConfig config = AdjustConfig(appToken, environment);
Adjust.start(config);
});
}
如果您需要记录某个事件的持续时长,可以调用 DTAnalyticsUtils
来开始计时。
在事件开始时,调用 trackTimerStart
并不会真正发送事件;在事件结束时调用 trackTimerEnd
,SDK 会上报 "event" 事件,并自动在"event" 事件属性中加入 #duration
这一属性来表示记录的事件持续时长。多次调用 trackTimerStart
\ trackTimerPause
时,事件 "event" 的开始时间\暂停时间以最后一次调用时为准。多次调用 trackTimerEnd
\ trackTimerResume
时,事件 "event" 的结束时间\恢复时间以最先一次调用时为准。
// 开始事件计时
DTAnalyticsUtils.trackTimerStart("event");
// 如果需要暂停事件计时
DTAnalyticsUtils.trackTimerPause("event");
// 如果需要恢事件计时
DTAnalyticsUtils.trackTimerResume("event");
// 结束事件计时, properties 为自定义属性,Map<String, __Object?__> 或者 JSONObject,可不传
DTAnalyticsUtils.trackTimerEnd("event", properties);
如需为所有事件添加属性,可以使用公共属性接口进行设置。
静态公共属性会使用持久化存储,应用退出再开启时,原先设置的值会保持不变。
final props = {};
// 设置
DTAnalytics.setStaticCommonProperties(props);
// 清除
DTAnalytics.clearStaticCommonProperties();
动态公共属性会在调用相关事件上报接口时动态地进行公共属性的获取,应用重启后需重新设置。
Map<String, Object?> props = {};
// 设置
DTAnalytics.setDynamicCommonProperties(() => props);
prop["key_sample"] = 20;
// Track 时会调用动态公共属性的函数来获取公共属性,并进行上报,(此时包含 "key_sample": 20)
DTAnalytics.track("simple_event");
// 清除
DTAnalytics.clearDynamicCommonProperties();
SDK默认情况下会有一些自动采集的行为,包括预置事件和用户事件
自动采集事件 | 时机 |
---|---|
#app_install(app安装) | App 首次启动,调用 DT.initSDK() 时 |
#session_start(app打开 | App 启动,调用 DT.initSDK() 时、App 从后台切换到前台时(对应 resume) |
#session_end(app关闭) | App 从前台切换到后台时(对应 pause) |
在某些场景下,您可能不希望有任何预置事件的上报,SDK 提供了接口来实现对预置事件的采集与上报的控制。
// 禁用预置事件
DT.disableAutoTrack(DTPresetEvent);
// 取消禁用
DT.enableAutoTrack(DTPresetEvent);
需传入枚举类型 PresetEvent,支持的预置事件。默认为不禁用:
用户事件类型 | 自动上报说明 |
---|---|
user_set | 在每次初始化时,自动上报,用于更新用户最新的属性(#latest_xxx),当最新值未发生变化时,不会上报 |
user_set_once | 用于记录用户激活时的属性(#active_xxx),仅上报一次,相关属性上报过一次就不再上报 |
当您在使用过程中,不希望上报DT的预置属性时,可通过配置文件的方式实现
特殊说明
以下预置属性不可关闭:
属性 | 说明说明 |
---|---|
#bundle_id | 应用包名,属于DT内置字段 |
#app_id | DT的app_id,上报数据的必备字段 |
#debug | 判断该条数据是否是debug |
#dt_id | 上报数据的必备字段,用于用户识别 |
#acid | 用于用户识别 |
#session_id | 会话事件唯一id,标识回话 |
#sdk_type | 判断SDK类型 |
#sdk_version_name | 判断SDK版本 |
配置方式
示例
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="DTDisPresetProperties">
<item>#os_lang_code</item>
<item>#os_version_name</item>
</string-array>
</resources>