在使用前,請先閱讀 數據模型 的介紹。

1. 概述

本文件所介紹的 C++ SDK 是用於記錄用戶端埋點的(而不是伺服器端),例如在 MFC 程序中整合,以收集用戶在程式介面上的操作。若需要伺服器端埋點,請使用 C SDK

本 SDK 區別於其他 SDK 在於將數據透過網路傳送到伺服器端需要在程式碼適當的位置顯式呼叫 Flush() 函式:

  1. 將數據傳送到伺服器端需要有可用的網路連接;
  2. 在適當的位置呼叫,如後台Main Thread,避免阻塞介面操作等。

處理程序退出時,若快取中仍有未 Flush 傳送到伺服器端的數據,則會將數據儲存到指定的暫存檔裡,下次 Flush 時會從檔案加載一起傳送。可以透過參數調整最多暫存的數據條數,若未傳送的數據條數超過該值,則從最早的數據開始淘汰。

對暫存檔的讀寫未使用檔案加密,請避免多處理程序操作同一個檔案。

2. 整合神策分析 SDK

SDK 原始碼檔案可從 https://github.com/sensorsdata/sa-sdk-cpp 取得。使用時可以將程式碼直接整合到目標專案中,或先編譯為函式庫再引入,SDK 原始碼包括:

./include/sensors_analytics_sdk.h
./src/sensors_analytics_sdk.cpp
CPP

SDK 依賴的第三方函式庫包括:

1. curl:用於網路請求;
2. zlib:用於 gzip 壓縮。

其他說明:

  • github 上的 vs2005 分支程式碼支援在 Visual Studio 2005 版本的 C++ 下編譯使用。
  • 若直接引入原始碼檔案並使用Visual Studio 編譯報錯,請看最開始的報錯是否是“warning C4819: 該檔案包含不能在當前程式碼頁(936)中表示的字元。請將該檔案儲存為 Unicode 格式以防止數據遺失”,可以將引入的幾個程式碼檔案“檔案->高級儲存選項->編碼->Unicode-程式碼頁1200”然後儲存再嘗試編譯。 VS2017 及以上可以搜尋 “Visual Studio 2017隱藏高級儲存選項” 找到該功能。
  • 字串型別的屬性值(主要是使用中文值時)需要是合法的 UTF-8 編碼,否則會在 stderr 報錯無法匯入欄位,這時請檢查是否使用了GBK 編碼(例如這個字串所在原始碼檔案是用 GBK 編碼儲存的)。將 GBK 編碼的 string 轉成 UTF-8 的方法,Windows 下可以用 MultiByteToWideChar、WideCharToMultiByte;Linux 下可以用 iconv,詳細方法可以搜尋。

2.1.  Windows 下 SDK 依賴

您可以直接嘗試使用我們編譯好的依賴文件,或自行編譯。

2.1.1. 使用我們編譯的 curl 和 zlib

我們在 Visual Studio 2005 上編譯了適用 Windows XP 的 curl 和 zlib。使用方法如下:

  1. 下載 curl 原始碼,在專案名上右鍵 -> 屬性 -> C/C++ -> 常規 -> “附加包含目錄”增加 curl 原始碼目錄下的 include 目錄;
  2. 下載 zlib 原始碼,在專案名上右鍵 -> 屬性 -> C/C++ -> 常規 -> “附加包含目錄”增加 zlib 原始碼目錄;
  3. 下載編譯好的 curl 和 zlib 函式庫文件,在專案的“資源檔案”右鍵 -> 增加 -> 現有項,選擇 libcurl.dll、libcurl.lib、zlib.lib;

更高版本的 Visual Studio 也可以引入並使用這個預編譯的庫。

2.1.2. 自行編譯 curl

  1. 下載 curl 原始碼:https://curl.haxx.se/download/curl-7.61.1.zip 並解壓縮;
  2. 開始選單中打開 Visual Studio 目錄中的 VS2017的開發人員命令提示字元,並切換到 curl 解壓縮目錄下的 winbuild 目錄下;
  3. 執行命令開始編譯,見下面的程式碼:
  4. 編譯輸出在 curl 目錄 builds 下。
nmake /f Makefile.vc mode=dll
CPP

如需要靜態編譯:

nmake /f Makefile.vc mode=static ENABLE_IDN=no
CPP

如果需要靜態連結 curl,需要在專案設定中:

  1. 連接器 -> 常規 -> 連結庫依賴,增加 libcurl_a.lib;Ws2_32.lib;Wldap32.lib;winmm.lib;Crypt32.lib
  2. 在C/C++ -> 預處理器 -> 預處理器定義中,加入 CURL_STATICLIB

另外,若希望上報數據使用 HTTPS 做傳輸加密,建議編譯 curl 時設定使用 OpenSSL 以取得更好的相容性,或使用我們編譯好的 curl。

2.1.3. 自行編譯 zlib

  1. 下載 zlib 原始碼:https://zlib.net/zlib-1.2.11.tar.gz
  2. 開始選單中打開 Visual Studio 目錄中的 `VS2017的開發人員命令字元`,並切換到 zlib 解壓縮目錄下;
  3. 執行命令開始編譯:
  4. 編譯輸出在 zlib 目錄下。
nmake -f win32/Makefile.msc
CPP

3.  初始化神策分析 SDK

在程式中使用

// 初始化 SDK
// data_file_path: 暫存文件路徑,用於將未傳送的數據臨時儲存在磁碟
// server_url: 神策伺服器網址
// distinct_id: 標識一個用戶的 ID
// is_login_id: distinct_id 參數傳值是否是一個“登入 ID”
// max_staging_record_count: 在傳送佇列中最多儲存的數據條數,若當前未傳送數據條數達到該值,
// 							 新埋點記錄將淘汰最早的一個記錄
sensors_analytics::Sdk::Init(staging_file_path,
                             server_url,
                             distinct_id,
                             is_login_id,
                             max_staging_record_size);
CPP

distinct_id 是標識用戶的 ID,若初始化 SDK 時無可用 ID,可以隨機產生一個 UUID 作為 distinct_id,並且 is_login_id 傳值為 false,並將這個 ID 儲存起來,下次初始化 SDK 時傳入相同的值;若有可用的登入 ID,可以傳入登入 ID 的值,並且 is_login_id 傳值為true。更多關於標識用戶的介紹請見 標識用戶

4. 追蹤事件

首次接入神策分析時,建議先追蹤 3~5 個關鍵的事件,只需要幾行程式碼,便能體驗神策分析的分析功能。例如:

  • 圖片社交產品,可以追蹤用戶瀏覽圖片和評論事件
  • 電商產品,可以追蹤用戶註冊、瀏覽商品和下訂單等事件

用戶透過

// 跟蹤一個用戶的行為
sensors_analytics::Sdk::Track(event_name);
sensors_analytics::Sdk::Track(event_name, event_properties);
CPP

介面記錄事件。以 App 產品為例,可以這樣追蹤一次啟動行為:

sensors_analytics::PropertiesNode event_properties;
event_properties.SetString("computer_name", "MyComputer");
sensors_analytics::Sdk::Track("OpenApp", event_properties);
CPP

4.1. 事件屬性

如前文中的範例,開發者追蹤的事件可以自定義事件的屬性,例如購買商品事件中,將商品 ID、商品分類等資訊作為事件屬性。在後續的分析工作中,事件屬性可以作為統計過濾條件使用,也可以作為維度進行多維分析。對於事件屬性,神策分析有一些限制:

  • 事件屬性是一個 sensors_analytics::PropertiesNode 物件;
  • 透過 PropertiesNode 的方法設定屬性,屬性名稱必需是字串型別,以大小寫字母開頭,由字母和數字組成,長度不超過100個字元;
  • PropertiesNode 屬性值支援 String、Number、Bool、List 和 DateTime,對於神策分析中事件屬性的更多限制,請參考 數據格式

開發者可以透過以下介面,向 `PropertiesNode` 物件加入屬性值,如加入 Bool 型別的屬性:

sensors_analytics::PropertiesNode event_properties;
event_properties.SetBool("use_ticket", true);
CPP

其中屬性名稱必須為大小寫字母開頭、長度不超過 100 的由字母和數字組成的字串。加入 Number 型別的屬性:

event_properties.SetNumber("price", 100.0);
CPP

加入 DateTime 型別的屬性,其中第一個參數為 time_t 類型,如系統函數 `time(NULL)` 的回傳值,第二個參數為毫秒部分。或者直接用一個字串作為 DateTime 型別屬性的值:

event_properties.SetDateTime("view_from_time", time(NULL), 0);
event_properties.SetDateTime("view_to_time", "2018-09-12 18:02:15.234");
CPP

加入 String 型別的屬性,字串必須為 UTF-8 編碼,字串長度為實際的 UTF-8 長度,如一個中文字佔 3 個位元組:

event_properties.SetString("view_page_title", "title1");

std::string page_name = "page-1";
event_properties.SetString("view_page_name", page_name);
CPP

向 List 型別的屬性中增加 String 物件:

std::vector<string> item_list;
item_list.push_back("Book1");
item_list.push_back("Movie2");
event_properties.SetList("view_items", item_list);
CPP

具體使用方式,可以參考上一節中的範例。

5. 追蹤登入與 ID 關聯

若 Init 時使用了隨機產生的裝置 ID,當取得到登入 ID 後,可呼叫 SDK 的 Login 方法將“裝置 ID”與登入 ID 關聯:

sensors_analytics::Sdk::Login("123456");
CPP

更詳細的說明請參考 標識用戶,並在必要時聯繫我們的技術支援人員。

6. 設定用戶屬性

為了更準確地提供針對人群的分析服務,神策分析 SDK 可以設定用戶屬性,如年齡、性別等。用戶可以在留存分析、分佈分析等功能中,使用用戶屬性作為過濾條件或以用戶屬性作為維度進行多維分析。使用

sensors_analytics::Sdk::ProfileSet(const PropertiesNode& properties);
CPP

設定用戶屬性,例如在電商應用中,用戶註冊時,填入了一些個人資訊,可以用 Profile 介面記錄下來:

sensors_analytics::PropertiesNode profile_properties;
profile_properties.SetString("vip_level", "3");
sensors_analytics::Sdk::ProfileSet(profile_properties);

// 設定單個用戶屬性也可以透過:
sensors_analytics::Sdk::ProfileSetNumber("Age", 26);
CPP

用戶屬性中,屬性名稱與屬性值的規則條件與事件屬性相同,詳細說明請參考 數據格式

6.1. 記錄初次設定的屬性

對於只在首次設定時有效的屬性,我們可以使用

sensors_analytics::Sdk::ProfileSetOnce(const PropertiesNode& properties);
CPP

介面記錄這些屬性。與 ProfileSet  介面不同的是,如果被設定的用戶屬性已存在,則這條記錄會被忽略而不會覆蓋已有數據,如果屬性不存在則會自動建立。因此,ProfileSetOnce 比較適用於為用戶設定首次相關屬性。例如:

sensors_analytics::Sdk::ProfileSetOnceString("first_visit_page", "Page567");
CPP

7. 其他

7.1. 使用 HTTPS 數據接收網址

使用 HTTPS 數據接收網址需要 curl 設定了 OpenSSL(建議)或 WinSSL(預設),我們提供的編譯好的 curl 使用了 OpenSSL。

另外在某些作業系統裡,curl 無法正確取得 ca-bundle,有兩種方法處理:

  1. 不增加 ca-bundle,不校驗伺服器端 SSL 憑證(會降低傳輸安全性,建議僅測試時使用)。具體做法是在 sensors_analytics_sdk.cpp 檔案中搜尋 CURLOPT_SSL_VERIFYPEER,取消相關兩行程式碼的註解;
  2. 附帶 ca-bundle 下載網址 。具體做法是在 sensors_analytics_sdk.cpp 檔案中搜尋 CURLOPT_CAINFO,取消該行註解,並指定憑證檔案的路徑。