如何准确的标识用户

最后更新于:2018-08-08 11:17:31

选取合适的用户标识对于提高用户行为分析的准确性有非常大的影响,尤其是漏斗、留存、Session 等用户相关的分析功能。因此,我们在进行任何数据接入之前,都应当先确定如何来标识用户。下面会介绍神策分析用户标识的原理,以及几种典型情况下的用户标识方案。

1. 基本概念

神策分析使用 distinct_id 来对每个产品的用户进行唯一的标识,但是并没有限制这个 distinct_id 具体由什么构成。一般来说,典型的 distinct_id 有以下两种:

  1. 设备 ID

    设备 ID 本质上是对设备的唯一标识,例如 iOS 的 IDFA/IDFV,Web 的 Cookie 等。我们的客户端 SDK 会默认生成设备 ID,且默认会把这个设备 ID 作为 distinct_id 来使用。如果有特殊的需要,也可以根据自己的需求,来手动生成设备 ID

    需要注意的是,设备 ID 也并不一定是设备的永久标识。例如 Web 的 Cookie 有可能因为各种情况被清空(例如各种安全卫士、或者微信内嵌的浏览器等),而 iOS 的 IDFV 则在不同厂商的 App 间是不同的。不过我们的客户端 SDK 已经做了各种处理,以尽量减少类似的问题导致的统计误差。

    使用设备 ID 作为 distinct_id 的主要问题是,一个设备有可能被多个用户使用,而一个用户也可能使用多个设备,在某些场景下可能会导致统计误差。

  2. 登录 ID

    通常是业务数据库里的主键或其它唯一标识。登录 ID 是更加精确和持久的 distinct_id,但是它也存在一个非常明显的缺陷,即用户在使用很多功能的时候并不一定已经注册或者登录,而这个时候是没有用户 ID 的。

需要特别说明的是,神策分析中的用户是指发生事件的主体,不一定是指终端用户,也可以是一个企业、商家甚至是一辆汽车,需要根据具体的分析需求灵活决定。

2. 方案详解

请注意,以下的各个方案之间是互不兼容的,请务必在正式进行接入之前选择一个最合适的方案。

2.1 只使用设备 ID

2.1.1 适用场景

适合没有用户注册体系,或者极少数用户会进行多设备登录的产品,如工具类产品、搜索引擎、部分电商等。这也是绝大多数其它数据分析产品唯一提供的方案。

2.1.2 具体做法

直接使用客户端 SDK 产生的设备 ID 作为 distinct_id 即可,不需要进行特殊处理。如果不希望使用神策 SDK 默认的设备 ID 生成规则,可以直接调用 identify 接口来传入自定义的设备 ID,该方法建议在 SDK 初始化完成之后立即调用。

如果是有用户注册体系的产品,可以额外在所有 Event 里加入 login_user_id 属性标识用户的正式 ID,这样也可以筛选出某个用户的具体行为,或者单独看登录前/登录后的用户行为。

2.1.3 方案缺点

主要是同一个用户在不同设备使用会被认为是两个用户,对于部分统计会有影响。但如果多设备并不是产品的一个常见场景,则可以忽略此问题。

2.2 关联设备 ID 和登录 ID

使用设备 ID 标识用户虽然简单,但是对于某些应用场景这种方式会不够准确,因此神策分析提供了一系列的方案可以在一定程度上融合设备 ID登录 ID,以满足不同场景的需求。

2.2.1 适用场景

神策系统内部的每个用户实体允许有两个 distinct_id:一个设备 ID 和一个登录 ID,在关联成功的情况下,这两个 distinct_id 发生的所有行为都会被认为是同一个用户实体发生的,在进行事件、漏斗、留存等用户相关的分析的时候也只会算作一个用户。因此,如果准确的使用这种方式,就可以实现更准确的用户跟踪。

ID 关联虽然有很大的用处,但是依然有一些局限性,同时也会增加埋点接入的复杂度。所以一般来说,我们建议只有当同时满足以下两个条件时,才考虑进行 ID 关联:

  1. 需要贯通一个用户在一个设备上注册前后的行为。
  2. 需要贯通一个注册用户在不同设备上登录之后的行为。

2.2.2 使用限制

  • 一个设备 ID 只能和一个登录 ID 进行关联,反之亦然。
  • 任何设备 ID登录 ID 只会关联到一个用户实体,虽然事实上一个物理设备有可能被多个用户实体使用。
  • 如果不遵循接口的调用顺序,可能会导致部分用户标识异常,影响数据统计的正确性。

2.2.3 客户端接入流程

客户端接入是指使用 iOS / Android / JavaScript 等 SDK 进行埋点,具体调用流程如下:

  • 在 SDK 初始化完成之后,神策的 SDK 会自动生成一个设备 ID 作为用户标识。
  • 在用户进行登录/注册或任何可以拿到登录 ID 的操作的时候,客户端主动调用 login(登录 ID) 接口。
  • 在用户注销的时候,有几种选择:
    • 不做任何操作,这样的话相当于神策会继续使用之前的用户标识来进行追踪。如果没有特殊情况,一般建议选择该方式。
    • 主动调用logout()方法,这样会清空登录 ID,重新使用设备 ID 作为用户标识,一般情况没有必要选择此方式。
    • 对于 JavaScript SDK,还可以调用logout(true)方法,该方法除了清空登录 ID之外,还会重新初始化设备 ID

2.2.4 服务端接入流程

服务端接入包括使用 Java / Python / PHP 等 SDK,以及直接使用 BatchImporter / LogAgent / FormatImporter 等工具进行导入的情况,具体流程如下:

  • 在进行服务端埋点或者历史数据导入时,如果当前在 track 或者 profile_set 等接口里传入的 distinct_id 是一个登录 ID,那么 is_login_id 的参数值必须为 true,来告诉神策这是一个登录 ID 产生的行为,以 Java SDK 为例:
    • 如果是登录 ID 产生的行为:sa.track(registerId, true, "SubmitOrderDetail", properties);
    • 如果是匿名 ID 产生的行为:sa.track(deviceId, false, "SubmitOrderDetail", properties);
  • 对于任意一个登录 ID,只要导入过任意数据,那么该登录 ID 后面将不能和任何设备 ID进行关联。因此在进行历史数据(即接入神策之前产生的数据)的导入时,建议按照下面的方式操作:
    • 先进行正常的 SDK 接入,并且保证所有用户都正常的通过了 login/track_signup 接口,在运行一段时间之后再导入历史数据,因为这个时候大部分活跃用户都应该已经成功进行了关联。
    • 如果历史数据中存在登录 ID 和其对应设备 ID 的对应关系,那么也可以先把这批数据构造 track_signup 请求进行导入,然后再导入具体的用户行为或者用户属性数据即可。
  • 由于客户端埋点存在一定的数据丢失概率,我们建议开发者也在服务端的注册接口里调用 track_signup 方法,将新用户的 设备 ID登录 ID 进行关联,以实现更准确的用户识别。

2.2.5 原理说明

下面以一个实际的场景来说明用户识别的机制,其中:

  • 发送的 Distinct Id:表示当前事件所使用的 Distinct Id,可能是登录 ID 或匿名 ID。如果是 ID 关联操作(login / track_signup)则两个 ID 会同时发送。
  • 是否登录 ID:当前行为的 Distinct Id 是否为一个登录 ID。
  • 神策 User Id:神策内部给该用户分配的唯一标识,是用于计算触发用户数、漏斗、留存等的最终依据,对应自定义查询中 events 表中的 user_id 及 users 表中的 id 字段。
步骤序号 发送的 Distinct Id 是否登录 ID 神策 User Id
1 X 1
2 A -> X ID 关联(成功) 1
3 A 1
4 A 1
5 B -> X ID 关联(失败) 2
6 B 2
7 Y 3
8 A -> Y ID 关联(失败) 1
9 A 1

详细的步骤说明如下:

  1. 某用户在小米手机上新安装了 App,并进行了一系列操作,SDK 生成的设备 ID 为 X,对应分配的神策 User Id 为 1。
  2. 该用户进行了注册并登录,其登录 ID 为 A,这里需要调用 SDK 的 login(客户端) 或 track_signup 接口(服务端),此时神策会将设备 ID X 与 登录 ID A 进行成功关联。
  3. 该用户在登录之后继续进行了一系列行为。
  4. 该用户退出登录并进行了一系列的操作,SDK 不调用任何方法,此时神策依然使用登录 ID A 来标识当前用户。
  5. 该用户使用一个已注册但未接入神策系统的的账户 B 来进行登录,此时神策将尝试将 X 与 B 进行关联,由于 X 已经和 A 关联,所以会关联失败,同时会分配一个新的神策 User Id 为 2。
  6. 该用户使用账户 B 进行了一系列行为,这里神策都使用登录 ID B 来标识此用户。
  7. 该用户更换了一个全新的苹果手机,并进行了一系列操作,由于尚未登录,此时神策使用全新的设备 ID Y 来标识此用户,对应分配的神策 User Id 为 3。
  8. 该用户在苹果手机上使用账户 A 进行登录,此时神策将尝试将设备 ID Y 与登录 ID A 进行关联,由于 A 已经与 X 关联,因此会关联失败,但是依然会切换到以 A 为登录 ID 的用户,其对应的神策 User Id 依然为 1。
  9. 该用户在苹果手机上的后续行为都以登录 ID A 来标识。

2.2.6 方案缺点

虽然该方案可以实现跨设备的用户贯通、以及准确的注册漏斗,不过还是有一些局限性:

  1. 需要理解较多的底层细节,实现代价较大。
  2. 如果一个已注册用户(即已经和某个设备 ID 关联过了)在一个新设备上进行操作,那么他在这个新设备的登录前行为是无法被准确识别的。
  3. 同样的,如果一个已注册的设备(即已经被关联到某个登录 ID了)上再次有新用户进行注册,也无法再次进行关联。

实际上,如果我们考虑的更深入一点,会发现上面所说的局限性其实是一个比较复杂的问题。我们可以假设一个实际的使用场景,例如在某一个设备(例如浏览器)上发生以下事情:

  1. 用户 A 注册并登录,然后使用了某些功能,之后注销。
  2. 某匿名用户 B 使用了某些功能。
  3. 用户 C 注册并登录,然后使用了某些功能。

这个时候我们会发现,对于用户 B 到底是谁,其实存在很多种可能性:可能是 A 或者 C,或者就是一个独立的用户;甚至 A/B/C 都可能是同一个用户的马甲。很遗憾,在目前的方案下我们并不能准确的做出判定。

2.2.7 属性说明

从神策分析 1.7 某个版本开始,我们加入了一个行为事件预置属性 $is_login_id(中文名 是否登录 ID)来标记这条事件发送时使用的是否是登录 ID,这里的登录 ID 指 “关联过设备 ID 的登录 ID” 或 “后端 SDK 显式标记过 is_login_id 的 ID”。需要注意的是仅有正确的进行了上述 2.2 关联设备 ID 和登录 ID 方案中的 ID 关联或 is_login_id 标记后此值才有意义,一些场景例如:

  1. 设备调用 login 传入登录 ID 之后,调用 logout 之前发送的行为事件数据 是否登录 ID 被标记为真;
  2. 服务端 SDK 导入时使用的 ID 标记 is_login_id 为真,包括本次和之后使用这个 ID 导入的数据 是否登录 ID 被标记为真;

神策分析会继续在更加准确的用户跟踪方面做出努力,以满足不同场景下的分析需求,敬请期待。