神策分析支持多种不同语言的 SDK,这些 SDK 虽然在外部提供的接口上有所不同,但是在内部实现上都使用统一的数据格式,并且 数据导入 都支持直接导入以文件形式存储的符合要求格式的数据,在这里,我们对数据格式进行一个更加细致的描述。

  • 注意:这里描述的是底层数据传输格式的定义,和具体 SDK 的调用接口无关
  • 注意:$is_login_id 参数说明

数据整体格式

日志文件是一行一个 JSON,物理上对应一条数据,逻辑上对应一个描述了用户行为的事件,或是描述一个或多个用户属性的 Profile 操作。

track:

记录一个 Event 及关联的 Properties。

数据样例:

{
	"distinct_id": "123456",
	"time": 1434556935000,
	"type": "track",
	"event": "ViewProduct",
	"project": "ebiz_test",
	"time_free": true, //建议在导入历史数据时使用,SDK 采集的实时数据不建议使用
	"properties": {
		"$is_login_id":true, //此参数请慎重使用,详细介绍请参考文档底部 8.1 $is_login_id 参数说明
		"$app_version":"1.3",
		"$wifi":true,
		"$ip":"180.79.35.65",
		"$province":"湖南",
		"$city":"长沙",
		"$user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/58.0.3029.113 Mobile/14F89 Safari/602.1",
		"$screen_width":320,
		"$screen_height":568,
		"product_id":12345,
		"product_name":"苹果",
		"product_classify":"水果",
		"product_price":14.0
	}
}
CODE


对于上述字段的说明如下:

  • distinct_id:类型是字符串,对用户的标识,对未登录用户,可以填充设备标识、CookieID 等,对于登录用户,则应该填充注册账号;这里的例子,我们假设是一个未注册用户,所以填充的是一个设备编号;
  • time:类型是数值,事件发生的实际时间戳,精确到毫秒;
  •  type:track 表明是记录一个 Event ,这里我们假设是一个商品浏览行为;
  • event:事件名,需是合法的变量名,即不能以数字开头,且只包含:大小写字母、数字、下划线和 $,其中以 $ 开头的表明是系统的预置事件,自定义事件名请不要以 $ 开头,且 event 字段长度最大为 100;
  •  project:这条数据所属项目名,若不指定该参数,则需要使用该字段时取值 default,即默认项目。指定的项目必须是系统中已经存在的项目,否则这条数据将无效,更多项目相关请参见多项目
  •  time_free:可选字段,表示不根据事件发生时间过滤该事件。只要出现 time_free 这个 key 且 value 不为 null,将不再校验 time 是否在允许导入的时间范围内。导入历史数据时可能会用到该字段;
  • properties:这个 Event 的具体属性,以 dict 的形式存在。其中以 $ 开头的表明是系统的预置属性,它的类型和中文名已经预先定义好了。自定义属性名需要是合法的变量名,不能以数字开头,且只包含:大小写字母、数字、下划线,自定义属性不能以 $ 开头;同一个名称的 property,在不同 event 中,必须保持一致的定义和类型;同一个名称的 property 大小写不可以相同,如果已经存在小写属性就不可再导入对应大写属性(比如元数据中有 abc 属性名,不能再传 ABC,Abc 等属性名),否则数据会校验失败不入库。

    • $is_login_id:distinct_id 对应的是否是一个注册 ID;
    • $app_version:用户所使用的 App 的版本;
    • $wifi:这条事件发生时,用户是否在使用 wifi;
    • $ip:用户使用设备的 IP。若数据中出现 $ip,且数据中没有 $province 或 $city 字段,将使用该 IP 解析出省市信息填入缺失字段;
    • $province、$city:省、市,在没有填充这两个字段的时候,会根据 IP 进行解析;
    • $user_agent:可选参数。如果传入该参数,则解析 User-Agent,解析结果包括:设备制造商、设备型号、操作系统、操作系统版本、浏览器、浏览器版本、爬虫名称(如果是爬虫);目前是神策是通过 UA 判断并有一个默认的属性 $bot_name (爬虫名称),但是有两种情况无法判断,第一种:如果 UA 里没有标明、且会触发 JS 脚本的非法爬虫。第二种:如果爬虫没有触发 JS 脚本,那么也不会触发我们的 SDK ,所以本身就不会被统计到。对于爬虫种类,不能提前把所有的种类都加进去,主流的神策都加了,其它的属于不太常见的,量较少。
    • $screen_width、$screen_height:屏幕的宽和高;
    • product_id、product_name、product_classify、product_price:跟商品相关的一些具体属性。

track_signup:

这个接口是一个较为复杂的功能,请在使用前先阅读 标识用户,并在必要时联系我们的技术支持人员。

数据样例:

{
	"distinct_id":"12345",
	"original_id":"2b0a6f51a3cd6775",
	"time": 1434557935000,
	"type": "track_signup",
	"event": "$SignUp",
	"project": "ebiz_test",
	"properties": {
		"$manufacturer":"Apple",
		"$model": "iPhone5,2",
		"$os":"iOS",
		"$os_version":"7.0",
		"$app_version":"1.3",
		"$wifi":true,
		"$ip":"180.79.35.65",
		"$province":"湖南",
		"$city":"长沙",
		"$screen_width":320,
		"$screen_height":568
	}
}
CODE


这条数据表示,一个匿名 ID 为 2b0a6f51a3cd6775 的用户,成功完成了注册,注册后的注册 ID 是 12345。并且系统后台,会将 original_id 为 2b0a6f51a3cd6775 的用户和 distinct_id 为 12345 的用户,当做同一个用户对待。需要注意的是,此接口中的 original_id 为必须字段,表示与注册 ID 进行关联的匿名 ID。

Profile 相关操作

Profile 相关操作,主要是用来设置用户的 Profile 的,提供了如下一系列接口:

profile_set:

直接设置一个用户的 Profile,如果用户或者 Profile 的字段已存在,则覆盖,不存在则自动创建。

数据样例:

{
	"distinct_id": "12345",
	"type": "profile_set",
	"time": 1435290195610,
	"project": "ebiz_test",
	"properties": {
		"$province":"湖南",
		"FavoriteFruits": ["苹果","香蕉","芒果"],
		"Age":33,
		"$city":"长沙",
		"IncomeLevel": "3000~5000",
		"$name": "小明",
		"Gender":"男",
		"$signup_time": "2015-06-26 11:43:15.610"
	}
}
CODE

profile_set_once

直接设置一个用户的 Profile。与 profile_set 接口不同的是,如果用户或者 Profile 的字段已存在,则这条记录会被忽略而不会覆盖已有数据,如果 Profile 不存在则会自动创建。因此,profile_set_once 比较适用于为用户设置首次激活时间、首次注册时间等只在首次设置时有效的属性。

数据样例:

{
	"distinct_id": "12345",
	"type": "profile_set_once",
	"time": 1435290195610,
	"project": "ebiz_test",
	"properties": {
		"$province":"湖南",
		"FavoriteFruits": ["苹果","香蕉","芒果"],
		"Age":33,
		"$city":"长沙",
		"IncomeLevel": "3000~5000",
		"$name": "小明",
		"Gender":"男",
		"$signup_time": "2015-06-26 11:43:15.610"
	}
}
CODE

profile_increment:

增加或减少一个用户的某个 NUMBER 类型的 Profile 值,比如给用户属性 Age 的值加 1 或者减 1 。如果用户表( users 表)中不存在这个用户,则会在用户表中自动创建该用户的 id 记录,并给该用户设置相应的 Profile 属性值,会在默认值 0 的基础上增加上传的 Profile 值。

数据样例:

{
	"distinct_id": "12345",
	"type": "profile_increment",
	"time": 1435290200354,
	"project": "ebiz_test",
	"properties": {
		"Age": 1
	}
}
CODE

profile_delete:

删除一个用户的整个 Profile。

数据样例:

{
	"distinct_id": "12345",
	"type": "profile_delete",
	"time": 1437290200354,
	"project": "ebiz_test",
	"properties":{
	}
}
CODE

profile_append:

向某个用户的某个数组类型的 Profile 添加一个或者多个值。如果本次上传的值,与系统中已存在的值有重复,默认是不会去重的。如果本次上传的值,有重复项,也不会去重的。

数据样例:

{
	"distinct_id": "12345",
	"type": "profile_append",
	"time": 1437280200354,
	"project": "ebiz_test",
	"properties": {
		"FavoriteFruits": ["橘子","西瓜"]
	}
}
CODE

 profile_unset:

将某个用户的某些属性值设置为空。另外,为了与其它接口保持一致,在提交的数据上,属性的值请设置为非 null 的任何值,例如 true。

数据样例:

{
	"distinct_id":"12345",
	"type":"profile_unset",
	"time":1437280200354,
	"project": "ebiz_test",
	"properties":{
		"Age":true,
		"FavoriteFruits":true
	}
}
CODE

Item 相关操作

Item 相关操作,主要是用来设置 Item 的具体内容,提供了如下一系列接口:

item_set:

直接设置一个 Item,如果 Item 的字段已存在,则覆盖,不存在则自动创建。

数据样例:

{
	"type":"item_set",
	"item_id":"12",
	"item_type":"dub",
	"project": "ebiz_test",
	"properties":{
		"title":"because of u",
		"sub_title":"st",
		"xxx":"xxx"
	}
}
CODE

对上述字段的解释如下:

  • type:item_set 表明是设置一个 item;
  • item_id:表示 item 的 id
  •  item_type:item 表的类型,区分不同的 item 表。需是合法的变量名,即不能以数字开头,且只包含:大小写字母、数字、下划线和 $,且 item_type 字段长度最大为 100;
  •  project:这条数据所属项目名,若不指定该参数,则需要使用该字段时取值 default,即默认项目。指定的项目必须是系统中已经存在的项目,否则这条数据将无效,更多项目相关请参见 多项目
  •  properties:这个 item 的具体属性,以 dict 的形式存在。属性名需要是合法的变量名,不能以数字开头,且只包含:大小写字母、数字、下划线;

item_delete:

删除整个 Item 内容。

数据样例:

{
  "type":"item_delete",
  "item_id":"16",
  "item_type":"dub",
  "project": "ebiz_test"
}
CODE

属性数据类型

注意问题

发送端使用 JSON 作为数据传输格式,本系统以 JSON 数据类型为基础再加以额外限制,定义了若干种数据类型,但 不与 JSON 类型完全等价,详见后文属性类型说明。
(table_name, property_name) 二元组唯一确定一个属性,table_name 为数据表的表名,如 users、events,可在自定义 SQL 查询中看到。这意味着同表同名属性类型必须相同,而不同表的同名属性类型可以不同。消息类型与所写入的数据表的关系如下表:

消息类型目标数据表
trackevents
profile_*users
track_signup事件信息被写入 events 表,users 表中会记录 first_id 和 second_id

一个属性的类型由首次导入时的类型决定,元数据-事件属性/用户属性页面展示的属性类型即为首次导入时的类型,后续导入数据时若类型和元数据中展示的类型不符,则尝试对数据进行类型转换,若无法转换或转换失败则 输入数据会被整条拒绝 。尝试进行的类型转换如下(空格不进行转换):

目标类型\原始类型数值型布尔值字符串字符串集合日期时间
数值型
true -> 1; false -> 0空字符串 "" 抛弃该属性; 其他按数值解析

布尔值0 -> false; 非 0 值 -> true
字符串"true"、"false"转换为布尔类型

字符串原值作为字符串原值作为字符串
原值作为字符串原值作为字符串
字符串集合




日期时间在一定区间内的按 UNIX 时间戳的秒或毫秒转换
多种日期时间格式模式串解析

  • 上述表格左侧的列对应目标类型,上方的行对应原始类型。目标类型对应元数据中的数据类型,原始类型是数据上传时的属性值类型
  • 什么时候该使用数值类型的属性:
    • 需要进行聚合运算(例如求和、均值)或者按区间分组的值,典型的比如价格、时长、年龄等。
    • 除非有特殊需求,否则各类 ID(例如订单 ID)不建议作为数值类型存储。

神策分析属性数据类型定义

神策分析数据类型中文名基础 JSON 类型额外限制示例说明
NUMBER数值型number-9E15 到 9E15 小数点后最多保留3位12 或 12.0
BOOL布尔值booltrue 或 false
STRING字符串string使用 UTF-8 编码后最大长度 1024 字节,如需调整最大长度可以联系我们"SensorsData"
LIST字符串数组list1.12 版本之后默认是字符串元素的数组(传入的字符串不会去重),最大元素个数为 500,其中每个元素使用 UTF-8 编码后最大长度 255 字节;注意:1.12 之前的版本,List 是集合,即在入库时会进行重排序和去重。如果需要调整 List 具体是数组还是集合,请联系神策技术支持。若 append 导致超过最大元素个数时,新入库的元素会淘汰最早入库的元素。["橘子","西瓜"]
DATETIME日期时间stringyyyy-MM-dd HH:mm:ss.SSS 或
yyyy-MM-dd HH:mm:ss 或
yyyy-mm-dd (时分秒按00:00:00处理), 建议使用第一种,其中 SSS 为毫秒;年取值范围是 [1900, 2099]
"2015-06-19 17:51:21.234"
"2015-06-19 17:51:21"
"2015-06-19"
有些语言的时间格式化库不直接提供毫秒格式化,如 Python 提供 us 而不提供 ms,如需自行编写程序生成数据请注意这点。
DATE (仅 <= 1.10 版本)日期string格式为 yyyy-mm-dd,年取值范围是 [1900, 2099]"2015-06-19"自 1.11 版本起,DATE 类型将作为 DATETIME 的一种格式存在(既时分秒为 00:00:00 的 DATETIME,且时分秒可省略),不再单设类型。

预置属性

为了帮助使用者更方便地使用我们的产品,我们目前分别为 Event 和 Profile 提供了一些预置字段。

注意:JavaScript SDK 预置属性较多,这里没有全部列出,详细说明请参考相关文档 .Web 预置属性 v1.13

Event 的预置字段有:

字段名称类型说明JS SDK 自动采集iOS SDK 自动采集Android SDK 自动采集小程序 SDK 自动采集服务端 SDK 自动采集
$app_version字符串应用的版本NYYNN
$ip字符串ipYYYYY
$country字符串国家YYYYN
$city字符串城市YYYYN
$province字符串省份YYYYN
$lib字符串SDK 类型,例如 Python、iOS等YYYYY
$lib_version字符串SDK 版本YYYYY
$manufacturer字符串设备制造商,例如 AppleYYYNN
$model字符串设备型号,例如 iPhone 8,4YYYYN
$os字符串操作系统,例如 iOSYYYYN
$os_version字符串操作系统版本,例如 8.1.1YYYYN
$screen_height数值屏幕高度,例如 1920YYYYN
$screen_width数值屏幕宽度,例如 1080YYYYN
$wifi布尔值是否使用 wifi,例如 trueNYYNN
$browser字符串浏览器名,例如 ChromeYNYNN
$browser_version字符串浏览器版本,例如 Chrome 45YNNNN
$carrier字符串运营商名称,例如 ChinaNetNYYNN
$network_type字符串网络类型,例如 4GNYYYN
$utm_matching_type字符串渠道追踪匹配模式NY1Y1NN
$latest_referrer字符串站外前向地址YNNNN
$latest_referrer_host字符串站外前向域名YNNNN
$latest_utm_source字符串最近广告系列来源YNNY5N
$latest_utm_medium字符串最近广告系列媒介YNNY5N
$latest_utm_term字符串最近广告系列字词YNNY5N
$latest_utm_content字符串最近广告系列内容YNNY5N
$latest_utm_campaign字符串最近广告系列名称YNNY5N
$latest_search_keyword字符串最近一次搜索引擎关键词YNNNN
$latest_traffic_source_type字符串最近一次流量来源类型YNNNN
$is_first_day布尔值是否首日访问YYYYN
$device_id字符串设备 IDY6YYNN

Profile 的预置字段有:

字段名称类型说明JS SDK 自动采集iOS SDK 自动采集Android SDK 自动采集小程序 SDK 自动采集服务端 SDK 自动采集
$city字符串用户所在的城市NNNNN
$province字符串用户所在的省份NNNNN
$name字符串用户名NNNNN
$signup_timeDatetime注册时间NNNNN
$utm_matching_type字符串渠道追踪匹配模式NY1Y1NN
$first_visit_timeDatetime首次访问时间Y3Y4Y4NN
$first_referrer字符串首次前向地址Y3NNNN
$first_referrer_host字符串首次前向域名Y3NNNN
$first_browser_language字符串首次使用的浏览器语言Y3NNNN
$first_browser_charset字符串首次浏览器字符类型(1.8支持)Y3NNNN
$first_search_keyword字符串首次搜索引擎关键词(1.8支持)Y3NNNN
$first_traffic_source_type字符串首次流量来源类型(1.8支持)Y3NNNN
$utm_source字符串首次广告系列来源Y2Y1Y1YN
$utm_medium字符串首次广告系列媒介Y2Y1Y1YN
$utm_term字符串首次广告系列字词Y2Y1Y1YN
$utm_content字符串首次广告系列内容Y2Y1Y1YN
$utm_campaign字符串首次广告系列名称Y2Y1Y1YN

Item 的预置字段有:

字段名称类型说明SDK 自动采集
$is_valid布尔值该 item 是否有效,不传入默认为 trueN
$receive_time数值型该 item 到达时间Y
$update_time数值型该 item 的更新时间,不传入默认为写入时间N

上述 Y 上标含义如下:

  1. $utm_ 开头的相关属性,由 App 渠道追踪功能自动采集,请参考相关文档 渠道追踪
  2. 新用户首次访问时,需要开启 autoTrack 且 URL 中带有 UTM 参数,才会收集,请参考相关文档 Web JS SDK 。
  3. 新用户首次访问时,开启 autoTrack 才会收集,请参考相关文档 Web JS SDK
  4. 新用户首次启动 App,如果调用了 trackInstallation 接口会自动给这个属性赋值。
  5. 小程序 SDK 1.3 版本支持。
  6. 如果 SDK 初始化时候配置了 is_track_device_id:true, 就会采集。

预置属性采集方式

 iOS 中,预置属性的采集方式大致如下:

NSMutableDictionary *p = [NSMutableDictionary dictionary];
  UIDevice *device = [UIDevice currentDevice];
  NSString *deviceModel = [self deviceModel];
  struct CGSize size = [UIScreen mainScreen].bounds.size;
  CTCarrier *carrier = [[[CTTelephonyNetworkInfo alloc] init] subscriberCellularProvider];
  // Use setValue semantics to avoid adding keys where value can be nil.
  [p setValue:[[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] forKey:@"$app_version"];
  [p setValue:carrier.carrierName forKey:@"$carrier"];
  [p addEntriesFromDictionary:@{
                                @"$lib": @"iOS",
                                @"$lib_version": [self libVersion],
                                @"$manufacturer": @"Apple",
                                @"$os": [device systemName],
                                @"$os_version": [device systemVersion],
                                @"$model": deviceModel,
                                @"$screen_height": @((NSInteger)size.height),
                                @"$screen_width": @((NSInteger)size.width),
                                    }];
CODE

Android 中,预置属性的采集方式大致如下:

{
    deviceInfo.put("$lib", "Android");
    deviceInfo.put("$lib_version", VERSION);
    deviceInfo.put("$os", "Android");
    deviceInfo.put("$os_version",
        Build.VERSION.RELEASE == null ? "UNKNOWN" : Build.VERSION.RELEASE);
    deviceInfo
        .put("$manufacturer", Build.MANUFACTURER == null ? "UNKNOWN" : Build.MANUFACTURER);
    deviceInfo.put("$model", Build.MODEL == null ? "UNKNOWN" : Build.MODEL);
    try {
      final PackageManager manager = mContext.getPackageManager();
      final PackageInfo info = manager.getPackageInfo(mContext.getPackageName(), 0);
      deviceInfo.put("$app_version", info.versionName);
    } catch (final PackageManager.NameNotFoundException e) {
      Log.e(LOGTAG, "Exception getting app version name", e);
    }
    final DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
    deviceInfo.put("$screen_height", displayMetrics.heightPixels);
    deviceInfo.put("$screen_width", displayMetrics.widthPixels);

    TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(Context
        .TELEPHONY_SERVICE);
    String operatorString = telephonyManager.getSimOperator();

    if (operatorString == null) {
      // DO NOTHING
    } else if (operatorString.equals("46000") || operatorString.equals("46002")) {
      deviceInfo.put("$carrier", "中国移动");
    } else if (operatorString.equals("46001")) {
      deviceInfo.put("$carrier", "中国联通");
    } else if (operatorString.equals("46003")) {
      deviceInfo.put("$carrier", "中国电信");
    } else {
      deviceInfo.put("$carrier", "其他");
    }
  }
JAVA

限制

一般限制

  1. 事件名(event 的值)和 属性名(properties 中 key 取值)都需是合法的变量名,即不能以数字开头,且只包含:大小写字母、数字、下划线和 $,且事件名和属性名最大长度都为 100;
  2. 类型 type 字段的取值只能是上文列出几种(track, profile_set 等),并且大小写敏感;
  3. 属性 properties 字段必须存在,可以为空( {} );
  4. 事件 time 字段允许的范围是 1000000000000(2001-09-09 09:46:40) ~ 10000000000000(2286-11-21 01:46:40);
  5. 本节 1.7.6 列出了保留属性名;

事件时间限制

导入不合理时间的用户事件将影响数据的准确性(如客户端时间错误导致导入未来的数据),故默认情况下对导入的事件时间进行了限制:

  1. 使用客户端 SDK (iOS、Android)导入的数据,服务端默认只接收事件发生时间在接收时间向前 10 天内和未来向后 1 小时内的数据;
  2. 使用后端语言 SDK (如 Java、Python 等)或导入工具(如 LogAgent、BatchImporter、HdfsImporter),默认只能导入事件时间当前向前 2 年内和未来向后 1 小时内的数据;


注意:

  • 如果希望导入上述默认时间窗口之外的数据,可以联系值班同学修改窗口限制,或在数据中添加 `time_free` 字段(见本文档 2. track 样例)。添加 `time_free` 字段也要保证 time 的格式满足 8.1 节的第 4 点。
  • 因为 App 端只能使用客户端的时间作为事件发生的时间,如果客户端时间不准确,会导致采集端数据有异常,因此神策默认开启时间修正机制:APP 端发生事件时的时间 time 的值为 t1,发送数据时的时间_flush_time 的值为 t2 (客户端时间,且 _flush_time 不入库),服务端接收到数据的时间 $recive_time 时间为 t3 (服务端时间),如果 |t3-t2|>60s,则认为客户端的时间不准确,会对事件触发时间进行修正,修正后事件时间 t1‘=t1+(t3-t2) 。

    以下两种场景不会修正事件发生的时间:
    • 如果采集事件时客户端时间不准确(即 t1 不准确,比如手机刚开机时间不准),而发送数据时客户端时间是准确的(_flush_time 时间准确,比如开启网络校正时间功能),此时发送到服务端时,由于 |t3-t2|<60s,因此不会对 t1 进行修正。
    • 如果数据是延迟上报(比如数据在发送之前用户强杀 App,导致部分数据未及时发送,会先缓存在本地,待下次打开 App,网络正常时会重新尝试发送本地的缓存数据),发送数据时的 _flush_time 时间是准确的,也不会修复事件触发的时间。

同名属性同类型

对 Event 属性,一个属性名,只能具有一种类型(不同的具体事件,同名属性类型也必须相同);
对 Profile 属性,一个属性名,只能具有一种类型;
对于一个属性名,在 Event 和 Profile 中可以具有不同的类型;

属性长度限制

属性的数据类型,及特殊字段长度限制如下:

项目限制
数据类型 NUMBER-9E15 到 9E15 小数点后最多保留3位

数据类型 STRING

最大长度 1024 字节
数据类型 LIST每个 LIST 中最多包含 500 个不大于 255 字节的字符串
用户 distinct_id最大长度 255 字节
用户 original_id最大长度 255 字节

属性数上限

单个项目 Event / Profile 的属性建议合理设置,过多影响导入和查询性能,达到上限则导致导入异常。

建议值硬上限
300 以内2000

保留字段

为了保证查询时属性名不与系统变量名冲突,设置如下保留字段,请避免其作为事件名和属性名(properties 中的 key)使用:

date
datetime
distinct_id
event
events
first_id
id
original_id
device_id
properties
second_id
time
user_id
users
user_group 开头
user_tag 开头
CODE

常见问题

$is_login_id 参数说明

常见使用场景:历史数据导入的 events 或者 users 数据,服务端 SDK 的 track 或 profile 接口。

属性值含义:true ,表示这条数据中的 distinct_id 字段的值为一个真实的 ID(例如客户的业务 ID),如果在这条数据进入数据库之前,此真实 ID 未和设备 ID 绑定,(绑定操作,前端可参考 login 方法,以 JavaScript SDK 为例,在登录和注册成功后,调用 sensor.login(userid); 来标识真实用户。服务端可参考 tracksignup 方法,以 Java SDK 为例,历史数据导入可参考本文档的 tracksignup 接口。),那么这个真实 ID 会自关联。两种情况:

  1. 如果开启了多对一(多对一)的话,新的设备 ID 还是可以和这个自关联的真实 ID 关联。
  2. 在未开启多对一的情况下导致这个真实 ID 之后不能再和设备 ID 绑定。

属性值含义:false,表示这条数据中的 distinct_id 字段的值为一个设备 ID(即客户注册登录之前的标识用户的 ID),之后此设备 ID 还可以和一个真实 ID 绑定。