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

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

请注意,简易用户关联有两种关联方案,一对一和多对一,一对一可以切换到多对一,多对一无法切换回一对一,请务必在正式接入之前选择一个最合适的关联方案。

项目部署后,默认是使用一对一关联方案,若需要更换到多对一关联方案,可联系神策值班同学。

项目重置后,默认会回退到一对一关联方案,若需要更换到多对一关联方案,可联系神策值班同学。

1. 基本概念

1.1. 神策 ID

神策分析使用神策 ID (即 events 表里的 user_id 和 users 表里的 id )来对每个产品的用户进行唯一的标识,而 神策 ID 是基于上报的 ID 数据,按照一定规则生成的。

1.2. 设备 ID(匿名 ID)

需要注意的是,设备 ID 并不一定是设备的唯一标识。例如 Web 端的 Cookies 有可能被清空(例如各种安全卫士),而 iOS 端的 IDFV 在不同厂商的 App 间是不同的。

SDK 类型规则
Android1.10.5 之前版本,默认使用 UUID(例如:550e8400-e29b-41d4-a716-446655440000),App 卸载重装 UUID 会变,为了保证设备 ID 不变,可以通过配置使用 AndroidId(例如:774d56d682e549c3);1.10.5 及之后的版本 SDK 默认使用 AndroidId 作为设备 ID,如果 AndroidId 获取不到则获取随机的 UUID。
iOS1.10.18 及之后版本,如果 App 引入了 AdSupport 库,SDK 默认使用 IDFA 作为匿名 ID。1.10.18 之前版本,神策 SDK 会优先使用 IDFV(例如:1E2DFA10-236A-47UD-6641-AB1FC4E6483F),如果 IDFV 获取失败,则使用随机的 UUID(例如:550e8400-e29b-41d4-a716-446655440000),一般情况下都能够获取到 IDFV。如果使用 IDFV 或 UUID ,当用户卸载重装 App 时设备 ID 会变。也可以通过配置使用 IDFA(例如:1E2DFA89-496A-47FD-9941-DF1FC4E6484A),如果开启 IDFA ,神策 SDK 会优先获取 IDFA,如果获取失败再尝试获取 IDFV。使用 IDFA 能避免用户在重装 App 后设备 ID 发生变化的情况。
JavaScript默认情况下使用 cookie_id(例如:15ffdb0a3f898-02045d1cb7be78-31126a5d-250125-15ffdb0a3fa40a),cookie_id 为神策 JavaScript SDK 默认生成的,存贮在浏览器的 cookie 中,规则为五段不同含义的字段拼接而成来保证唯一性,其中包括两段时间戳,一段屏幕宽高,一段随机数,一段 UA 值。
微信小程序默认情况下使用 UUID(例如:1558509239724-9278730-00c1875d5f63f8-41373096),但是删除小程序,UUID 会变。为了保证设备 ID 不变,建议获取并使用 openid(例如:oWDMZ0WHqfsjIz7A9B2XNQOWmN3E)。 如果选择使用 openid 的话,请注意【操作暂存】,由于获取 openid 是一个异步的操作,但是冷启动事件等会先发生,这时候这个冷启动事件的设备 ID 就不对了。所以我们会把先发生的操作,暂存起来,等获取到 openid 等后调用 sa.init() 后才会发送数据。 openid 的获取和操作暂存的方法,请参考此文档微信小程序 SDK

1.3. 登录 ID

登录 ID 通常是业务数据库里的主键或其它唯一标识。所以 登录 ID,相对来说更精确更持久。但是,用户在使用时不一定注册或者登录,而这个时候是没有登录 ID 的。

登录 ID 会存在 users 表里的 $identity_login_id 字段中。

登录 ID 一旦确定尽量不要修改,如果需要修改请联系神策值班同学。

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

1.4. 方案详解

1.4.1. 一对一:一个设备 ID 关联一个登录 ID

1.4.1.1. 适用场景

有用户注册/登录体系,设备 ID 和登录 ID 关联之后,用户在该设备 ID 上或该登录 ID 下的行为就会贯通,被认为是一个用户(神策 ID)发生的。在进行事件、漏斗、留存等用户相关分析时也会算作一个用户。

关联设备 ID 和登录 ID 的方法虽然实现了更准确的用户追踪,但是也会增加埋点接入的复杂度。所以一般来说,我们建议只有当同时满足以下条件时,才考虑进行 ID 关联:

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

1.4.1.2. 局限性

  • 一个设备 ID 只能和一个登录 ID 关联,而事实上一台设备可能有多个用户使用。
  •  一个登录 ID 只能和一个设备 ID 关联,而事实上一个用户可能用一个登录 ID 在多台设备上登录。
  • 如果不遵循神策接口调用顺序,可能会导致部分用户标识异常(例如历史数据导入时),影响数据统计的准确性。

1.4.1.3. 客户端接入实施方法

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

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

备注一:

SDK 类型 前端获取前端缓存中 ID 的方法
安卓通过 getAnonymousId 方法 获取神策分析 SDK 分配的 匿名 ID,String AnonymousId=SensorsDataAPI.sharedInstance().getAnonymousId();
iOS通过 anonymousId 方法可获取神策分析 iOS SDK 分配的 匿名 ID,获取当前用户的匿名id NSString *anonymousId = [[SensorsAnalyticsSDK sharedInstance] anonymousId];(swift 代码示例:let anonymousId:String = SensorsAnalyticsSDK.sharedInstance().anonymousId())。
JavaScript获取匿名 ID 的方法 sensors.quick('getAnonymousID'); 返回匿名 id (SDK 版本 1.13.4 及以上支持)
微信小程序sensors.getAnonymousID();

1.4.1.4. 服务端接入实施方法

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

  • 在进行服务端埋点或者历史数据导入时,如果当前在 track 或者 profile_set 等接口里传入一个 登录 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 进行关联,以实现更准确的用户识别。

1.4.1.5. 案例

详细步骤说明如下:

  1. 某用户在小米手机上新安装了 App,并进行了一系列操作,SDK 生成的设备 ID 为 X,发送的 anonymous_id 为 X,对应分配的神策 ID 为 1,神策 ID 1 、设备 ID X 存入 users 表的 id, $identity_anonymous_id 字段。
  2. 该用户进行了注册并登录,其登录 ID 为 A,这里会调用 SDK 的 login(客户端)或 track_signup 接口(服务端),设备 ID X 和登录 ID A 关联成功,并将登录 ID A 存入 users 表的 $identity_login_id 字段,神策 ID 仍为 1。
  3. 该用户登录之后继续进行一系列操作,发送的 anonymous_id 为 X,login_id 为 A,神策 ID 仍为 1。
  4. 该用户退出登录并进行了一系列操作,SDK 调用 logout() 方法,发送的 anonymous_id 为 X,当前用户的神策 ID 仍为 1(因为设备 ID X 已与神策 ID 1 关联)。
  5. 该用户把手机送给朋友了,朋友用自己的账号登录设备 X,登录 ID 为 B,此时神策 SDK 尝试将设备 ID X 与登录 ID B 进行关联,由于 X 已与 A 关联,所以此次关联失败,同时会分配一个新的神策 ID 2 来标识此用户,并将登录 ID B 同时存入 users 表的 $identity_login_id 字段(用户的朋友账号上之前未关联过别的设备,且首次登录设备关联失败,此时 $identity_anonymous_id 为空)。
  6. 之后,该用户的朋友一直使用账号 B 在设备 X 上进行了一系列操作,发送的 login_id 为 B,神策都使用神策 ID 2 来标识此用户(因为登录 ID B 已与神策 ID 2 关联,当 login_id 和 anonymous_id 同时存在且无法关联时,事件归属为 login_id 对应用户)。
  7. 该用户更换了一个新的苹果手机,并进行一系列操作,由于尚未登录,此时神策使用全新的设备 ID Y 来标识此设备,发送的 anonymous_id 为 Y,对应分配的神策 ID 为 3,神策 ID 3 、设备 ID Y 存入 users 表的 id, $identity_anonymous_id 字段。
  8. 该用户在苹果手机上使用账号 A 进行登录,此时神策将尝试将设备 ID Y 与登录 ID A 进行关联, 因为登录 ID A 已经关联了一个设备 ID X,所以无法完成关联,此时事件归属为 login_id 对应的用户神策 ID 1。
  9. 该用户登录之后的后续操作,发送的 login_id 为 A,anonymous_id 为 Y,所以仍以神策 ID 1 标识。


在上述案例中,很大程度上已经实现了跨设备的用户贯通,但仍存在局限性:

  • 当用户换手机后,虽然登录账号之后的行为与换手机之前的行为贯通了,但是在新设备上首次登录之前的行为仍没法贯通,仍被识别为新的用户的行为。
  • 当用户把旧手机送给朋友之后,由于旧手机已被关联到自己的登录 ID 了,无法再与朋友的登录 ID 关联。后续使用这台旧手机的用户们,若不登录就操作,则都会被识别为同一个用户(旧手机成功关联的登录 ID )。

1.4.2. 多对一:多个设备 ID 关联一个登录 ID

关联设备 ID 和登录 ID(一对一)虽然已经实现了跨设备的用户贯通,但是对于某些应用场景还是不够准确,因此神策分析提供了新的关联方案,支持一个登录 ID 绑定多个设备 ID 的方案,从而实现更准确的用户追踪。

1.4.2.1. 适用场景

一个用户在多个设备上进行登录是一种比较常见的场景,比如 Web 端和 App 端可能都需要进行登录。支持一个登录 ID 下关联多设备 ID 之后,用户在多设备下的行为就会贯通,被认为是一个神策 ID 发生的。

1.4.2.2. 局限性

  • 一个设备 ID 只能和一个登录 ID 关联,而事实上一台设备可能有多个用户使用。
  • 一个设备 ID 一旦跟某个登录 ID 关联或者一个登录 ID 和一个设备 ID 关联,就不能解除(自动解除)。

1.4.2.3. 实施方法

客户端和服务端的实施方法与方案二完全相同,神策服务端的处理行为会不一样:

  • 对于已经关联过设备的登录 ID,仍然可以和新的设备 ID 进行关联,并存入users 表的 $identity_anonymous_id 中。
  • 当用户发生合并时,系统会默认读取过去 7 天的所有 events 数据,找到需要修复的数据,修改其中的 user_id 字段与 users 表中对应的 id 字段保持一致。

1.4.2.4. 案例

详细步骤说明如下:

1. 某用户在小米手机上新安装了 App,并进行了一系列操作,SDK 生成的设备 ID 为 X,发送的 anonymous_id 为 X,对应分配的神策 ID 为 1,神策 ID 1 、设备 ID X 存入 users 表的 id, $identity_anonymous_id 字段。
2. 该用户进行了注册并登录,其登录 ID 为 A,这里会调用 SDK 的 login(客户端)或 track_signup 接口(服务端),设备 ID X 和登录 ID A 关联成功,并将登录 ID A 存入 users 表的 $identity_login_id 字段,神策 ID 仍为 1。
3. 该用户登录之后继续进行一系列操作,发送的 login_id 为 A,神策 ID 仍为 1。
4. 该用户退出登录并进行了一系列操作,发送的 anonymous_id 为 X,仍使用神策 ID 1 来标识当前用户(因为设备 ID X 已与神策 ID 1 关联)。
5. 该用户把手机送给朋友了,朋友用自己的账号(已注册但未接入神策系统)登录设备 X,登录 ID 为 B,此时神策后端尝试将设备 ID X 与登录 ID B 进行关联,由于 X 已与 A 关联,所以此次关联失败,同时会分配一个新的神策 ID 2 来标识此用户,并将登录 ID B 存入 users 表的 $identity_login_id 字段。
6. 之后,该用户的朋友一直使用账号 B 在设备 X 上进行了一系列操作,发送的 login_id 为 B,神策都使用神策 ID 2 来标识此用户(因为登录 ID B 已与神策 ID 2 关联)。
7. 该用户更换了一个新的苹果手机,并进行一系列操作,由于尚未登录,此时神策使用全新的设备 ID Y 来标识此设备,发送的 anonymous_id 为 Y,对应分配的神策 ID 为 3,将神策 ID 3 、设备 ID Y 存入 users 表的 id, $identity_anonymous_id 字段。
8. 该用户在苹果手机上使用账号 A 进行登录,此时神策将设备 ID Y 与登录 ID A 进行关联,关联成功,对应的神策 ID 依然为 1,同时将设备 ID Y 添加到 users 表中神策 ID 1 的 $identity_anonymous_id字段。
9. 该用户登录之后的后续操作,发送的 login_id 为 A,所以仍以神策 ID 1 标识。

后续修复如下:

  • 由于设备 Y 被关联到登录 ID A 下,修复设备 Y 上登录之前的数据:神策 ID 3 ->神策 ID 1。需要注意的是,对于要修复的数据,使⽤新的 user_id 生成新的 parquet 文件。对于被修复的文件暂时不进行修改,只在索引中进行标记哪些数据已经在源文件中失效。
  • 同时将 users 表中神策 ID 3 的用户属性合并到神策 ID 1 上,并删除 users 表中神策 ID 3 这条数据。进行属性合并时,如果神策 ID 1 的用户该属性有值,则不会修改该属性的值;如果神策 ID 1 的用户该属性没值,且神策 ID 3 的用户该属性有值,则将对应的值合并到神策 ID 1 的用户上,并删除 users 表中神策 ID 3 这条数据。

在上述案例中,真正实现了跨设备的用户贯通,通过修复解决了方案二中换手机登录之前的行为贯通问题,但仍存在局限性:

  • 一个设备只能关联到一个登录 ID 下,当用户把旧手机送给朋友之后,由于旧手机已被关联到自己的登录 ID 了,无法再与朋友的登录 ID 关联。后续使用这台旧手机的用户们,若不登录就操作,则都会被识别为同一个用户(旧手机成功关联的登录 ID)。
  • 而事实上,旧手机上后续的匿名登录很难识别到底是谁,可能归为匿名登录之前最近一次登录的用户会更合理一些。

1.5. 方案对比

  • 方案一:关联设备 ID 和登录 ID(一对一),
    • 当用户换手机后,登录账号之后的行为与换手机之前的行为贯通了,但是在新设备上首次登录之前的行为仍没法贯通,仍被识别为新的用户的行为。
    • 当用户把旧手机送给朋友之后,由于旧手机已被关联到自己的登录 ID 了,无法再与朋友的登录 ID 关联。后续使用这台旧手机的用户们,若不登录就操作,则都会被识别为同一个用户。
  • 方案二:关联设备 ID 和登录 ID(多对一)
    • 当用户把旧手机送给朋友之后,由于旧手机已被关联到自己的登录 ID 了,无法再与朋友的登录 ID 关联。后续使用这台旧手机的用户们,若不登录就操作,则都会被识别为同一个用户。
    • 而事实上,旧手机上后续的匿名登录很难识别到底是谁,可能归为匿名登录之前最近一次登录的用户会更合理一些。

其实,两种方案没有对与错,建议客户结合产品的应用场景以及埋点复杂度来选择合适的方案。

准确的标识用户其实是一个很复杂的问题,神策一直致力于寻求更合理、更准确的方法,满足各种应用场景。