1. PHP SDK 使用说明

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

1.1. 整合神策分析 SDK

在 PHP 腳本中整合 神策分析 SDK ,使用神策分析採集並分析用戶數據。 SDK 最低相容 PHP 5.X,部分功能依賴 curl 擴展。有兩種整合方式:

使用 composer 整合。

{
	"require": {
		"sensorsdata/sa-sdk-php": "v1.10.5"
	}
}
JS

直接從 GitHub 取得 SDK 的原始碼並整合到專案中。

1.2. 初始化神策分析 SDK

1.2.1. 取得設定資訊

首先從神策分析的主頁中,取得數據接收的 URL 和 Token(Cloud 版)。

如果使用神策分析 Cloud 服務,需取得的設定資訊為:

數據接收網址,建議使用不帶埠號的: http://{$service_name}.datasink.sensorsdata.cn/sa?project={$project_name}&token={$project_token}
數據接收網址,帶埠號的: http://{$service_name}.cloud.sensorsdata.cn:8106/sa?project={$project_name}&token={$project_token}


如果用戶使用單機版私有部署的神策分析,預設的設定資訊為:

數據接收網址: http://{$host_name}:8106/sa?project={$project_name}(注:神策分析 1.7 及之前的版本,單機版私有部署預設埠號為 8006)


如果用戶使用叢集版私有部署的神策分析,預設的設定資訊為:

數據接收網址: http://{$host_name}:8106/sa?project={$project_name}


其中 {$host_name}可以是叢集中任意一台機器。

如果私有部署的過程中修改了 Nginx 的預設設定,或透過 CDN 等連接神策分析,則請諮詢相關人員獲得設定資訊。

1.2.2. 在程式中初始化 SDK

在程式中初始化的程式碼段中建構神策分析 SDK 的執行個體:

注意:BatchConsumer 是同步發送數據,因此不要在任何線上的服務中使用此 Consumer,線上推薦使用 FileConsumer

<?php
	require_once("SensorsAnalytics.php");

	# 從神策分析設定頁面中取得的數據接收的 URL
	$SA_SERVER_URL = 'YOUR_SERVER_URL';

	# 初始化一個 Consumer,用於數據傳送
	# BatchConsumer 是同步傳送數據,因此不要在任何線上的服務中使用此 Consumer
	$consumer = new BatchConsumer($SA_SERVER_URL);
	# 使用 Consumer 來建構 SensorsAnalytics 物件
	$sa = new SensorsAnalytics($consumer);
	# 支援在建構SensorsAnalytics物件時指定project, 後續所有透過這個SensorsAnalytics物件傳送的數據都將發往這個project
	# $sa = new SensorsAnalytics($consumer, "project_name");

	# 記錄用戶登入事件
	$distinct_id = 'ABCDEF123456789';
	$sa->track($distinct_id, true, 'UserLogin');

	$sa->close();
?>
PHP


其中 YOUR_SERVER_URL 是前文中從神策分析取得的數據接收的 URL。用戶程式應該一直持有該執行個體,直到程式結束。程式退出前,需要使用 `close()` 方法表示關閉,否則可能遺失部分快取的數據。

至此,我們已經可以正常使用神策分析 SDK 了。需了解更多關於 SDK 的使用方法,可以跳到本文末尾的 PHP SDK #設定神策分析 SDK 一節。

1.3. 追蹤事件

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

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


用戶透過 track() 介面記錄事件,對於任何事件,必須包含用戶識別符distinct_id)、用戶標識是否為登入 ID (is_login_id)和事件名event_name)這三個參數。同時,用戶可以在 track() 的第四個參數傳入一個 object 物件,為事件增加自定義事件屬性。以電商產品為例,可以這樣追蹤一次購物行為:

<?php
	$distinct_id = 'ABCDEF123456789';

	$properties = array(
		# '$time' 屬性是系統預設屬性,傳入毫秒表示的 Timestamp,表示事件發生的時間,如果不填入該屬性,則預設使用系統當前時間
		'$time' => (int)(microtime(true) * 1000), # 對於windows用戶需要這樣定義 '$time' => substr((microtime(true) * 1000), 0, 13)
		# '$ip' 屬性是系統預設屬性,如果伺服器端中能取得用戶 IP 網址,並填入該屬性,神策分析會自動根據 IP 網址解析用戶的省份、程式資訊
		'$ip' => '123.123.123.123',
		# 商品 ID
		'ProductId' => '123456',
		# 商品類別
		'ProductCatalog' => 'Laptop Computer',
		# 是否加入收藏夾,Boolean 型別的屬性
		'IsAddedToFav' => true,
	);

	# 記錄用戶瀏覽商品事件
	$sa->track($distinct_id, true, 'ViewProduct', $properties);

	$properties = array(
	# 用戶 IP 網址
	'$ip' => '123.123.123.123',
	# 商品 ID 列表,list<str> 型別的屬性
	'ProductIdList' => array('123456', '234567', '345678'),
	# 訂單價格
	'OrderPaid' => 12.10,
	);

	# 記錄用戶訂單付款事件
	$sa->track($distinct_id, true, 'PaidOrder', $properties);
?>
PHP


1.3.1. 事件屬性

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

事件屬性是一個 array 物件
array 中每個元素描述一個屬性,Key 為屬性名稱,必需是 string 型別
array 中,每個元素的 Value 是屬性的值,支援 string、int、float、array 和 DateTime


對於神策分析中事件屬性的更多限制,請參考 數據格式

1.3.1.1. 系统預設屬性

如前文中範例,事件屬性中以 '$' 開頭的屬性為系統預設屬性,在自定義事件屬性中填入對應 '$' 開頭的屬性值可以覆蓋這些預設屬性:

$ip - 填入該屬性,神策分析會自動根據 IP 網址解析用戶的省份、程式資訊,該屬性值為 string 型別;
$time - 填入該屬性,神策分析將事件時間設定為屬性值的時間,該屬性值必須為 DateTime 型別。請注意,神策分析預設會過濾忽略 365 天前或 3 天後的數據,如需修改請聯繫我們。


關於其他更多預設屬性,請參考 數據格式 中 '預設屬性' 一節。

1.3.1.2. 事件公共屬性

特別地,如果某個事件的屬性,在所有事件中都會出現,可以透過 register_super_properties() 將該屬性設定為事件公共屬性。例如將伺服器的應用版本及機房網址設定為事件的公共屬性,設定方法如下:

<?php
	$properties = array(
		# 伺服器應用版本
		'ServerVersion' => '1.2',
		# 伺服器機房網址
		'Location' => 'BeiJing',
	);

	# 設定事件公共屬性
	$sa->register_super_properties($properties);
?>
PHP


成功設定事件公共屬性後,再透過 track() 追蹤事件時,事件公共屬性會被增加進每個事件中。

使用 clear_super_properties() 會刪除所有已設定的事件公共屬性。

當事件公共屬性和事件屬性的 Key 衝突時,事件屬性優先級最高,它會覆蓋事件公共屬性。

1.4. 用戶識別

在伺服器端應用中,神策分析也要求為每個事件設定用戶的 Distinct Id,這有助於神策分析提供更準確的留存率等數據。

對於註冊用戶,推薦使用系統中的用戶 ID 作為 Distinct Id,不建議使用用戶名、Email、手機號碼等可以被修改的資訊。

所有的 track 和 profile 系列方法都必須同時指定用戶 ID 及用戶 ID 是否為登入 ID 這兩個參數,以便明確告知神策分析用戶 ID 的類型。

1.4.1. 用戶註冊/登入

當同一個用戶的 Distinct Id 發生變化時(一般情況為匿名用戶註冊行為),可以透過 track_signup() 將舊的 Distinct Id 和新的 Distinct Id 關聯,以確保用戶分析的準確性。例如:

<?php
	$anonymous_id = '9771C579-71F0-4650-8EE8-8999FA717761';# 匿名 ID 由前端傳過來
	$register_id = '0012345678';
	# 用戶註冊/登入時,將用戶註冊 ID 與 匿名 ID 關聯
	$sa->track_signup($register_id, $anonymous_id);
?>
PHP


注意,對同一個用戶,track_signup() 一般情況下建議只呼叫一次(通常在用戶 註冊 時呼叫),用戶 登入 前後的行為的關聯建議在業務端實現。在神策分析 1.13 版本之前,多次呼叫 track_signup()時,只有第一次關聯行為是有效的。神策分析 1.13 版本之後提供了多裝置 id 關聯的方法。更詳細的說明請參考 如何準確的標識用戶,並在必要時聯繫我們的技術支援人員。

1.5. 設定用戶屬性

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

使用 profile_set() 設定用戶屬性:

<?php
	$distinct_id = 'ABCDEF123456789';

	$properties = array(
		# 用戶性別屬性(Sex)為男性
		'Sex' => 'Male',
		# 用戶等級屬性(Level)為 VIP
	'UserLevel' => 'Elite VIP',
);

	# 設定用戶屬性
	$sa->profile_set($distinct_id, true, $properties);
?>
PHP


對於不再需要的用戶屬性,可以透過 `profile_unset()` 介面將屬性刪除。

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

1.5.1. 記錄初次設定的屬性

對於只在首次設定時有效的屬性,我們可以使用 ProfileSetOnce() 記錄這些屬性。與 ProfileSet() 介面不同的是,如果被設定的用戶屬性已存在,則這條記錄會被忽略而不會覆蓋已有數據,如果屬性不存在則會自動建立。因此,profileSetOnce() 比較適用於為用戶設定首次啟用時間、首次註冊時間等屬性。例如:

<?php
	$distinct_id = 'ABCDEF123456789';

	# 設定用戶管道屬性(AdSource)為 "App Store"
	$sa->profile_set_once($distinct_id, true, array('AdSource' => 'App Store'));

	# 再次設定用戶管道屬性(AdSource),設定無效,屬性 "AdSource" 的值仍為 "App Store"
	$sa->profile_set_once($distinct_id, true, array('AdSource' => 'Search Engine'));
?>
PHP


1.5.2. 數值型別的屬性

對於數值型的用戶屬性,可以使用 ProfileIncrement() 對屬性值進行累加。常用於記錄用戶付費次數、付費額度、積分等屬性。例如:

<?php
	$distinct_id = 'ABCDEF123456789';

	# 設定用戶遊戲次數屬性(GamePlayed),將次數累加1次
	$sa->profile_increment($distinct_id, true, array('GamePlayed' => 1));
?>
PHP


1.5.3. 列表型別的屬性

對於用戶喜愛的電影、用戶評價過的餐廳等屬性,可以記錄列表型屬性。需要注意的是,列表型屬性中的元素必須為 String 型別,且元素的值會自動去重。關於列表型別限制請見 數據格式

<?php
	$distinct_id = 'ABCDEF123456789';

	$properties = array(
		# 電影列表
		'Movies' => array('Sicario', 'Love Letter'),
		# 遊戲列表
		'Games' => array('Call of Duty', 'Halo'),
	);

	# 傳入properties,設定用戶喜歡的電影屬性(movies)和喜歡的遊戲屬性(games)
	# 設定成功後,"Movies" 屬性值為 ["Sicario", "Love Letter"];"Games" 屬性值為 ["Call of Duty", "Halo"]
	$sa->profile_append($distinct_id, true, $properties);

	# 傳入屬性名稱和需要插入屬性的值,設定用戶喜歡的電影屬性(Movies)
	# 設定成功後 "Movies" 屬性值為 ["Sicario", "Love Letter", "Dead Poets Society"]
	$sa->profile_append($distinct_id, true, array('Movie' => array('Dead Poets Society')));

	# 傳入屬性名稱和需要插入屬性的值,設定用戶喜歡的電影屬性(Movies),
	# 但屬性值 "Love Letter" 與已列表中已有元素重複,操作無效,
	# "Movies" 屬性值仍然為 ["Sicario", "Love Letter", "Dead Poets Society"]
	$sa->profile_append($distinct_id, true, array('Movie' => array('Love Letter')));
?>
PHP


1.6. 物品元數據上報

在神策推薦專案中,客戶需要將物品元數據上報,以開展後續推薦業務的開發與維護。神策分析 SDK 提供了設定與刪除物品元數據的方法。

item_id(物品 ID ) item_type (物品所屬型別)共同組成了一個物品的唯一標識。所有的 item 系列方法都必須同時指定物品 ID 及物品所屬型別這兩個參數,來完成對物品的操作。

1.6.1. 設定物品

直接設定一個物品,如果已存在則覆蓋。除物品 ID 與物品所屬型別外,其他物品屬性需在 $properties 中定義。

物品屬性中,屬性名稱與屬性值的限制條件與事件屬性相同,詳細說明請參考 數據格式

<?php
	function item_set($item_type, $item_id, $properties = array())

	# 例如
	$item_type = 'fruit';
	$item_id = 'ABCDEF123456789';
	$sa->item_set($item_type, $item_id, array('apple' => 1));
?>
PHP


1.6.2. 刪除一個物品

如果物品不被推薦而需要下線,刪除該物品即可,如不存在則忽略。

除物品 ID 與 物品所屬型別外,不解析其他物品屬性。

<?php
	function item_delete($item_type, $item_id, $properties = array())

	#例如:
	$item_type = 'fruit';
	$item_id = 'ABCDEF123456789';
	$sa->item_delete($item_type, $item_id, null);
?>
PHP


1.7. 不同 Consumer 的使用方法

PHP SDK 主要由以下兩個元件構成:

SensorsAnalytics: 用於傳送數據的介面物件,建構函式需要傳入一個 Consumer 執行個體。
Consumer: Consumer 會進行實際的數據傳送


為了讓開發者更靈活的接入數據,神策分析 SDK 實作了以下 Consumer:

FileConsumer: 將待傳送的數據寫入指定的本地檔案,後續可以使用 LogAgent 或者 BatchImporter 來進行匯入。

<?php
	require_once("SensorsAnalytics.php");
	# 初始化一個 Consumer,用於數據傳送
	$consumer = new FileConsumer("sa.log." . date('Y-m-d'));
	# 使用 Consumer 來建構 SensorsAnalytics 物件
	$sa = new SensorsAnalytics($consumer);
?>
PHP


BatchConsumer: 通常用於匯入小規模歷史數據,或者離線 / 略過匯入數據的場景。由於是網路直接傳送數據,如果網路出現異常可能會導致數據重發或遺失,因此不要用在任何線上服務中 。使用 CURL 批量傳送數據的 Consumer,當且僅當數據達到指定的量時,才將數據進行傳送。

<?php
	require_once("SensorsAnalytics.php");

	# 從神策分析設定頁面中取得的數據接收的 URL
	$SA_SERVER_URL = 'YOUR_SERVER_URL';
	# 可選參數,當快取的數據量達到參數值時,批量傳送數據
	$SA_BULK_SIZE = 100;
	# 可選參數,傳送數據的超時時間,單位毫秒
	$SA_REQUEST_TIMEOUT = 100000;
	# 可選參數,傳送數據請求是否回傳詳情
	$RESPONSE_INFO = false;
	# 可選參數,傳送數據請求的回傳狀態及數據落地檔案網址,必須同時 $RESPONSE_INFO 為 ture 時,才會記錄
	$FILENAME = false;

	# 初始化一個 Consumer,用於數據傳送
	# BatchConsumer 是同步傳送數據,因此不要在任何線上的服務中使用此 Consumer
	$consumer = new BatchConsumer($SA_SERVER_URL, $SA_BULK_SIZE, $SA_REQUEST_TIMEOUT, $RESPONSE_INFO, $FILENAME);
	# 使用 Consumer 來建構 SensorsAnalytics 物件
	$sa = new SensorsAnalytics($consumer);

	# 程式結束前呼叫 close() ,通知 Consumer 傳送所有快取數據
	$sa->close();
?>
PHP
# 回傳數據請求詳情的回傳值格式
# 數據進入快取請求詳情回傳格式:
            $result = array(
                "ret_content" => "data into cache buffers",
                "ret_origin_data" => "",
                "ret_code" => 900
            );
# 範例
{"ret_content":"data into cache buffers","re​​t_data":"","re​​t_code":900}
 
# 數據傳送請求詳情回傳格式:
            $result = array(
                "ret_content" => $ret,
                "ret_origin_data" => $origin_data,
                "ret_code" => curl_getinfo($ch, CURLINFO_HTTP_CODE)
            );
# 範例
{"ret_content":"","re​​t_origin_data":["{"type":"profile_unset","properties":{"City":true,"$is_login_id":true},"time":1595659757260,"distinct_id ":"1234","lib":{"$lib":"php","$lib_version":"1.10.7","$lib_method":"code","$lib_detail":"#### \/Users\/kakusei\/phpdemo\/test.php##32"}}"],"ret_code":200}
PHP


bugConsumer: 用於校驗數據匯入是否正確,關於 除錯模式 的詳細資訊,請進入相關頁面查看。

請注意:Debug 模式是為方便開發者除錯而設定的模式,該模式會逐條校驗數據並在校驗失敗時拋出異常,效能遠低於正常模式。線上環境使用 Debug 模式會嚴重影響效能並存在崩潰風險,產品上線前請務必替換掉/關閉 Debug 模式。

<?php
	require_once("SensorsAnalytics.php");

	# 從神策分析設定頁面中取得的數據接收的 URL
	$SA_SERVER_URL = 'YOUR_SERVER_URL';
	# 可選參數,Debug 模式下,是否將數據匯入神策分析
	# True - 校驗數據,並將數據匯入到神策分析中
	# False - 校驗數據,但不進行數據匯入
	$SA_DEBUG_WRITE_DATA = True;
	# 可選參數,傳送數據的超時時間,單位毫秒
	$SA_REQUEST_TIMEOUT = 100000;

	# 初始化一個 Consumer,用於數據傳送
	$consumer = new DebugConsumer($SA_SERVER_URL, $SA_DEBUG_WRITE_DATA, $SA_REQUEST_TIMEOUT);
	# 使用 Consumer 來建構 SensorsAnalytics 物件
	$sa = new SensorsAnalytics($consumer);
?>
PHP