選取合適的用戶標識對於提高用戶行為分析的準確性有非常大的影響,尤其是漏斗、留存、Session 等用戶相關的分析功能。因此,我們在進行任何數據接入之前,都應當先確定如何來標識用戶。下面會介紹神策分析用戶標識的原理,以及幾種典型情況下的用戶標識方案。

注意:不要在線上頁面直接切換不同專案的數據接收網址,會導致首日首次,ID 異常。建議在線下測試時數據發到測試專案,沒問題的話,線上採集的數據直接發往正式專案。   

基本概念

神策分析使用 神策 ID (即 events 表裡的 user_id 和 users 表裡的 id )來對每個產品的用戶進行唯一的標識,而 神策 ID 是基於 distinct_id 按照一定規則產生的。一般來說,典型的 distinct_id 有以下兩種:

裝置 ID

需要注意的是,裝置 ID 並不一定是裝置的唯一標識。例如 Web 端的 Cookies 有可能被清空(例如各種防毒軟體),而 iOS 端的 IDFV 在不同廠商的 App 間是不同的。不過神策的用戶端 SDK 已經做了各種處理。

SDK 類型規則
Android

1.10.5 之前版本,預設使用 UUID(例如:550e8400-e29b-41d4-a716-446655440000),App 移除重裝 UUID 會變,為了保證裝置 ID 不變,可以透過設定使用 AndroidId(例如:774d56d682e549c);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 值。

登入 ID

登入 ID 通常是業務數據庫裡的主鍵或其它唯一標識。所以 登入 ID,相對來說更精確更持久。但是,用戶在使用時不一定註冊或者登入,而這個時候是沒有登入 ID 的。
登入 ID 會存在 users 表裡的 second_id 欄位
登入 ID  一旦確定儘量不要修改,如果需要修改請聯繫神策值班同學。

需要特別說明的是,神策分析裡的用戶是發生事件的主體,不一定是終端用戶,也可以是一個企業、商家甚至是一輛汽車,需要根據具體的分析需求靈活決定。

方案詳解

請注意,以下各方案之間互不相容,請務必在正式接入之前選擇一個最合適的方案

方案一:只使用裝置 ID

適用場景

適合沒有用戶註冊體系,或者極少數用戶會進行多裝置登入的產品,如工具類產品、搜尋引擎、部分電商等。這也是絕大多數其它數據分析產品唯一提供的方案。

侷限性

  • 同一用戶在不同裝置使用會被認為不同的用戶(神策 ID 不同,跟裝置 ID 關聯),對後續的分析統計有影響。
  • 不同用戶在相同裝置使用會被認為是一個用戶(神策 ID 相同,因為裝置 ID 相同),也對後續的分析統計有影響。
  • 但如果用戶跨裝置使用或者多用戶共用裝置不是產品的常見場景的話,可以忽略上述問題。

實施方法

  • 直接使用用戶端 SDK 產生的 裝置 ID 作為 distinct_id 即可,不需要進行特殊處理。如果不希望使用神策 SDK 預設的 裝置 ID 產生規則,可以直接呼叫 identify 介面來傳入自定義的 裝置 ID ,該方法建議在 SDK 初始化完成之後立即呼叫。
  • 如果是有用戶註冊體系的產品,可以額外在所有 Event 裡加入 login_user_id 屬性標識用戶的正式 ID,這樣也可以篩選出某個用戶的具體行為,或者單獨看登入前/登入後的用戶行為。 

案例

注意:X,Y 均有用戶屬性,所以即使 second_id 沒值,也可以以 first_id 的形式寫進用戶表。

詳細步驟說明如下:

1. 某用戶在小米手機上新安裝了 App,並進行了一系列操作,SDK 產生的裝置 ID 為 X,發送的 distinct_id 為 X,對應分配的神策 ID 為 1,若用戶端 SDK 呼叫介面 profile_set ,則將神策 ID 1 、裝置 ID X 存入 users 表的 id, first_id 欄位。

2. 該用戶進行了註冊並登入,裝置未變,發送的 distinct_id 仍為 X,所以神策 ID 仍為 1。

3. 該用戶登入之後繼續進行一系列操作,發送的 distinct_id 仍 為 X,所以神策 ID 仍為 1。

4. 該用戶退出登入並進行了一系列操作,發送的 distinct_id 仍為 X,所以神策 ID 仍為 1。

5. 該用戶把手機送給朋友了,朋友用自己的帳號登入(已註冊但未接入神策系統)裝置 X,但發送的 distinct_id 仍為 X,所以神策 ID 仍為 1。

6. 之後,該用戶的朋友一直使用帳號 B 在裝置 X 上進行了一系列操作,由於裝置未變,所以神策 ID 仍為 1。

7. 該用戶更換了一個新的蘋果手機,並進行一系列操作,由於裝置 ID 變為 Y,發送的 distinct_id 為 Y,分配的神策 ID 為 2,若用戶端 SDK 呼叫介面 profile_set ,則將神策 ID 2 、裝置 ID Y 存入 users 表的 id, first_id 欄位。

8. 該用戶在蘋果手機上使用帳號 A 進行登入,發送的 distinct_id 為 Y,所以神策 ID 仍為 2。

9. 該用戶登入之後的後續操作,都以神策 ID 2 標識,只要不更換裝置。

在上述案例中,僅使用裝置 ID 識別用戶的好處就是邏輯很簡單,當然侷限性也很明顯:

  • 當用戶換手機後,用戶換手機前後的行為無法關聯上。
  • 當用戶把手機送給朋友後,朋友的行為卻仍記在該用戶下。

方案二:關聯裝置 ID 和登入 ID(一對一)

僅使用 裝置 ID 標識用戶雖然簡單,但是對於某些應用場景這種方式不夠準確,因此神策分析提供了另一種關聯 裝置 ID 和 登入 ID 的方案,在一定程度上融合 裝置 ID 和 登入 ID,從而實現更準確的用戶追蹤。

適用場景

成功關聯裝置 ID 和登入 ID 之後,用戶在該裝置 ID 上或該登入 ID 下的行為就會貫通,被認為是一個神策 ID 發生的。在進行事件、漏斗、留存等用戶相關分析時也會算作一個用戶。

關聯裝置 ID 和登入 ID 的方法雖然實現了更準確的用戶追蹤,但是也會增加埋點接入的複雜度。所以一般來說,我們建議只有當同時滿足以下條件時,才考慮進行 ID 關聯:

  1. 需要貫通一個用戶在一個裝置上註冊前後的行為。
  2. 需要貫通一個註冊用戶在不同裝置上登入之後的行為。

侷限性

  • 一個裝置 ID 只能和一個登入 ID 關聯,而事實上一台裝置可能有多個用戶使用。
  • 一個登入 ID 只能和一個裝置 ID 關聯,而事實上一個用戶可能用一個登入 ID 在多台裝置上登入。
  • 如果不遵循神策介面呼叫順序,可能會導致部分用戶標識異常(例如歷史數據匯入時),影響數據統計的準確性。

用戶端接入實施方法

用戶端接入是指使用 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 及以上支援)

伺服器端接入實施方法

伺服器端接入包括使用 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 進行關聯,以實現更準確的用戶識別。

案例

注意:Y 有用戶屬性,所以即使 second_id 沒有值,也可以以 first_id 的形式寫進用戶表。

詳細步驟說明如下:

1. 某用戶在小米手機上新安裝了 App,並進行了一系列操作,SDK 產生的裝置 ID 為 X,發送的 distinct_id 為 X,對應分配的神策 ID 為 1,若用戶端 SDK 呼叫介面 profile_set ,則將神策 ID 1 、裝置 ID X 存入 users 表的 id, first_id 欄位。

2. 該用戶進行了註冊並登入,其登入 ID 為 A,這裡會呼叫 SDK 的 login(用戶端)或 track_signup 介面(伺服器端),裝置 ID X 和登入 ID A 關聯成功,並將登入 ID A 存入 users 表的 second_id 欄位,神策 ID 仍為 1。

3. 該用戶登入之後繼續進行一系列操作,發送的 distinct_id 為 A,神策 ID 仍為 1。

4. 該用戶退出登入並進行了一系列操作,發送的 distinct_id 為 A,SDK 不呼叫任何方法,仍使用神策 ID 1 來標識當前用戶(因為登入 ID A 已與神策 ID 1 綁定)。

5. 該用戶把手機送給朋友了,朋友用自己的帳號(已註冊但未接入神策系統)登入裝置 X,登入 ID 為 B,此時神策 SDK 嘗試將裝置 ID X 與登入 ID B 進行關聯,由於 X 已與 A 關聯,所以此次關聯失敗,同時會分配一個新的神策 ID 2 來標識此用戶,並將登入 ID B 同時存入 users 表的 first_id 和 second_id 欄位(用戶的朋友帳號上之前未關聯過別的裝置,且首次登入裝置關聯失敗,則將登入 ID 同時記錄到 first_id 上)。

6. 之後,該用戶的朋友一直使用帳號 B 在裝置 X 上進行了一系列操作,發送的 distinct_id 為 B,神策都使用神策 ID 2 來標識此用戶(因為登入 ID B 已與神策 ID 2 綁定)。

7. 該用戶更換了一個新的蘋果手機,並進行一系列操作,由於尚未登入,此時神策使用全新的裝置 ID Y 來標識此裝置,發送的 distinct_id 為 Y,對應分配的神策 ID 為 3,若用戶端 SDK 呼叫介面 profile_set ,則將神策 ID 3 、裝置 ID Y 存入 users 表的 id, first_id 欄位。

8. 該用戶在蘋果手機上使用帳號 A 進行登入,此時神策將嘗試將裝置 ID Y 與登入 ID A 進行關聯,由於 A 已經與 X 關聯,因此會關聯失敗,但是依然會切換到以 A 為登入 ID 的用戶,其對應的神策 ID 依然為 1。

9. 該用戶登入之後的後續操作,發送的 distinct_id 為 A,所以仍以神策 ID 1 標識。

在上述案例中,很大程度上已經實現了跨裝置的用戶貫通,但仍存在侷限性:

  • 當用戶換手機後,雖然登入帳號之後的行為與換手機之前的行為貫通了,但是在新裝置上首次登入之前的行為仍沒法貫通,仍被識別為新的用戶的行為。
  • 當用戶把舊手機送給朋友之後,由於舊手機已被關聯到自己的登入 ID 了,無法再與朋友的登入 ID 關聯。後續使用這台舊手機的用戶們,若不登入就操作,則都會被識別為同一個用戶(舊手機成功關聯的登入 ID )。

方案三:關聯裝置 ID 和登入 ID(多對一)

關聯裝置 ID 和登入 ID(一對一)雖然已經實現了跨裝置的用戶貫通,但是對於某些應用場景還是不夠準確,因此神策分析提供了新的關聯方案,支援一個登入 ID 綁定多個裝置 ID 的方案,從而實現更準確的用戶追蹤。

適用場景

一個用戶在多個裝置上進行登入是一種比較常見的場景,比如 Web 端和 App 端可能都需要進行登入。支援一個登入 ID 下關聯多裝置 ID 之後,用戶在多裝置下的行為就會貫通,被認為是一個神策 ID 發生的。

侷限性

  • 一個裝置 ID 只能和一個登入 ID 關聯,而事實上一台裝置可能有多個用戶使用。
  • 一個裝置 ID 一旦跟某個登入 ID 關聯或者一個登入 ID 和一個裝置 ID 關聯,就不能解除(自動解除)。而事實上,裝置 ID 和登入 ID 的動態關聯才應該是更合理的。

實施方法

用戶端和伺服器端的實施方法與方案二完全相同,神策伺服器端的處理行為會不一樣:

  • 對於已經關聯過裝置的登入 ID,仍然可以和新的裝置 ID 進行關聯,並存入users 表新增欄位 $device_id_list (關聯用戶 id 列表) 中。
  • 例⾏任務每天讀取 users 表中需要修復的 id 列表,即 $device_id_list。讀取過去 2 天的所有 events 數據,找到需要修復的數據。修改其中的 user_id 欄位與 profile 表中對應的 id 欄位保持一致。

案例

詳細步驟說明如下:

1. 某用戶在小米手機上新安裝了 App,並進行了一系列操作,SDK 產生的裝置 ID 為 X,發送的 distinct_id 為 X,對應分配的神策 ID 為 1,若用戶端 SDK 呼叫介面 profile_set ,則將神策 ID 1 、裝置 ID X 存入 users 表的 id, first_id 欄位。

2. 該用戶進行了註冊並登入,其登入 ID 為 A,這裡會呼叫 SDK 的 login(用戶端)或 track_signup 介面(伺服器端),裝置 ID X 和登入 ID A 關聯成功,並將登入 ID A 存入 users 表的 second_id 欄位,神策 ID 仍為 1。

3. 該用戶登入之後繼續進行一系列操作,發送的 distinct_id 為 A,神策 ID 仍為 1。

4. 該用戶退出登入並進行了一系列操作,發送的 distinct_id 為 A,SDK 不呼叫任何方法,仍使用神策 ID 1 來標識當前用戶(因為登入 ID A 已與神策 ID 1 綁定)。

5. 該用戶把手機送給朋友了,朋友用自己的帳號(已註冊但未接入神策系統)登入裝置 X,登入 ID 為 B,此時神策 SDK 嘗試將裝置 ID X 與登入 ID B 進行關聯,由於 X 已與 A 關聯,所以此次關聯失敗,同時會分配一個新的神策 ID 2 來標識此用戶,並將登入 ID B 同時存入 users 表的 first_id 和 second_id 欄位(用戶的朋友帳號上之前未關聯過別的裝置,且首次登入裝置關聯失敗,則將登入 ID 同時記錄到 first_id 上)。

6. 之後,該用戶的朋友一直使用帳號 B 在裝置 X 上進行了一系列操作,發送的 distinct_id 為 B,神策都使用神策 ID 2 來標識此用戶(因為登入 ID B 已與神策 ID 2 綁定)。

7. 該用戶更換了一個新的蘋果手機,並進行一系列操作,由於尚未登入,此時神策使用全新的裝置 ID Y 來標識此裝置,發送的 distinct_id 為 Y,對應分配的神策 ID 為 3,若用戶端 SDK 呼叫介面 profile_set ,則將神策 ID 3 、裝置 ID Y 存入 users 表的 id, first_id 欄位。

8. 該用戶在蘋果手機上使用帳號 A 進行登入,此時神策將裝置 ID Y 與登入 ID A 進行關聯,關聯成功,對應的神策 ID 依然為 1,同時將裝置 ID Y 添加到 users 表中神策 ID 1 的 $device_id_list 欄位。 9. 該用戶登入之後的後續操作,發送的 distinct_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)。
  • 而事實上,舊手機上後續的匿名登入很難識別到底是誰,可能歸為匿名登入之前最近一次登入的用戶會更合理一些。

方案對比

將上述三個方案放到一起,可以明顯看到三種方案的區別,如下表所示:

事件序號 事件神策 ID_方案一神策 ID_方案二神策 ID_方案三
1安裝 App111
2登入 App111
3使用 App111
4使用 App111
5登入 App122
6使用 App122
7使用 App233->1
8使用 App211
9使用 App211
  • 方案一:僅使用裝置 ID,不管用戶是誰,只要裝置未變(裝置 ID 未變),神策 ID 不變。
  • 方案二:關聯裝置 ID 和登入 ID(一對一),
    • 當用戶換手機後,登入帳號之後的行為與換手機之前的行為貫通了,但是在新裝置上首次登入之前的行為仍沒法貫通,仍被識別為新的用戶的行為。
    • 當用戶把舊手機送給朋友之後,由於舊手機已被關聯到自己的登入 ID 了,無法再與朋友的登入 ID 關聯。後續使用這台舊手機的用戶們,若不登入就操作,則都會被識別為同一個用戶。
  • 方案三:關聯裝置 ID 和登入 ID(多對一)
    • 當用戶把舊手機送給朋友之後,由於舊手機已被關聯到自己的登入 ID 了,無法再與朋友的登入 ID 關聯。後續使用這台舊手機的用戶們,若不登入就操作,則都會被識別為同一個用戶)。
    • 而事實上,舊手機上後續的匿名登入很難識別到底是誰,可能歸為匿名登入之前最近一次登入的用戶會更合理一些。

其實,三種方案沒有對與錯,建議客戶結合產品的應用場景以及埋點複雜度來選擇合適的方案。

準確的標識用戶其實是一個很複雜的問題,神策一直致力於尋求更合理、更準確的方法,滿足各種應用場景,後續還會推出動態關聯裝置 ID 和登入 ID,敬請期待。