iOS SDK 使用指南
本文将会为您介绍如何使用 iOS SDK 接入您的项目,您可以访问 GitHub 获取 iOS SDK 的源代码。
最新版本为: 2.6.1
更新时间为: 2020-08-25
1. 集成与初始化 SDK
1.1 自动集成 SDK
使用 CocoaPods 安装 SDK
1.创建并编辑 Podfile 内容(如果已有,直接编辑):
创建 Podfile,项目工程(.xcodeproj
)文件同目录下命令行执行命令:
pod init
编辑 Podfile 的内容如下:
platform :ios, '9.0'
target 'YourProjectTarget' do
pod 'ThinkingSDK' #ThinkingSDK
end
2.执行安装命令
pod install
成功以后,会出现如下记录:
3.导入成功,启动工程
命令执行成功后,会生成 .xcworkspace
文件,说明您已成功导入 iOS SDK
。打开 .xcworkspace
文件以启动工程(注意:此时不能同时开启 .xcodeproj
文件)
1.2 手动集成 SDK
1.下载并解压 iOS SDK
2.将 ThinkingSDK.framework
以及 TDAnalyticsSDK.bundle
拖入 XCode Project Workspace 工程项目中
3.修改工程设置 Targets 选项下的 Build Settings 选项卡中 Other linker flags 的设置 添加 -ObjC
4.切换到 Build Phases 选项卡,在 Link Binary With Libraries 栏目下添加如下依赖项:
libz.dylib
、Security.framework
、SystemConfiguration.framework
、libsqlite3.tbd
1.3 初始化 SDK
在 v1.2.0 版本中,新增多 APP ID 实例的特性,关于多 APPID 的使用指南,请参考 iOS SDK 多 APPID 指南一节
在 AppDelegate.m 中添加 #import <ThinkingSDK/ThinkingAnalyticsSDK.h>
然后在 application:didFinishLaunchingWithOptions:
中添加初始化
如下
// 初始化
ThinkingAnalyticsSDK *instance = [ThinkingAnalyticsSDK startWithAppId:APP_ID withUrl:SERVER_URL];
// 支持初始化多个APPID实例
// ThinkingAnalyticsSDK *instance2 = [ThinkingAnalyticsSDK startWithAppId:APP_ID2 withUrl:SERVER_URL2];
// 初始化
let instance = ThinkingAnalyticsSDK.start(withAppId: "YOUR_APPID", withUrl: "YOUR_SERVER_URL")
// 支持初始化多个APPID实例
// let instance2 = ThinkingAnalyticsSDK.start(withAppId: "YOUR_APPID2", withUrl: "YOUR_SERVER_URL2")
参数 APP_ID
是您的项目的 APP_ID ,在您申请项目时会给出,请在此处填入
参数 SERVER_URL
为数据上传的 URL
如果您使用的是云服务,请输入以下 URL:
https://receiver.ta.thinkingdata.cn
如果您使用的是私有化部署的版本,请输入以下 URL:
https://数据采集地址
使用 https 协议,请自行申请具有 SSL 证书的域名,TA 工作人员将会协助进行端口配置。
在完成初始化后,您可以按以下方式来使用 SDK :
// 后续可以通过如下两种方法使用 SDK
[instance track:@"event_name" properties:eventProperties];
// [[ThinkingAnalyticsSDK sharedInstanceWithAppid:APP_ID] track:@"event_name" properties:eventProperties];
// v1.2.0版本之前,或者单实例可使用下列使用 SDK
// [[ThinkingAnalyticsSDK sharedInstance] track:@"event_name" properties:eventProperties];
// 后续可以通过如下两种方法使用 SDK
let properties:Dictionary<String,String>=["key":"value"];
instance.track("event_name", properties:properties)
// v1.2.0版本之前,或者单实例可使用下列使用 SDK
// ThinkingAnalyticsSDK.sharedInstance(withAppid: "YOUR_APPID").track("event_name", properties:eventProperties)
1.4 后台自启事件说明
iOS 12 及以下版本(iOS 13 没有使用 EnableSceneSupport
)时,后台自启事件默认不统计,通过 trackRelaunchedInBackgroundEvents
来配置,YES
表示采集,NO
表示不采集。
iOS 13 使用了 EnableSceneSupport
,必须传入 launchOptions
参数。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// ...
TDConfig *config = [[TDConfig alloc] init];
config.launchOptions = launchOptions;
config.trackRelaunchedInBackgroundEvents = YES;
ThinkingAnalyticsSDK *instance = [ThinkingAnalyticsSDK startWithAppId:@"YOUR_APPID" withUrl:@"YOUR_SERVER_URL" withConfig:config];
return YES;
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let config = TDConfig()
config.launchOptions = launchOptions ?? [:]
config.trackRelaunchedInBackgroundEvents = true
ThinkingAnalyticsSDK.start(withAppId: "APP_ID", withUrl: "SERVICE_URL", with: config)
return true
}
1.5 开启与 H5 页面的打通(可选)
如果需要与采集 H5 页面数据的 JavaScript SDK 进行打通,请调用如下接口,详情请参考 H5 与 APP SDK 打通一节
// 打通H5页面数据
[instance addWebViewUserAgent];
// [[ThinkingAnalyticsSDK sharedInstanceWithAppid:APP_ID] addWebViewUserAgent];
// 打通H5页面数据
instance.addWebViewUserAgent()
2. 设置用户 ID
SDK 实例会使用随机 UUID 作为每个用户的默认访客 ID,该 ID 将会作为用户在未登录状态下身份识别 ID。需要注意的是,访客 ID 在用户重新安装 App 以及更换设备时将会变更。
a) 设置访客 ID(可选)
如果用户在您的产品中可以未登录状态下使用,且您需要配置用户在未登录状态下的访客 ID ,则您可以调用 identify:
来进行设置:
[instance identify:@"123ABCabc"];
instance.identify("123ABCabc")
如果需要获得当前访客 ID,可以调用 getDistinctId
获取:
// 返回访客 ID,多实例的情况下,返回的是调用实例的访客 ID
[instance getDistinctId];
// 返回访客 ID,多实例的情况下,返回的是调用实例的访客 ID
instance.getDistinctId()
b) 设置账号 ID
在用户进行登录时,可调用 login:
来设置用户的账号 ID, TA 平台优先以账号 ID 作为身份标识,设置后的账号 ID 将会被保存,多次调用 login:
将覆盖先前的账号 ID :
[instance login:@"123ABCabc@thinkingdata.cn"];
instance.login("123ABCabc@thinkingdata.cn")
请注意,该方法不会上传用户登录的事件
c) 清空账号 ID
在用户产生登出行为之后,可调用 logout
来清除账号 ID ,在下次调用 login:
之前,将会以访客 ID 进行身份识别
[instance logout];
instance.logout()
我们推荐您在显性的登出事件时调用 logout
,比如用户产生注销行为时才调用,不需要在关闭 App 时进行调用。
请注意,该方法不会上传用户登出的事件
3. 发送事件
在 SDK 初始化完成之后,您就可以调用 track:
、 track:properties:
来上传事件,一般情况下,您可能需要上传 20~100 个不同的事件,如果您是第一次使用 TA 后台,我们推荐您先上传几个关键事件。
a) 发送事件
您可以调用 track:
、 track:properties:
来上传事件,建议您根据先前梳理的文档来设置事件的属性以及发送信息的条件:
// 该事件没有设置属性
[instance track:@"StartApp"];
// 上传购买商品事件
NSDictionary *eventProperties = @{
@"product_name": @"商品名",
@"product_num": @(1),
@"IsFirstBuy": @(YES)
};
[instance track:@"product_buy" properties:eventProperties];
// 该事件没有设置属性
instance.track("StartApp")
// 上传购买商品事件
let properties = [
"productName": "商品名",
"productNumber": 1,
"isFirstBuy": true
] as [String: Any]
ThinkingAnalyticsSDK.sharedInstance()?.track("event_name", properties: properties)
事件的名称是 NSString
类型,只能以字母开头,可包含数字,字母和下划线“_”,长度最大为50个字符,对字母大小写不敏感。
- 事件的属性是一个
NSDictionary
对象,其中每个元素代表一个属性。 - Key的值为属性的名称,为
NSString
类型,规定只能以字母开头,包含数字,字母和下划线“_”,长度最大为50个字符,对字母大小写不敏感。 - Value为该属性的值,可以为
NSString
、NSNumber
、NSDate
以及NSArray
。 - 如果您需要上传布尔型的属性,则请以
@YES
与@NO
或[NSNumber numberWithBool:YES]
与[NSNumber numberWithBool:NO]
来赋值。 不可以使用@true
、@false
、@TRUE
和@FALSE
赋值布尔型数据。
注意: NSArray 类型在 v2.4.0 版本开始支持,需配合 TA 后台 v2.5 及后续版本使用. 在 v2.2.0 版本中加入了设置事件触发时间及时间偏移的方法重载,支持传入
NSDate
类型的参数来设置事件触发时间,以NSTimeZone
类型的参数来设置时间偏移。不传入该参数,则取track:
被调用时的本机时间以及偏移作为事件触发时间以及时区偏移:
NSDictionary *properties = @{
@"product_name": @"商品名",
@"product_num": @1,
@"IsFirstBuy": @YES
};
[instance track:@"product_buy"
properties:properties
time:[NSDate date]
timeZone:[NSTimeZone timeZoneWithName:@"Asia/Shanghai"]];
let properties = ["product_name": "商品名", "product_num": NSNumber.init(value: 1), "IsFirstBuy": true] as [String: Any]
instance.track("product_buy", properties:properties time: Date(), timeZone: NSTimeZone(name: "Asia/Shanghai")! as TimeZone)
注意:尽管事件可以设置触发时间,但是接收端会做如下的限制,只接收相对服务器时间在前 10 天至后 3 天的数据,超过时限的数据将会被视为异常数据,整条数据无法入库。
自 v2.3.1 版本开始,您可以通过设置 SDK 默认时区的方式,对齐多个时区下的事件时间,请参考设置默认时区小节。
自 v2.5.0 开始,您可以通过校准 SDK 时间接口来统一使用服务端时间完成数据采集。请参考校准时间小节。
b) 设置公共事件属性
对于一些重要的属性,譬如用户的会员等级、来源渠道等,这些属性需要设置在每个事件中,此时您可以将这些属性设置为公共事件属性。公共事件属性指的就是每个事件都会带有的属性,您可以调用 setSuperProperties:
来设置公共属性 ,我们推荐您在发送事件前,先设置公共事件属性。
公共事件属性的格式要求与事件属性一致。
[instance setSuperProperties:@{@"Channel": @"ABC", @"isTest": @YES}];
// 设置后上传数据:
[instance track:@"product_view"
properties:@{@"product_id": @"A1234"}];
// 相当于在事件中设置了属性:
NSDictionary *properties = @{
@"Channel": @"ABC",
@"isTest": @YES,
@"product_id": @"A1234"
};
[instance track:@"product_view"
properties:properties];
instance.setSuperProperties(["Channel" : "ABC", "isTest": true])
// 设置后上传数据:
instance.track("product_view", properties: ["product_id" : "A1234"])
// 相当于在事件中设置了属性:
let properties = ["Channel": "ABC", "isTest": true, "product_id": "A1234"] as [String: Any]
instance.track("product_view", properties: properties)
公共事件属性将会被保存到缓存中,无需每次启动App时调用。如果调用 setSuperProperties:
设置了先前已设置过的公共事件属性,则会覆盖之前的属性。如果公共事件属性和 track:properties:
上传的某个属性的Key重复,则该事件的属性会覆盖公共事件属性:
[instance setSuperProperties:@{@"Channel": @"ABC", @"isTest": @YES}];
// 覆盖"Channel",此时属性"Channel"的值为"XYZ"
[instance setSuperProperties:@{@"Channel": @"XYZ"}];
// 覆盖"isTest","isTest"的值为False
[instance track:@"product_view"
properties:@{@"isTest": @NO}];
instance.setSuperProperties(["Channel": "ABC", "isTest": true])
// 覆盖"Channel",此时属性"Channel"的值为"XYZ"
instance.setSuperProperties(["Channel": "XYZ"])
// 覆盖"isTest","isTest"的值为False
instance.track("product_view", properties: ["isTest": false])
如果您需要删除某个公共事件属性,您可以调用 unsetSuperProperty:
清除指定的公共事件属性;如果您想要清空所有公共事件属性,则可以调用 clearSuperProperties
:
// 清除一条公共事件属性,将之前设置"isTest"属性清除
[instance unsetSuperProperty:@"isTest"];
// 清除所有公共事件属性
[instance clearSuperProperties];
// 清除一条公共事件属性,将之前设置"isTest"属性清除
instance.unsetSuperProperty("isTest")
// 清除所有公共事件属性
instance.clearSuperProperties()
c) 设置动态公共属性
在 v1.2.0 版本中,新增了动态公共属性的特性,即公共属性可以上报时获取当时的值,使得诸如会员等级之类的可变公共属性可以被便捷地上报。通过 registerDynamicSuperProperties
设置动态公共属性类之后,SDK 将会在事件上报时自动执行并获取返回值中的属性,添加到触发的事件中。以下例子是每次上报时将获取当前时间并切换时区,当任意事件触发时,SDK会将返回的时间加入到该事件的属性中。
// 设置动态公共属性,在事件上报时动态获取事件发生时刻
[instance registerDynamicSuperProperties:^NSDictionary * _Nonnull{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSS"];
formatter.timeZone = [NSTimeZone timeZoneWithName:@"America/Chicago"];
NSDate *datenow = [NSDate date];
NSString *currentTimeString = [formatter stringFromDate:datenow];
return @{@"AmericaTime": currentTimeString};
}];
// 设置动态公共属性,在事件上报时动态获取事件发生时刻
instance.registerDynamicSuperProperties { () -> [String : Any] in
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
formatter.timeZone = TimeZone(abbreviation: "CDT")
let currentTimeString = formatter.string(from: Date())
return ["AmericaTime": currentTimeString]
}
d) 记录事件时长
如果您需要记录某个事件的持续时长,可以调用 timeEvent
来开始计时,配置您想要计时的事件名称,当您上传该事件时,将会自动在您的事件属性中加入 #duration
这一属性来表示记录的时长,单位为秒。
// 开始计时,记录的事件为 "product_view"
[instance timeEvent:@"product_view"];
//其他代码...
// 上传事件,计时结束,"product_view" 这一事件中将会带有表示事件时长的属性 "#duration"
[instance track:@"product_view"];
// 开始计时,记录的事件为 "product_view"
instance.timeEvent("product_view")
// 其他代码...
// 上传事件,计时结束,"product_view" 这一事件中将会带有表示事件时长的属性 "#duration"
instance.track("product_view")
4.用户属性
TA平台目前支持的用户属性设置接口为 user_set:
、user_setOnce:
、user_add:
、user_unset:
、user_delete
与user_append
a) user_set
对于一般的用户属性,您可以调用 user_set:
来进行设置,使用该接口上传的属性将会覆盖原有的属性值,如果之前不存在该用户属性,则会新建该用户属性,类型与传入属性的类型一致
// 设置用户属性
[instance user_set:@{@"UserName": @"TA", @"Age": @20}];
// 设置用户属性
instance.user_set(["UserName": "TA", "Age": 20])
user_set:
来设置的用户属性是一个NSDictionary
对象,其中每个元素代表一个属性。user_set
设置的用户属性格式要求与事件属性保持一致。
b) user_setOnce
如果您要上传的用户属性只要设置一次,则可以调用 user_setOnce:
来进行设置,当该属性之前已经有值的时候,将会忽略这条信息。
// 设置用户名
[instance user_setOnce:@{@"UserName": @"TA"}];
// 此时用户名为TA
[instance user_setOnce:@{@"UserName": @"ABC"}];
// 此时用户名仍为TA,此条数据被忽略
// 设置用户名
instance.user_setOnce(["UserName": "TA"])
// 此时用户名为TA
instance.user_setOnce(["UserName": "ABC"])
// 此时用户名仍为TA,此条数据被忽略
user_setOnce
设置的用户属性格式要求与事件属性保持一致。
c) user_add
当您要上传数值型的属性时,您可以调用 user_add:
来对该属性进行累加操作,如果该属性还未被设置,则会赋值 0 后再进行计算
// 设置累计付费金额
[instance user_add:@{@"TotalRevenue": @6}];
// 此时累计付费值为6
[instance user_add:@{@"TotalRevenue": @30}];
// 此时累计付费值为36
// 设置累计付费金额
instance.user_add(["TotalRevenue": 6])
// 此时累计付费值为6
instance.user_add(["TotalRevenue": 30])
// 此时累计付费值为36
user_add:
设置的属性类型以及 Key 值的限制与user_set:
一致,但 Value 只允许NSNumber
。
d) user_unset
当您要清空用户的某个用户属性值时,您可以调用 user_unset:
来对指定属性进行清空操作,如果该属性还未在集群中被创建,则 user_unset:
不会创建该属性
// 清空该用户的累计付费金额属性值
[instance user_unset:@"TotalRevenue"];
// 清空该用户的累计付费金额属性值
instance.user_unset("TotalRevenue")
user_unset:
的传入值为被清空属性的Key值。
e) user_delete
如果您要删除某个用户,可以调用 user_delete
将这名用户删除,您将无法再查询该名用户的用户属性,但该用户产生的事件仍然可以被查询到
[instance user_delete];
instance.user_delete()
f) user_append
从 v2.4.0 版本开始,您可以调用 user_append
对 NSArray 类型的用户属性进行追加操作。
// 调用 user_append 为用户属性 product_buy 追加元素。如果不存在,会新建该元素
[instance user_append:@{@"product_buy": @[@"product_name1", @"product_name2"]}];
instance.user_append(["product_buy": ["product_name1", "product_name2"]])
5. 自动采集事件
关于自动采集事件的具体使用方法,请参考 iOS SDK 自动采集指南一章。
6. SDK配置
a) 设置上传的网络条件
在默认情况下,SDK 将会网络条件为在 3G, 4G 及 Wifi 时上传数据,您可以通过下列方法修改允许上传的网络条件:
// 在 2G, 3G, 4G 及 Wifi 时上传数据
[instance setNetworkType:TDNetworkTypeALL];
// 只在 Wifi 环境下上报数据
[instance setNetworkType:TDNetworkTypeOnlyWIFI];
// 在 3G, 4G 及 Wifi 时上传数据, 默认设置
[instance setNetworkType:TDNetworkTypeDefault];
// 在 2G, 3G, 4G 及 Wifi 时上传数据
ThinkingAnalyticsSDK.sharedInstance()?.setNetworkType(ThinkingAnalyticsNetworkType.TDNetworkTypeALL)
// 只在 Wifi 环境下上报数据
ThinkingAnalyticsSDK.sharedInstance()?.setNetworkType(ThinkingAnalyticsNetworkType.TDNetworkTypeOnlyWIFI)
// 在 3G, 4G 及 Wifi 时上传数据, 默认设置
ThinkingAnalyticsSDK.sharedInstance()?.setNetworkType(ThinkingAnalyticsNetworkType.TDNetworkTypeDefault)
b) 暂停/停止数据上报
在 v2.1.0 版本中,新增了停止 SDK 上报数据的功能,一共有两类停止 SDK 上报的接口:
1. 暂停 SDK 上报(enableTracking)
您可能希望在一些场景下,暂时停止 SDK 的数据采集以及上报,比如用户处于测试环境中、或者用户登录了一个测试账号,此时您可以调用下列接口,暂时停止 SDK 的上报。
您可以通过某一实例(包括主要实例以及轻实例)调用 enableTracking:
,传入 false
来暂停 SDK 的上报,该实例已经设置的 #distinct_id
、#account_id
、公共属性等将保留;该实例已经采集但还未上报成功的数据将继续尝试上报;后续该实例不能采集以及上报任何新数据、不能设置访客 ID、账户ID以及公共属性等,但是可以读取该实例已经设置的公共属性和设备 ID、访客 ID、账号 ID 等信息。
实例的停止状态将会被保存在本地缓存,直到调用 enableTracking:
、传入 true
,SDK 实例将会重新恢复数据采集以及上报,需要注意轻实例因为不进行缓存,因此每次打开 APP 后,轻实例的暂停状态不会被保留,将重新开启上报。
// 暂停上报
[instance enableTracking:NO];
// 恢复上报
[instance enableTracking:YES];
// 暂停上报
instance.enableTracking(false)
// 恢复上报
instance.enableTracking(true)
2. 停止 SDK 上报(optOutTracking)
在一些特殊场景下,您可能需要完全停止 SDK 的功能,比如在适用 GDPR 的地区,用户选择不提供数据采集权限,则您可以调用如下接口完全关闭 SDK 的功能。
optOutTracking
只能通过主要实例调用,与 enableTracking
的最大区别在于,其将会清空该实例的本地缓存,包括本实例的访客 ID,账号 ID,公共属性,以及未上报的数据队列。之后再关闭该实例的采集和上报功能。
// 停止上报,并重置本地缓存
[instance optOutTracking];
// 停止上报,并重置本地缓存
instance.optOutTracking()
如果您希望关闭 SDK 功能的同时,删除该用户在 TA 集群中的用户数据,可以调用 optOutTrackingAndDeleteUser
,这将会在停止 SDK 实例的功能前,上报一条 user_del
数据,以删除该用户的用户数据。
// 停止上报,并发送删除用户请求
[instance optOutTrackingAndDeleteUser];
// 停止上报,并发送删除用户请求
instance.optOutTrackingAndDeleteUser()
实例的停止状态也将保存在本地缓存,直到调用 optInTracking
,后续可以继续上报,但此时相当于一个全新的实例
// 重新开启上报
[instance optInTracking];
// 重新开启上报
instance.optInTracking()
c) 打印数据Log
可以调用setLogLevel
来开启(默认是关闭的):
[ThinkingAnalyticsSDK setLogLevel:TDLoggingLevelDebug];
// TDLoggingLevelError :Error Log
// TDLoggingLevelInfo :Info Log
// TDLoggingLevelDebug :Debug Log
ThinkingAnalyticsSDK.setLogLevel(TDLoggingLevel.debug)
// TDLoggingLevel.error :Error Log
// TDLoggingLevel.info :Info Log
// TDLoggingLevel.debug :Debug Log
d) 获取设备 ID
在 v2.0.0 版本,加入了获取设备 ID(也就是预置属性#device_id
)的接口,您可以通过调用 getDeviceId
来获取设备ID:
[instance getDeviceId];
// 如果需要将设备ID设置成访客ID可以如下调用
// [instance identify:[instance getDeviceId]];
e) 配置 HTTPS 校验方法:
从 v2.3.0 版本开始,SDK 可以配置HTTPS校验方法,需要在初始化的时候首先获取 TDConfig 实例,然后用 TDConfig 完成初始化。
TDConfig *config = [[TDConfig alloc] init];
TDSecurityPolicy *securityPolicy = [TDSecurityPolicy policyWithPinningMode:TDSSLPinningModeNone];
// TDSSLPinningModeNone:默认认证方式,只会在系统的信任的证书列表中对服务端返回的证书进行验证
// TDSSLPinningModePublicKey:校验证书的公钥
// TDSSLPinningModeCertificate:校验证书的所有内容
securityPolicy.allowInvalidCertificates = YES; // 是否允许自建证书或者过期SSL证书,默认NO
securityPolicy.validatesDomainName = NO; // 是否验证证书域名,默认YES
config.securityPolicy = securityPolicy;
[ThinkingAnalyticsSDK startWithAppId:@"YOUR_APPID" withUrl:@"YOUR_SERVER_URL" withConfig:config];
let tdconfig = TDConfig();
let tdSecurityPolicy = TDSecurityPolicy(pinningMode: TDSSLPinningMode.publicKey);
// TDSSLPinningMode [] 默认认证方式,只会在系统的信任的证书列表中对服务端返回的证书进行验证
// TDSSLPinningMode.publicKey 校验证书的公钥
// TDSSLPinningMode.certificate 校验证书的所有内容
tdSecurityPolicy.allowInvalidCertificates = true // 是否允许自建证书或者过期SSL证书,默认NO
tdSecurityPolicy.validatesDomainName = false // 是否验证证书域名,默认YES
tdconfig.securityPolicy = tdSecurityPolicy;
ThinkingAnalyticsSDK.start(withAppId: "YOUR_APPID", withUrl: "YOUR_SERVER_URL", with: tdconfig);
f) 设置默认时区
默认情况下,如果用户不指定事件发生时间,SDK 默认会使用接口调用时的本机时间作为事件发生时间上报。自 v2.3.1 版本开始,您也可以通过设置默认时区接口,指定默认的时区,这样所有的事件(包括自动采集事件)都将按照您设置的时区来对齐事件时间:
// 获取 TDConfig 实例
TDConfig *config = [[TDConfig alloc] init];
// 设置默认时区为 UTC
config.defaultTimeZone = [NSTimeZone timeZoneWithName:@"UTC"];
// 初始化 SDK
ThinkingAnalyticsSDK *instance = [ThinkingAnalyticsSDK startWithAppId:@"YOUR_APPID" withUrl:@"YOUR_SERVER_URL" withConfig:config];
注意:用指定时区对齐事件时间,会丢掉设备本机时区信息。如果需要保留设备本机时区信息,目前需要您自己为事件添加相关属性。
g) 开启 Debug 模式
从 v2.4.0 版本开始,客户端 SDK 支持 Debug 模式,需要配合 TA 平台 2.5 之后的版本使用。
Debug 模式可能会影响数据采集质量和 App 的稳定性,只用于集成阶段数据验证,不要在线上环境使用。当前 SDK 实例支持三种运行模式,在 TDConfig
中定义:
/**
Debug模式
- ThinkingAnalyticsDebugOff : 默认 不开启Debug模式
*/
typedef NS_OPTIONS(NSInteger, ThinkingAnalyticsDebugMode) {
/**
默认 不开启Debug模式
*/
ThinkingAnalyticsDebugOff = 0,
/**
开启Debug_only模式,只对数据做校验,不会入库
*/
ThinkingAnalyticsDebugOnly = 1 << 0,
/**
Debug 模式,数据逐条上报。当出现问题时会以日志和异常的方式提示用户
*/
ThinkingAnalyticsDebug = 1 << 1
};
为了设置 SDK 实例运行模式,请使用 TDConfig
来完成 SDK 初始化:
// 获取 TDConfig 实例
TDConfig *config = [[TDConfig alloc] init];
// 设置运行模式为 Debug 模式
config.debugMode = ThinkingAnalyticsDebug;
// 初始化 SDK
ThinkingAnalyticsSDK *instance = [ThinkingAnalyticsSDK startWithAppId:@"YOUR_APPID" withUrl:@"YOUR_SERVER_URL" withConfig:config];
为了避免 Debug 模式在生产环境上线,规定只有指定的设备才能开启 Debug 模式。只有在客户端开启了 Debug 模式,并且设备 ID 在 TA 后台的"埋点管理"页的"Debug数据"板块中配置了的设备才能开启 Debug 模式。
设备 ID 可以通过以下三种方式获取:
- TA 平台中事件数据中的 #device_id 属性
- 客户端日志:SDK 初始化完成后会打印设备 DeviceId
- 通过实例接口调用:获取设备 ID
h) 校准时间
SDK 默认会使用本机时间作为事件发生时间上报,如果用户手动修改设备时间会影响到您的业务分析,自 v2.5.0 版本开始,您可以使用从服务端获取的当前时间戳对 SDK 的时间进行校准。此后,所有为指定时间的调用,包括事件数据和用户属性设置操作,都会使用校准后的时间作为发生时间。
// 1585633785954 为当前 unix 时间戳,单位为毫秒,对应北京时间 2020-03-31 13:49:45
[ThinkingAnalyticsSDK calibrateTime:1585633785954];
// 1585633785954 为当前 unix 时间戳,单位为毫秒,对应北京时间 2020-03-31 13:49:45
ThinkingAnalyticsSDK.calibrateTime(1585633785954)
我们也提供了从 NTP 获取时间对 SDK 校准的功能。您需要传入您的用户可以访问的 NTP 服务器地址。之后 SDK 会尝试从传入的 NTP 服务地址中获取当前时间,并对 SDK 时间进行校准。如果在默认的超时时间(3 秒)之内,未获取正确的返回结果,后续将使用本地时间上报数据。
// 使用苹果公司 NTP 服务对时间进行校准
[ThinkingAnalyticsSDK calibrateTimeWithNtp:@"time.apple.com"];
ThinkingAnalyticsSDK.calibrateTime(withNtp: "time.apple.com")
注意:
- 您需要谨慎地选择您的 NTP 服务器地址,以保证网络状况良好的情况下,用户设备可以很快的获取到服务器时间。
- 使用 NTP 服务进行时间校准存在一定的不确定性,建议您优先考虑用时间戳校准的方式。
除了以上校准时间接口外,在 v2.5.0 提供了所有用户属性接口的时间函数重载,您可以在调用用户属性相关接口时,传入 Date 对象,则系统会使用传入的 Date 对象来设定数据的 #time
字段。
7. 相关预置属性
7.1 所有事件带有的预置属性
以下预置属性,是 iOS SDK 中所有事件(包括自动采集事件)都会带有的预置属性
属性名 | 中文名 | 说明 |
---|---|---|
#ip | IP地址 | 用户的IP地址,TA将以此获取用户的地理位置信息 |
#country | 国家 | 用户所在国家,根据IP地址生成 |
#country_code | 国家代码 | 用户所在国家的国家代码(ISO 3166-1 alpha-2,即两位大写英文字母),根据IP地址生成 |
#province | 省份 | 用户所在省份,根据IP地址生成 |
#city | 城市 | 用户所在城市,根据IP地址生成 |
#os_version | 操作系统版本 | iOS 11.2.2、Android 8.0.0等 |
#manufacturer | 设备制造商 | 用户设备的制造商,如Apple,vivo等 |
#os | 操作系统 | 如Android、iOS等 |
#device_id | 设备ID | 用户的设备ID,iOS取用户的IDFV或UUID,Android取androidID |
#screen_height | 屏幕高度 | 用户设备的屏幕高度,如1920等 |
#screen_width | 屏幕宽度 | 用户设备的屏幕高度,如1080等 |
#device_model | 设备型号 | 用户设备的型号,如iPhone 8等 |
#app_version | APP版本 | 您的APP的版本 |
#lib | SDK类型 | 您接入SDK的类型,如Android,iOS等 |
#lib_version | SDK版本 | 您接入SDK的版本 |
#network_type | 网络状态 | 上传事件时的网络状态,如WIFI、3G、4G等 |
#carrier | 网络运营商 | 用户设备的网络运营商,如中国移动,中国电信等 |
#zone_offset | 时区偏移 | 数据时间相对UTC时间的偏移小时数 |
7.2 自动采集事件的预置属性
以下预置属性,是各个自动采集事件中所特有的预置属性
- APP启动事件(ta_app_start)的预置属性
属性名 | 中文名 | 说明 |
---|---|---|
#resume_from_background | 是否从后台唤醒 | 表示APP是被开启还是从后台唤醒,取值为true表示从后台唤醒,false为直接开启 |
- APP关闭事件(ta_app_end)的预置属性
属性名 | 中文名 | 说明 |
---|---|---|
#duration | 事件时长 | 表示该次APP访问(自启动至结束)的时长,单位是秒 |
- APP浏览页面事件(ta_app_view)的预置属性
属性名 | 中文名 | 说明 |
---|---|---|
#title | 页面标题 | 为View Controller的标题,取值为controller.navigationItem.title 属性的值 |
#screen_name | 页面名称 | 为View Controller的类名 |
#url | 页面地址 | 当前页面的地址,需要调用getScreenUrl 进行url的设置 |
#referrer | 前向地址 | 跳转前页面的地址,跳转前页面需要调用getScreenUrl 进行url的设置 |
- APP控件点击事件(ta_app_click)的预置属性
属性名 | 中文名 | 说明 |
---|---|---|
#title | 页面标题 | 为View Controller的标题,取值为controller.navigationItem.title 属性的值 |
#screen_name | 页面名称 | 为View Controller的类名 |
#element_id | 元素ID | 控件的ID,需要thinkingAnalyticsViewID 进行设置 |
#element_type | 元素类型 | 控件的类型 |
#element_selector | 元素选择器 | 为控件的viewPath 的拼接 |
#element_position | 元素位置 | 控件的位置信息,只有当控件类型为UITableView 或UICollectionView 才会存在,表示控件被点击的位置,取值为组号(Section):行号(Row) |
#element_content | 元素内容 | 控件上的内容 |
- APP崩溃事件(ta_app_crash)的预置属性
属性名 | 中文名 | 说明 |
---|---|---|
#app_crashed_reason | 异常信息 | 字符型,记录崩溃时的堆栈轨迹 |
7.3 其他预置属性
除了上述提到预置属性,还有部分预置属性需要调用对应接口才会被记录:
属性名 | 中文名 | 说明 |
---|---|---|
#duration | 事件时长 | 需要调用计时功能接口timeEvent: ,记录事件发生时长,单位是秒 |
8. 进阶功能
从 v2.6.0 开始,SDK 支持上报三种特殊类型事件: 首次事件、可更新事件、可重写事件。这三种事件需要配合 TA 系统 2.8 及之后的版本使用。由于特殊事件只在某些特定场景下适用,所以请在数数科技的客户成功和分析师的帮助下使用特殊事件上报数据。
8.1 首次事件
首次事件是指针对某个设备或者其他维度的 ID,只会记录一次的事件。例如在一些场景下,您可能希望记录在某个设备上第一次发生的事件,则可以用首次事件来上报数据。
// 示例:上报设备首次事件, 假设事件名为 DEVICE_FIRST
TDFirstEventModel *firstModel = [[TDFirstEventModel alloc] initWithEventName:@"DEVICE_FIRST"];
// 可选参数
firstModel.properties = @{};
[firstModel configTime:<# __kindof NSDate * #> timeZone:<# __kindof NSTimeZone *_Nullable #>];
// 上报事件API
[[ThinkingAnalyticsSDK sharedInstance] trackWithEventModel:firstModel];
// 示例:上报设备首次事件, 假设事件名为 DEVICE_FIRST
let firstModel = TDFirstEventModel(eventName:"DEVICE_FIRST")
// 可选参数
firstModel.properties = ["KEY": "VALUE"]
firstModel.configTime(<#T##time: Date##Date#>, timeZone: <#T##TimeZone?#>)
ThinkingAnalyticsSDK.sharedInstance()?.track(with: firstModel)
如果您希望以设备以外的其他维度来判断是否首次,则可以为首次事件设置 FIRST_CHECK_ID. 例如您需要记录某个账号的首次事件,可以将账号 ID 设置为首次事件的 FIRST_CHECK_ID:
// 自定义#first_check_id的构造方法
TDFirstEventModel *firstModel = [[TDFirstEventModel alloc] initWithEventName:@"DEVICE_FIRST" firstCheckID:@"YOUR_ACCOUNT_ID"];
// 可选参数
firstModel.properties = @{};
[firstModel configTime:<# __kindof NSDate * #> timeZone:<# __kindof NSTimeZone *_Nullable #>];
// 上报事件API
[[ThinkingAnalyticsSDK sharedInstance] trackWithEventModel:firstModel];
// 示例:上报设备首次事件, 假设事件名为 DEVICE_FIRST
let firstModel = TDFirstEventModel(eventName:"DEVICE_FIRST", firstCheckID:"YOUR_ACCOUNT_ID")
// 可选参数
firstModel.properties = ["KEY": "VALUE"]
firstModel.configTime(<#T##time: Date##Date#>, timeZone: <#T##TimeZone?#>)
ThinkingAnalyticsSDK.sharedInstance()?.track(with: firstModel)
注意:由于在服务端完成对是否首次的校验,首次事件会延时 1 小时入库。
8.2 可更新事件
您可以通过可更新事件实现特定场景下需要修改事件数据的需求。可更新事件需要指定标识该事件的 ID,并在创建可更新事件对象时传入。TA 后台将根据事件名和事件 ID 来确定需要更新的数据。
// 示例: 上报可被更新的事件,假设事件名为 UPDATABLE_EVENT
TDUpdateEventModel *updateModel = [[TDUpdateEventModel alloc] initWithEventName:@"UPDATABLE_EVENT" eventID:@"test_event_id"];
updateModel.properties = @{@"status": @3, @"price": @100};
// 上报后事件属性 status 为 3, price 为 100
[[ThinkingAnalyticsSDK sharedInstance] trackWithEventModel:updateModel];
TDUpdateEventModel *updateModel_new = [[TDUpdateEventModel alloc] initWithEventName:@"UPDATABLE_EVENT" eventID:@"test_event_id"];
updateModel_new.properties = @{@"status": @5};
// 上报后事件属性 status 被更新为 5, price 不变
[[ThinkingAnalyticsSDK sharedInstance] trackWithEventModel:updateModel_new];
// 示例: 上报可被更新的事件,假设事件名为 UPDATABLE_EVENT
let updateModel = TDUpdateEventModel(eventName: "UPDATABLE_EVENT", eventID: "test_event_id")
updateModel.properties = ["status": 3, "price": 100]
// 可选参数
updateModel.configTime(<#T##time: Date##Date#>, timeZone: <#T##TimeZone?#>)
// 上报后事件属性 status 为 3, price 为 100
ThinkingAnalyticsSDK.sharedInstance()?.track(with: updateModel)
let updateModel_new =TDUpdateEventModel(eventName: "UPDATABLE_EVENT", eventID: "test_event_id")
updateModel_new.properties = ["status": 5]
// 上报后事件属性 status 为 5, price 不变
ThinkingAnalyticsSDK.sharedInstance()?.track(with: updateModel_new)
8.3 可重写事件
可重写事件与可更新事件类似,区别在于可重写事件会用最新的数据完全覆盖历史数据,从效果上看相当于删除前一条数据,并入库最新的数据。TA 后台将根据事件名和事件 ID 来确定需要更新的数据。
// 示例: 上报可被重写的事件,假设事件名为 OVERWRITE_EVENT
TDOverwriteEventModel *overwriteModel = [[TDOverwriteEventModel alloc] initWithEventName:@"OVERWRITE_EVENT" eventID:@"test_event_id"];
overwriteModel.properties = @{@"status": @3, @"price": @100};
// 上报后事件属性 status 为 3, price 为 100
[[ThinkingAnalyticsSDK sharedInstance] trackWithEventModel:overwriteModel];
TDOverwriteEventModel *overwriteModel_new = [[TDOverwriteEventModel alloc] initWithEventName:@"OVERWRITE_EVENT" eventID:@"test_event_id"];
overwriteModel_new.properties = @{@"status": @5};
// 上报后事件属性 status 为 5, price属性被删除
[[ThinkingAnalyticsSDK sharedInstance] trackWithEventModel:overwriteModel_new];
// 示例: 上报可被重写的事件,假设事件名为 OVERWRITE_EVENT
let overwriteModel = TDOverwriteEventModel(eventName: "OVERWRITE_EVENT", eventID: "test_event_id")
overwriteModel.properties = ["status": 3, "price": 100]
// 可选参数
overwriteModel.configTime(<#T##time: Date##Date#>, timeZone: <#T##TimeZone?#>)
// 上报后事件属性 status 为 3, price 为 100
ThinkingAnalyticsSDK.sharedInstance()?.track(with: overwriteModel)
let overwriteModel_new = TDOverwriteEventModel(eventName: "UPDATABLE_EVENT", eventID: "test_event_id")
overwriteModel_new.properties = ["status": 5]
// 上报后事件属性 status 为 5, price 被删除
ThinkingAnalyticsSDK.sharedInstance()?.track(with: overwriteModel_new)
ChangeLog
v2.6.1 2020/08/25
- 修复特殊事件设置timeZone的逻辑, 现在不设置timeZone上报数据不会再带有#zone_offset=0了.
v2.6.0 2020/08/24
- 支持首次事件, 允许传入自定义的 ID 校验是否首次上报
- 支持可更新、可重写的事件
v2.5.6 2020/08/11
- 优化时间校准API, 现在多次调用会多次生效.
v2.5.5 2020/06/23
- 修复部分机型 #system_language 异常
v2.5.4 2020/06/22
- 修复 v2.5.3 undeclared selector 'applicationWillTerminateNotification:' [-Wundeclared-selector]
v2.5.3 2020/06/22
- 新增预置属性 #system_language
- 固定预置属性 #os 为 "iOS"
- 优化代码
v2.5.2 2020/05/15
- 修复 v2.5.1 中 Debug 模式会因数据格式错误降级的问题
v2.5.1 2020/05/14
- 适配TA 后台 2.7 版本屏蔽事件配置接口
- 调整 DEBUG 模式,去除客户端抛异常逻辑
v2.5.0 2020/04/03
- 支持客户端 SDK 的时间校准功能
- 新增指定时间的用户属性设置接口
- 代码优化
v2.4.3 2020/03/11
- 去除 UIWebView 相关代码
v2.4.2 2020/03/09
- 延迟初始化时正常按间隔上报数据
- 代码优化
v2.4.1 2020/02/21
- 修复 v2.3.0、v2.3.1、v2.4.0 引入的 bug
v2.4.0 2020/02/10
- 支持 NSArray 类型
- 新增 user_append 接口
- 去除客户端的属性格式检查
v2.3.1 2020/01/07
- 支持配置默认时区
v2.3.0 2019/12/31
- 支持 Debug 模式: 需配合后台 Debug 设备白名单一起开启
- H5 与原生 SDK 打通支持多实例
- 优化 SDK 配置: 增加全局设置;上报策略允许针对不同项目配置
- 支持配置HTTPS证书校验
v2.2.2 2019/12/01
- 修复使用
EnableSceneSupport
时,APP启动事件(ta_app_install
)中的属性#resume_from_background
取值`异常的问题
v2.2.1 2019/11/22
- 依据Appstore ITMS-90809 默认去除 UIWebView 相关内容
v2.2.0 2019/10/21
- 新增
user_unset
接口,可用于清空一个用户属性 - 新增预制属性
#zone_offset
,单位为小时。 默认情况下会将本地时区的偏移上报到服务端,该时间偏移会受夏令时影响。满足如下公式:utc_time + #zone_offset = #event_time
v2.1.1 2019/10/11
- 优化上报逻辑,解决极端情况下数据异常上报的问题
v2.1.0 2019/09/16
- 支持轻量级实例, 便于上报被动事件等需求
- 新增 enableTracking 接口, 可以打开或关闭实例上报功能
- 新增 optOutTracking/optInTracking 接口
- 其他代码优化
v2.0.1 2019/07/15
- 调整了自动采集事件中ta_app_install(APP安装事件)的触发顺序,现在将在ta_app_start(APP启动事件)前触发
v2.0.0 2019/07/12
- 自动采集事件新增APP安装事件
- 默认不采集后台自启时产生的数据,后续会添加后台自启接口,可控制是否采集后台自启时产生的数据
v1.2.0 2019/06/20
- 新增多APPID实例功能
- 新增动态公共属性特性
- 自动采集事件新增APP崩溃事件