C SDK
C SDK 使用说明
在使用前,請先閱讀 數據模型 的介绍。
1. 整合神策分析 SDK
開發者可以在 C 程式中整合 神策分析 SDK,使用神策分析採集並分析用戶數據。
從 GitHub 下載 神策分析 SDK 的原始碼,可在本地編譯,透過靜態庫的形式加入專案中,也可以直接將來源檔案引入專案中。 SDK 原始碼包括:
./LICENSE
./Makefile // Makefile
./sensors_analytics.h // SDK 頭檔案
./sensors_analytics.c // SDK 來源檔案
./demo.c // Demo 程式,使用 LoggingConsumer 將 log 檔輸出到本機硬碟
開發者編譯 SDK 後,會產生靜態庫:
./output/include/sensors_analytics.h
./output/lib/libsensorsanalytics.a
SDK 符合 ANSI C99 規範,部分功能依賴 POSIX 函式庫,不依賴第三方函式庫。
開發者透過 C SDK 在程式中記錄用戶行為數據。 SDK 將格式化的行為數據以 log 檔的形式輸出到本地硬碟檔案中,開發者需要透過神策分析的 LogAgent 工具 將 log 檔傳輸到神策分析中。LogAgent 工具 確保 log 傳輸的時效性和完整性。
2. 初始化神策分析 SDK
在程式中使用
// 初始化神策分析物件
//
// @param consumer<in> log數據的“消費”方式
// @param sa<out> 初始化的神策分析執行個體
//
// @return SA_OK 初始化成功,否則初始化失敗
int sa_init(struct SAConsumer* consumer, struct SensorsAnalytics** sa);
初始化神策分析執行個體,透過它實作 SDK 各項功能。其中第一個參數 consumer 物件負責“消費”用戶行為 log,在程式中使用
// 初始化 Logging Consumer
//
// @param file_name<in> log 檔案名,例如: /data/logs/http.log
// @param consumer<out> SALoggingConsumer 執行個體
//
// @return SA_OK 初始化成功,否則初始化失敗
int sa_init_logging_consumer(const char* file_name, SALoggingConsumer** consumer);
初始化 SALoggingConsumer 執行個體,它負責將用戶行為 log 輸出到本地磁碟。
// 初始化 SALogingConsumer 執行個體
SALoggingConsumer* consumer = NULL;
if (SA_OK != sa_init_logging_consumer("./demo.out", &consumer)) {
fprintf(stderr, "Failed to initialize the consumer.");
return 1;
}
SensorsAnalytics *sa = NULL;
if (SA_OK != sa_init(consumer, &sa)) {
fprintf(stderr, "Failed to initialize the SDK.");
return 1;
}
// ... 使用神策分析進行各種操作
// 將本地快取的數據同步到檔案或 Sensors Analtycis 中
sa_flush(sa);
// 釋放 Sensors Analtycis 執行個體
sa_free(sa);
3. 追蹤事件
首次接入神策分析時,建議先追蹤 3~5 個關鍵的事件,只需要幾行程式碼,便能體驗神策分析的分析功能。例如:
- 圖片社交產品,可以追蹤用戶瀏覽圖片和評論事件
- 電商產品,可以追蹤用戶註冊、瀏覽商品和下訂單等事件
用戶透過
// 跟蹤一個用戶的行為
//
// @param distinct_id<in> 用戶ID
// @param event<in> 事件名稱
// @param properties<in> 事件屬性,SAProperties 物件,NULL表示無事件屬性
// @param sa<in/out> SensorsAnalytics 執行個體
//
// @return SA_OK 追蹤成功,否則追蹤失敗
#define sa_track(distinct_id, event, properties, sa)
介面記錄事件。開發者必須傳入用戶 ID(distinct_id)和事件名(event)兩個參數,標記用戶和事件名稱,同時,開發者可以在第三個參數傳入一個 SAProperties 物件,為事件增加自定義事件屬性,傳入 NULL 表示無自定義事件屬性,在自定義屬性中需要包含 $is_login_id 屬性來說明 distinct_id 是否為登入 ID。以電商產品為例,可以這樣追蹤一次購物行為:
// 記錄用戶提交訂單事件
// 初始化事件屬性
properties = sa_init_properties();
if (NULL == properties) {
fprintf(stderr, "Failed to initialize the properties.");
return 1;
}
// 增加作業系統屬性,透過請求中的UA,可以解析出用戶使用裝置的作業系統是 iOS
assert(SA_OK == sa_add_string("$os", "iOS", strlen("iOS"), properties));
// 增加作業系統版本屬性
assert(SA_OK == sa_add_string("$os_version", "10.0.0", strlen("10.0.0"), properties));
// 增加 IP 網址屬性,$ip 是預設屬性,神策分析會自動根據這個解析省份、城市
assert(SA_OK == sa_add_string("$ip", "123.123.123.123", strlen("123.123.123.123"), properties));
// 增加商品名稱屬性
assert(SA_OK == sa_add_string("product_name", "XX手机", 8, properties));
// 增加商品價格屬性
assert(SA_OK == sa_add_number("product_price", 5888, properties));
// $is_login_id 屬性判斷 distinct_id 是否為登入 ID,如果是則設定為 SA_TRUE,否則為 SA_FALSE,預設為 SA_FALSE
assert(SA_OK == sa_add_bool("$is_login_id", SA_TRUE, properties);
// 記錄購買商品事件
assert(SA_OK == sa_track(cookie_id, "SubmitOrder", properties, sa));
// 釋放事件屬性執行個體
sa_free_properties(properties);
3.1 事件屬性
如前文中的範例,開發者追蹤的事件可以自定義事件的屬性,例如購買商品事件中,將商品 ID、商品分類等資訊作為事件屬性。在後續的分析工作中,事件屬性可以作為統計過濾條件使用,也可以作為維度進行多維分析。對於事件屬性,神策分析有一些限制:
- 事件屬性是一个 SAProperties 對象,SDK 提供介面由開發者進行初始化和釋放;
- SAProperties 中每個元素描述一個事件屬性,屬性名稱必需是字串型別,以大小寫字母開頭,由字母和數字組成,長度不超過100個字元;
- SAProperties 中元素的值為事件屬性值,支援 String、Number、Bool、List 和 Date,對於神策分析中事件屬性的更多限制,請參考 數據格式。
開發者可以透過以下介面,向 SAProperties 物件加入屬性值,如加入 Bool 型別的屬性:
// 向事件屬性或用戶屬性增加 Bool 型別的屬性
//
// @param key<in> 屬性名稱
// @param bool_<in> SABool 物件,屬性值
// @param properties<out> SAProperties 物件
//
// @return SA_OK 增加成功,否則失敗
int sa_add_bool(const char* key, SABool bool_, SAProperties* properties);
其中屬性名稱必須為大小寫字母開頭、長度不超過100的由字母和數字組成的字串。加入 Number 型別的屬性:
// 向事件屬性或用戶屬性增加 Number 型別的屬性
//
// @param key<in> 屬性名稱
// @param number_<in> 屬性值
// @param properties<out> SAProperties 對象
//
// @return SA_OK 增加成功,否則失败
int sa_add_number(const char* key, double number_, SAProperties* properties);
加入 Date 型別的屬性,其中第一個參數為單位為秒的時間戳,如系統函數 time(NULL) 的回傳值,第二個參數為毫秒部分:
// 向事件属性或用戶屬性增加 Date 型別的屬性
//
// @param key<in> 屬性名稱
// @param seconds<in> 時間戳,單位為秒
// @param microseconds<in> 時間戳中毫秒部分
// @param properties<out> SAProperties 物件
//
// @return SA_OK 增加成功,否則失敗
int sa_add_date(const char* key, time_t seconds, int microseconds, SAProperties* properties);
加入String 型別的屬性,字串必須為 UTF-8 編碼,字串長度為實際的 UTF-8 長度,如一個中文字佔 3 個位元組:
// 向事件屬性或用戶屬性增加 String 型別的屬性
//
// @param key<in> 屬性名稱
// @param string_<in> 字串的 Handle
// @param length<in> 字串長度
// @param properties<out> SAProperties 物件
//
// @return SA_OK 增加成功,否則失敗
向 List 型別的屬性中增加 String 物件:
// 向事件屬性或用戶屬性的 List 型別的屬性中插入新物件,物件必須是 String 型別的
//
// @param key<in> 屬性名稱
// @param string_<in> 字串的 Handle
// @param length<in> 字串長度
// @param properties<out> SAProperties 物件
//
// @return SA_OK 增加成功,否則失敗
int sa_append_list(
const char* key,
const char* string_,
unsigned int length,
SAProperties* properties);
具體使用方式,可以參考上一節中的範例。
3.1.1 系统預設屬性
如前文中範例,事件屬性中以 '$' 開頭的屬性為系統預設屬性,在自定義事件屬性中填入對應 '$' 開頭的屬性值可以覆蓋這些預設屬性:
- $ip - 透過 sa_add_string() 向 SAProperties 物件加入該屬性,神策分析會自動根據 IP 網址解析用戶的省份、城市資訊;
- $time - 透過 sa_add_date() 向 SAProperties 物件加入該屬性,神策分析將事件時間設定為屬性值的時間。請注意,神策分析預設會過濾忽略 2 年前或 1 小時後的數據,如需修改這個限制請聯繫我們的技術支援。
關於其他更多預設屬性,請參考 數據格式 中 '預設屬性' 一節。
4. 用戶識別
在伺服器端應用中,神策分析也要求為每个事件設定用戶的 Distinct Id,這有助於神策分析提供更準確的留存率等數據。
對於註冊用戶,推薦使用系统中的用戶 ID 作為 Distinct Id,不建議使用用戶名、Email、手機號碼等可以被修改的資訊。
4.1 用戶註冊/登入
當同一個用戶的 Distinct Id 發生變化時(一般情況為匿名用戶註冊行為),可以透過
// 關聯匿名用戶和註冊用戶
//
// @param distinct_id<in> 用戶的註冊 ID
// @param origin_id<in> 被關聯的用戶匿名 ID
// @param properties<in> 事件屬性
// @param sa<in/out> SensorsAnalytics 物件
//
// @return SA_OK 追蹤關聯事件成功,否則失敗
#define sa_track_signup(distinct_id, origin_id, properties, sa)
將舊的 Distinct Id 和新的 Distinct Id 關聯,以確保用戶分析的準確性。例如:
// 初始化神策分析 SDK ...
// 用戶未註冊前的匿名 ID (匿名 ID 由前端傳過來)
const char* anonymous_id = '9771C579-71F0-4650-8EE8-8999FA717761';
# 未註冊前的匿名用戶瀏覽商品
assert(SA_OK == sa_track(anonymous_id, "ViewProduct", NULL, sa));
properties = sa_init_properties();
if (NULL == properties) {
fprintf(stderr, "Failed to initialize the properties.");
return 1;
}
// 向事件屬性增加用戶的註冊管道
assert(SA_OK == sa_add_string("register", "Baidu", 5, properties));
// 用戶註冊 ID
const char* login_id = "abcdefg";
// 關聯註冊用戶與匿名用戶
assert(SA_OK == sa_track_signup(login_id, anonymous_id, properties, sa));
// 釋放事件屬性
sa_free_properties(properties);
注意,對同一個用戶,sa_track_signup() 一般情況下建議只呼叫一次(通常在用戶 註冊 時呼叫),用戶 登入 前後的行為的關聯建議在業務端實作。在神策分析 1.13 版本之前,多次呼叫 sa_track_signup() 时,只有第一次關聯行為是有效的。神策分析 1.13 版本之後提供了多裝置 id 關聯的方法。更詳細的說明請參考 標識用戶,並在必要時聯繫我們的技術支援人員。
5. 設定用戶屬性
為了更準確地提供針對人群的分析服務,神策分析 SDK 可以設定用戶屬性,如年齡、性別等。用戶可以在留存分析、分佈分析等功能中,使用用戶屬性作為過濾條件或以用戶屬性作為維度進行多維分析。使用
// 設定用戶屬性,如果某個屬性已經在該用戶的屬性中存在,則覆蓋原有屬性
//
// @param distinct_id<in> 用戶 ID
// @param properties<in> 用戶屬性
// @param sa<in/out> SensorsAnalytics 物件
//
// @return SA_OK 設定成功,否則失敗
#define sa_profile_set(distinct_id, properties, sa)
設定用戶屬性,例如在電商應用中,用戶註冊時,填入了一些個人資訊,可以用Profile介面記錄下來:
properties = sa_init_properties();
if (NULL == properties) {
fprintf(stderr, "Failed to initialize the properties.");
return 1;
}
// 用戶的註冊管道
assert(SA_OK == sa_add_string("register", "Baidu", 5, properties));
// 用戶註冊日期
assert(SA_OK == sa_add_date("$signup_time", time(NULL), 0, properties));
// 用戶是否購買過商品
assert(SA_OK == sa_add_bool("is_vip", SA_FALSE, properties));
// $is_login_id 屬性判斷 distinct_id 是否為登入 ID,如果是則設定為 SA_TRUE,否則為 SA_FALSE,預設為 SA_FALSE
assert(SA_OK == sa_add_bool("$is_login_id", SA_TRUE, properties);
// 設定用戶屬性
assert(SA_OK == sa_profile_set(login_id, properties, sa));
sa_free_properties(properties);
對於不再需要的用戶的一個屬性,可以透過
// 刪除某用戶的一個屬性
//
// @param distinct_id<in> 用戶 ID
// @param key<in> 用戶屬性名稱
// @param sa<in/out> SensorsAnalytics 物件
//
// @return SA_OK 設定成功,否則失敗
#define sa_profile_unset(distinct_id, key, sa)
介面將屬性刪除。也可以透過
// 刪除某用戶所有屬性
//
// @param distinct_id<in> 用戶 ID
// @param sa<in/out> SensorsAnalytics 物件
//
// @return SA_OK 設定成功,否則失敗
#define sa_profile_delete(distinct_id, sa)
介面將某個用戶的所有屬性刪除。
用戶屬性中,屬性名稱與屬性值的約束條件與事件屬性相同,詳細說明請參考 數據格式。
5.1 記錄初次設定的属性
對於只在首次設定時有效的屬性,我們可以使用
// 設定用戶屬性,如果某個屬性已經在該用戶的屬性中存在,則忽略該操作
//
// @param distinct_id<in> 用戶 ID
// @param properties<in> 用戶屬性
// @param sa<in/out> SensorsAnalytics 物件
//
// @return SA_OK 設置成功,否則失败
#define sa_profile_set_once(distinct_id, properties, sa)
介面記錄這些屬性。與 sa_profile_set() 介面不同的是,如果被設定的用戶屬性已存在,則這條記錄會被忽略而不會覆蓋已有數據>,如果屬性不存在則會自動建立。因此,sa_profile_set_once() 比較適用於為用戶設定首次啟用時間、首次註冊時間等屬性。例如:
// 記錄用戶首次登入時間
properties = sa_init_properties();
if (NULL == properties) {
fprintf(stderr, "Failed to initialize the properties.");
return 1;
}
// 用戶首次使用時間
assert(SA_OK == sa_add_date("first_time", time(NULL), 0, properties));
// $is_login_id 屬性判斷 distinct_id 是否為登入 ID,如果是則設定為 SA_TRUE,否則為 SA_FALSE,預設為 SA_FALSE
assert(SA_OK == sa_add_bool("$is_login_id", SA_TRUE, properties);
// 記錄用戶屬性
assert(SA_OK == sa_profile_set_once(cookie_id, properties, sa));
sa_free_properties(properties);
5.2 數值型別的屬性
對於數值型的用戶屬性,可以使用
// 增加或減少用戶屬性中的 Number 型別屬性的值
//
// @param distinct_id<in> 用戶 ID
// @param properties<in> 用戶屬性,必須為 Number 型別的屬性
// @param sa<in/out> SensorsAnalytics 物件
//
// @return SA_OK 設定成功,否則失敗
#define sa_profile_increment(distinct_id, properties, sa)
對屬性值進行累加。常用於記錄用戶付費次數、付費額度、積分等屬性。例如:
// 在用戶屬性中記錄用戶支付金額
properties = sa_init_properties();
if (NULL == properties) {
fprintf(stderr, "Failed to initialize the properties.");
return 1;
}
// 累加用戶支付金額
assert(SA_OK == sa_add_number("pay", 5888, properties));
// 用戶獲得頭銜
assert(SA_OK == sa_append_list("title", "VIP", 3, properties));
// 記錄搜尋商品事件
assert(SA_OK == sa_profile_increment(login_id, properties, sa));
sa_free_properties(properties);
5.3 列表型別的屬性
對於用戶喜愛的電影、用戶評價過的餐廳等屬性,可以透過
// 向用戶屬性中的 List 屬性增加新元素
//
// @param distinct_id<in> 用戶 ID
// @param properties<in> 用戶屬性,必須為 List 型別的屬性
// @param sa<in/out> SensorsAnalytics 物件
//
// @return SA_OK 設定成功,否則失敗
#define sa_profile_append(distinct_id, properties, sa)
介面記錄列表型屬性。需要注意的是,列表型屬性中的元素必須為 String 類型,且元素的值會自動去重。關於列表型別限制請見 數據格式 7.3 屬性長度限制。
介面範例請參考前一節中的程式碼。