1. 用户匹配策略
1.1. ID 体系设计
事件表和用户表都包含 userId
属性,该属性作为用户的唯一标识。
有两种场景:
- 基于设备来作为用户标识:这种场景下,用户标识比较准确,但无法跨端做用户匹配
- 基于用户ID来作为用户标识:可跨端做用户匹配,但用户在匿名和注册,以及登出及登入过程,会有可能出现多个
userId
,导致日活、留存、漏斗等统计有差距。
1.2. 基于用户 ID 做为用户标识的优化方案
1.2.1. 匿名用户
SDK 默认会生成 deviceUdid
, 作为设备唯一标识,userId
默认会被设置为该值(在实时流计算过程处理)。
- iOS 第一次使用时会通过随机数方式,生成设备 ID,并保存在 keychain 中用于再次打开时获取(为了更好的匹配用户,SDK 还会收集
idfa
和idfv
)。 - Andoroid 第一次使用时会获取 android_id, mac 地址等信息生成设备 ID。
- Web 端则是通过在 cookie 中保存自动生成的随机 ID 来作为用户唯一标识。
- 服务端尽量使用用户帐号 ID 来作为用户唯一标识(包括匿名用户 ID)。
如果产品业务方针对每个匿名用户已经生成账户ID,则也可以通过调用 SDK loginUser
接口来记录用户的账户 ID,作为匿名用户 ID 标识,不采用 deviceUdid
作为匿名用户 ID 标识。
1.2.2. 注册用户
当用户通过产品登录后,需要调用 SDK loginUser
接口来记录用户的账户 ID,登录之后发送的所有事件的 userId
值更改为用户的账户 ID。但用户在注册过程中,是从匿名用户转为注册用户,同一用户会出现不同的 userId
值,可能导致日活、留存、转化漏斗出现问题。
解决方法是:
在注册成功后,需要再次调用 loginUser
接口,传入新的 userId
值,如果前后两个 userId
值不相同,系统会通过内部事件记录两个 userId
的关联关系(如老 userId
是空,实时流计算同样会使用 deviceUdid
值来做填充)。如果一个设备或者浏览器会被多人使用,为了避免被绑定人同一人,需要在切换用户时调用 logoutUser
接口,然后再调用 loginUser
接口进行新 userId
设置,这个过程,不会做 userId
绑定。关于user接口,推荐使用姿势:
- 推荐用户在App启动之后尽早调用
loginUser
接口userId
,减少匿名用户数据; - 不推荐用户调用
logoutUser
接口,调用此接口时SDK将会清空存在本地的userId
,造成不必要的匿名用户访问。如果存在多个用户共用的一台设备的情况,推荐直接调用loginUser
,此时可以保证后续产品的userId
为最新的userId
;
1.3. 存在问题
1.3.1. 用户错误关联
上节方案可以解决匿名用户通过注册转为注册用户两个 userId
之间 的绑定问题,但也带来了另一个问题:用户不调用 logoutUser
多次连续调用 loginUser
,会导致系统错误将两两 userId
进行绑定。
不调用 logoutUser
分两种情况:
- 产品开发在用户登出过程忘了调用,这点需要和开发沟通,统一接入规范,调用错误会导致数据源头就出现问题,很难修复。
- 在移动端因为版本升级、Web端因为 cookie 失效等情况下,用户会被自动登出,因为不是主动触发,无法在 SDK 端进行监测,同样会导致
logoutUser
接口没被调用。
具体影响:
按常识,移动设备多人共享的情况较少,切换用户场景出现概率较低,错误匹配对整体数据影响较少。
但电脑上,多个用户使用同一个浏览器访问同一产品的情况不低,会导致多个用户被错误的关联成同一个用户,可能对整体数据造成影响。因为用户是跨端的,所以,这一问题对移动端的用户数据也会产生影响。
登出用户 ID 设置
当用户在产品中登出时,userId
需要重新赋值,这里我们有两个不同的考量:
- 恢复到之前的
deviceUdid
,考虑到即使用户登出,其实也还是同一个用户 - 重新生成新的
deviceUdid
,考虑到用户既然手工登出,那么可能是另一个用户要用,一个设备或者浏览器有可能多个人共用。
当前采用 1 方案。