注意:不要在线上页面直接切换不同项目的数据接收地址,会导致首日首次,id 关联异常。建议在线下测试时数据发到测试项目,没问题的话,线上采集的数据直接发往正式项目。

1. 新增用户

一般我们对新增用户的定义是第一次使用产品的用户,或者是一些关键行为(比如注册、购买)的首次触发。在神策分析中,可以结合 是否首日访问( $is_first_day ) 属性来得到每天访问的新增用户,以及结合 是否首次触发事件(  $is_first_time )属性来得到首次触发关键事件的用户。

1.1. 新增用户指标配置

Web 端新增用户定义:当日的独立访客中,历史上首日访问网站的访客定义为新用户。

App 端新增用户定义:当日启动 App 的用户中,历史上首日启动 App 的用户为新用户数。

小程序端新增用户定义:当日启动小程序的用户中,历史上首日启动小程序的用户为新用户数。

用户首次访问时间分布:用户第一次使用 Web/App/小程序 的时间分布

首次触发事件定义:第一次触发 APP 启动/Web 浏览/小程序启动的新用户

1.2. 新增用户标记采集

新用户的标记主要是在客户端完成,神策 SDK 默认会采集的区分新增用户的字段有

前端事件公共属性:是否首日访问($is_first_day)

字段名称类型说明JS SDK 自动采集iOS SDK 自动采集Android SDK 自动采集小程序 SDK 自动采集服务端 SDK 自动采集
$is_first_day布尔值是否首日访问YYYYN

实现逻辑:

1. Web 端:用户第一次访问埋入神策 SDK 页面的当天(即第一天),JS SDK 会在网页的 cookie 中设置一个首日访问的标记,并设置第一天 24 点之前,该标记记为首日为 true,即第一天触发的网页端所有事件中,$is_first_day=true。第一天之后,该标记则为 首日为 false,即第一天之后触发的网页端所有事件中,​$is_first_day= false;

2. 小程序端:用户第一天访问埋入神策 SDK 的页面时,小程序 SDK 会在 storage 缓存中创建一个首日为 true 的标记,并且设置第一天 24 点之前,该标记均为 true。即第一天触发的小程序端所有事件中,$is_first_day=true。第一天之后,该标记则为 首日为 false,即第一天之后触发的小程序端所有事件中,​$is_first_day= false;

3. APP 端:用户安装 App 后,第一次打开埋入神策 SDK 的 App 的当天,Android/iOS SDK 会在手机本地缓存内,创建一个首日为 true 的标记,并且设置第一天 24 点之前,该标记均为 true。即第一天触发的 APP 端所有事件中,$is_first_day=true。第一天之后,该标记则为 首日为 false,即第一天之后触发的 APP 端所有事件中,$is_first_day= false;

前端事件属性:是否首次触发事件($is_first_time)

字段名称类型说明JS SDK 自动采集iOS SDK 自动采集Android SDK 自动采集小程序 SDK 自动采集服务端 SDK 自动采集
$is_first_time布尔值是否首次触发事件YYYYN

实现逻辑:

本地针对 $pageview/$AppStart/$MPLaunch 事件存储一个标记。标记默认是 no,首次为把 no 修改为 yes,之后都是 no。

用户属性:首次访问时间($first_visit_time)

字段名称类型说明JS SDK 自动采集iOS SDK 自动采集Android SDK 自动采集小程序 SDK 自动采集服务端 SDK 自动采集
$first_visit_timeDatetime首次访问时间YYYYN

实现逻辑:

1. Web 端、小程序端:集成神策 Js、MiniProgram SDK 后,设置 autotrack 开启全埋点,SDK 会默认在用户第一次浏览页面/启动小程序时,调用 profile_set_once 接口给用户设置首次访问时间属性。

2. APP 端:集成神策 iOS、Android SDK 后调用 trackInstallation 接口,调用此接口之后会在用户首次使用 app 的时候设置首次访问时间属性。如果没有调用 trackInstallation 接口,不会主动设置首次访问时间。

1.3. 首次首日标记修正

在很多场景下,仅仅依靠前端标记是不准确的。除了前端标记之外,神策为了保证数据更准确,添加了服务端的修正。

1.3.1. 首日访问在服务端的修正

如上文所述,判断新增用户时,是通过 App/Web/小程序上报的属性 $is_first_day (是否首日访问)为 true 来进行判断的。在如下场景下,$is_first_day 取值会出现错误,这就需要依靠神策服务端来进行修正。

场景一:App 缓存被清理或者用户卸载重装。这会导致前端标记被清除。标记清除之后再使用,首日首次属性又会被识别为 true 进行上报。神策服务端会对此进行修正,修正逻辑:当有 $is_first_day (是否首日访问)属性上报并且取值为 true 时,神策服务端会对本次日期与历史该用户首个 $is_first_day (是否首日访问)为 true 的日期进行比较。如果不在同一天,那么修正本次 $is_first_day 为 false。

场景二:由未接入神策 SDK 的版本升级到接入神策 SDK  的版本。比如:小明从 2012 年就开始使用您家的 App,是一个元老级用户。在 2020-1-1 日您家上线了集成神策 SDK 的 Android  新版本,小明升级了 App。神策 SDK  第一次打标记,识别小明的 $is_first_day (是否首日访问)属性为 true 并进行上报。显然这样是不准确的。因为小明虽然对神策来说是新用户,但是本质上他是一个老用户。

对于这种情况可以选择不处理,等大部分历史活跃用户升级使用,随着时间推移,数据趋于准确。

如果需要处理,神策也提供处理方案,即提前把像小明这样的历史用户的首日访问时间导入系统中。通过提前导入的方式,神策预先知道哪些用户是老用户,当这些历史老用户进入神策时,原本  $is_first_day (是否首日访问)为 true 的就会被修正为 false。

导入步骤如下:

1. 生成一个文件,每行为一个用户的 Distinct Id 和首次访问时间(以 unix 时间戳表示):

6D92078A-8246-4BA4-AE5B-76104861E7DC 1513577063
5D3169E2-16BC-316C-12AB-1E2EC1A79E2B 1512057600

注意:

  • 该文件上传之后,只对上传日期之后入库的数据有效。早于首次访问时间文件上传时间的入库的数据无法修改;
  • 该文件内的首次访问时间,会存在于服务端,用于之后对入库的数据校验使用,不会立刻写入用户表。
  • 服务端会根据上传的首次访问时间,对实时导入的事件属性 $is_first_day(是否首日访问)取值为 true 修正,修正规则是仅对 $is_first_day 为 true 的属性值进行修复,且只要导入的事件的 time 和服务端记录的首次访问时间不是同一天就会修正为 false(包含 time 早于服务端的时间也会修正 )。不会修复 $is_first_day 为 false 的属性值。
  • 服务端会根据上传的首次访问时间,修正实时导入的用户属性 $first_visit_time(首次访问时间),修正 $first_visit_time 为服务端上传的首次访问时间 。
  • 服务端上传的首次访问时间,不会 对 $is_first_time 的属性进行修正。目前不支持提前在服务端上传首次访问时间,对 ​$is_first_time = true 的属性进行修正。只有在导入过 ​$is_first_time = true 事件数据之后,服务端才能记录该事件的首次访问时间。

2. 如果文件中的 Distinct Id 是设备 ID(参考2021-10-19_10-11-05_.标识用户 v1.13),继续下一步。若 Distinct Id 是登录 ID,则需要通过 SDK 或导入工具对每个 ID 导入一条 profile_set,设置 is_login_id 为 true,properties 可以为空。例如 Java SDK 可以调用:

sensorsAnalytics.profileSet("123456789", true, Collections.emptyMap());
JAVA

3. 登录神策服务器,使用 sa_cluster 用户执行:

java -cp '/home/sa_cluster/sa/extractor/lib/extractor-1.0-SNAPSHOT.jar:/home/sa_cluster/sa/commonjars/*' com.sensorsdata.analytics.extractor.utils.ImportFirstTimeUtils --project 导入的项目名 --file 数据文件路径 --is_login_id distinct_id 是否是登录 ID,若是则为 yes,否则为 no
CODE
java -cp '/home/sa_cluster/sp/extractor/lib/extractor-1.0-SNAPSHOT.jar:/home/sa_cluster/sp/commonjars/*' com.sensorsdata.analytics.extractor.utils.ImportFirstTimeUtils --project 导入的项目名 --file 数据文件路径 --is_login_id distinct_id 是否是登录 ID,若是则为 yes,否则为 no
CODE
java -cp '/home/sa_cluster/sp/extractor/lib/extractor-1.0-SNAPSHOT.jar:/home/sa_cluster/sp/commonjars/*' com.sensorsdata.analytics.extractor.utils.ImportFirstTimeUtils --project 导入的项目名 --file 数据文件路径 --event 事件名,可选
CODE
sdfadmin import_first_time --project 导入的项目名 --file 数据文件路径 --event 事件名,可选
CODE

1.3.2. 首次触发事件在服务端的修正

目前神策预制采集的“是否首次触发事件” 只针对 $pageview/$AppStart/$AppStartPassively/$MPLaunch 事件才会采集,并不是所有事件都会有这个属性。如果需要对自定义事件添加 $is_first_time 属性,可参考下面的自定义事件设置首次触发事件属性示例

在一些分析场景中,我们希望可以通过一个事件属性判断该事件(自定义事件,前端和后端事件皆可)是否是某个用户首次触发,例如 App 启动中的这个属性可以判断用户是否首次启动 App,加入购物车事件中的这个属性可以判断用户是否首次将商品加入购物车。这就需要我们针对“启动”,“购物”事件来增加 $is_first_time 属性来判断是否是触发关键事件的新用户。

1.3.2.1. 导入时添加字段

在导入事件时,若认为这次事件 可能 是该用户(distinct_id)首次触发,设置 $is_first_time 的值为 true 即可。其原理是神策后端导入模块在数据导入过程中会在遇到 $is_first_time 的值为 true 时判断和 修正 该值,具体来说,若遇到 $is_first_time 的值为 true 的事件数据,神策后端会在数据库查询该用户在该事件是否有首次访问记录,若已记录的触发时间与本次不同,那么将修改 $is_first_time 的值为 false,否则将记录该用户首次触发事件时间并保持 $is_first_time 值为 true。

1.3.2.2. 自定义事件设置首次触发事件属性示例

以 Java SDK 为例:

// 首次触发"BuyGold"事件标记"$is_first_time"为 true,最终导入值为 true
properties.put("$is_first_time", true); 
sa.track("user1", false, "BuyGold", properties);

// do something else ...

// 再次触发"BuyGold"事件标记"$is_first_time"为 true,最终导入值为 false
properties.put("$is_first_time", true); 
sa.track("user1", false, "BuyGold", properties);
CODE

虽然两次都设置了 $is_first_time 为 true,但实际导入后仅第一次导入的值为 true。

1.3.2.3. 注意事项

  1. 仅当 $is_first_time 值为 true 时会触发上述逻辑;
  2. 若之前导入数据没有设置过 $is_first_time 值为 true,那么第一次出现时才会记录首次触发时间,并且以后以这次时间判断;
  3. 该逻辑里判断是否首次触发是以事件触发时间(精确到毫秒)是否与数据库里的值相等作为条件,若两次触发事件时间相同且都设置了 $is_first_time 值为 true 将不会进行修正;一般情况下不会发生这种情况,例如 App 连续发送两次事件,若第二次已经明确知道不是首次时,不应该设置 $is_first_time 值为 true;
  4. 该逻辑受数据导入顺序影响,例如先导入 6 日数据并标记了首次,再导入 3 日的数据并标记了首次,最终 6 日的数据首次被标记为 true,而 3 日的将被标记为 false;
  5. 本功能在 1.8 及以后的版本中支持,且构建时间(可在后端的关于页面查看)在 2017-11-26 之后,否则需要先进行升级。

1.4. 常见问题

1.4.1. 同一用户同一天的事件中首日($is_first_day)有真有假

可能是时区差异造成的,例如用户在 A 地的的客户端时间比中国时间晚 12 个小时,客户服务器的时间是中国时间。当用户在 A 地客户端时间为 2019-08-02  23:00 时触发事件,对应的 $is_first_day 属性为 true,记录该事件的时间是 2019-08-02 11:00; 而当用户在 A 地客户端时间为 2019-08-03  02:00 时触发事件,对应的 $is_first_day 属性为 false,记录该事件的时间是 2019-08-02 14:00。在神策分析查询数据时,就会出现 2019-08-02 这一天同一用户触发的事件中 $is_first_day 有真有假的情况。