反饋是任何成功的產品開發流程的基石。 對於 WordPress 外掛開發人員來說,了解使用者停用外掛程式的原因可以提供寶貴的見解。

當我使用 Cloudflare 為 WordPress 開發另一個很棒的插件時,如果用戶停用我的插件,我想要一個回饋系統。 我開始在網上搜索,找到的解決方案對我來說不可行。

許多 WordPress 外掛程式創建者依靠內建的停用調查或第三方服務來收集回饋。 然而,這些方法有其限制和問題:

  • 成本:運行伺服器和管理回饋收集基礎架構可能會很昂貴。 因此,第三方提供者收取相當多的費用。
  • 延遲:緩慢的回饋機制可能會阻止使用者參與。 當使用者停用外掛程式時,他預計 10 秒內不會載入頁面。
  • 整合麻煩:許多回饋系統需要陡峭的學習曲線或複雜的整合過程,例如 SDK 等。
  • 隱私問題:大多數第三方服務提供者都會收集電子郵件地址等敏感資料。 將用戶敏感資料儲存在可能會也可能不會出售這些資料、遭到駭客攻擊或更糟的平台上; 就是不可行。

那麼,如何才能有效率、安全且經濟高效地收集回饋呢? 根據 Cloudflare WorkersKV 和 [D1](https://developers.cloudflare.com/d1/ )。

我決定基於令人驚嘆的 Cloudflare Workers 平台創建自己的 REST API,有效地將使用 Pages 部署的會員區域與 API 互連。 您可以在 此處 詳細了解我如何建立會員區域。

這意味著我可以將 API 使用限制為尊貴的會員,同時提供儲存資料的隱私和安全性。 該 API 在全球範圍內運行速度極快,停機時間為零,同時保持低成本和增強的安全性。 人們還想要什麼? 😃

這只是開始,因為我已經為未來的服務準備了幾個端點,包括免費的和付費的給客戶、開發人員和合作夥伴。

入門

我的 API 入門非常簡單。 註冊我的會員專區 。 註冊後,只需造訪您的個人資料 。 如果您已經有一個帳戶,則會動態產生一組 API 令牌。

您將在此頁面上找到:帳戶 ID公共令牌私人令牌

  • 帳戶ID用於識別您的帳戶並儲存對應資訊。
  • 公共代幣僅限於某些操作,請參閱範圍。
  • 私人代幣不像公共代幣那樣受到限制,您可以使用它來讀取、寫入、刪除您帳戶上的回饋。 再次,請查看範圍。

注意:我的 API 有嚴格的速率限制以防止濫用。 如果你玩得太多,你可能會受到至少一小時或更長的時間限制。

使用 WordPress 回饋 API 端點是免費的,這是完全免費的,所以請不要嘗試濫用它,否則我將不得不禁止您的帳戶。

將 API 與您的外掛程式集成

整合非常簡單,您只需按照以下步驟操作:

  1. 連接到 admin_footer 並注入您的回饋模式/表單。
  2. 使用「admin_enqueue_scripts」載入 CSS 和 JS; 確保您只在插件頁面上加載它們。 提示:建立您自己的自訂樣式,否則您將破壞外掛程式頁面樣式,甚至與其他外掛程式回饋模式發生衝突。
  3. 建立一個管理AJAX函數來處理回饋; 例如wp_ajax_your_plugin_deactivation_feedback。 注意:始終使用隨機數字來保護您的 AJAX 功能。

在收集回饋時,您需要收集一些資訊並將其相應地發送到API。 由於我非常關心隱私,API 不會儲存電子郵件地址或任何其他被視為機密的內容。

此外,為了盡可能遵守 GDPR,我提供了 D1 提供的所有五個位置來儲存收集的資料:

  • 北美西部
  • 北美東部
  • 西歐
  • 東歐洲
  • 亞太地區

考慮到這一點,我還提供了一個 GEO 輔助函數,它會傳回您的託管區域。 這意味著您可以自動將資料儲存在託管 WordPress 的封閉區域中。

取得區域的範例函數:

 1private function get_region($account, $token)
 2{
 3	$api_url = "https://api.mecanik.dev/v1/developer/$account/geo-info";
 4
 5	$response = wp_remote_post($api_url, [
 6		'headers' => [
 7			'Authorization' => 'Bearer '.$token,
 8			'Content-Type' => 'application/json; charset=utf-8',
 9		],
10		'method' => 'GET',
11	]);
12
13	$response_body = wp_remote_retrieve_body($response);
14	$response_data = json_decode($response_body, true);
15	
16	return $response_data;
17}

This will return a JSON response like:

 1{
 2    "longitude": "8.68370",
 3    "latitude": "50.11690",
 4    "continent": "EU",
 5    "asn": 14061,
 6    "asOrganization": "Digital Ocean",
 7    "country": "DE",
 8    "isEUCountry": "1",
 9    "city": "Frankfurt am Main",
10    "region": "Hesse",
11    "timezone": "Europe/Berlin",
12    "postalCode": "60341",
13    "recommended-storage-region": "weur"
14}

如您在此範例中看到的,伺服器駐留在「Hesse」區域,因此 API 建議將資料儲存在「weur」區域。 對此持保留態度; API 不能保證它總是回傳正確的「建議」。

現在,您可以繼續建立回饋物件並向 API 發送以下內容:reasoncommentswp_plugin_namewp_plugin_versionwp_site_urlwp_versionwp_localewp_pultisite php_versiondb_typedb_versionserver_typeserver_versiondate_created

發送回饋的範例函數:

 1public function wp_ajax_your_plugin_deactivation_feedback()
 2{
 3	if (!wp_verify_nonce($_POST['nonce'], 'wp_ajax_your_plugin_deactivation_feedback_nonce')) {
 4		wp_send_json_error(esc_html__('Request is invalid. Please refresh the page and try again.', 'your-plugin-name'), 400, 0);
 5		exit();
 6	}
 7	
 8	$account = "....";
 9	$token = "....";
10	$api_url = "https://api.mecanik.dev/v1/developer/$account/wp-feedback";
11
12	$region = $this->get_region($account, $token);
13
14	$response = wp_remote_post($api_url, [
15		'headers' => [
16			'Authorization' => 'Bearer '.$token,
17			'Content-Type' => 'application/json; charset=utf-8',
18		],
19		'body' => json_encode([
20			'reason'             => sanitize_text_field($_POST['reason']),
21			'comments'           => sanitize_textarea_field($_POST['comments']),
22			'wp_plugin_name'     => $this->plugin_name,
23			'wp_plugin_version'  => $this->version,
24			'wp_site_url'        => get_bloginfo('url'),
25			'wp_version'         => $this->get_wp_version(),
26			'wp_locale'          => get_locale(),
27			'wp_multisite'       => is_multisite(),
28			'php_version'        => $this->get_php_version(),
29			'db_type'            => $this->get_db_type(),
30			'db_version'         => $this->get_db_version(),
31			'server_type'        => $this->get_server_type(),
32			'server_version'     => $this->get_server_version(),
33			'date_created'       => current_time('mysql'),
34			'region'             => $region['recommended-storage-region'],
35		]),
36		'method' => 'PUT',
37		'data_format' => 'body'
38	]);
39
40	$response_body = wp_remote_retrieve_body($response);
41	$response_data = json_decode($response_body);
42
43	if ($response_data && isset($response_data->success) && $response_data->success === false) {
44		$error_message = isset($response_data->errors[0]->message) ? esc_html($response_data->errors[0]->message) : 'Unknown error';
45		wp_send_json_error($error_message, 400);
46		exit();
47	}
48	else if ($response_data && isset($response_data->success) && $response_data->success === true && isset($response_data->error)) {
49		wp_send_json_error($response_data->error, 400);
50		exit();
51	}
52	
53	wp_send_json_success($response_data, 200, 0);
54}

將會傳回成功儲存的回饋回應,如下所示:「回饋已儲存在 <region_name> 區域。」

在上面的範例函數中,您可以看到我們收集了 php_versiondb_typedb_version 等。為了您的方便,我將提供一些範例函數:

 1private function get_wp_version() {
 2	global $wp_version;
 3	return $wp_version;
 4}
 5
 6private function get_php_version() {
 7	return PHP_VERSION;
 8}
 9
10private function get_db_type() {
11	global $wpdb;
12
13	$query = "SELECT TABLE_SCHEMA FROM information_schema.TABLES WHERE TABLE_NAME = 'wp_options'";
14	$result = $wpdb->get_row($query);
15
16	if ($result && isset($result->TABLE_SCHEMA)) {
17		$table_schema = $result->TABLE_SCHEMA;
18
19		if (strpos($table_schema, 'mysql') !== false) {
20			return 'MySQL';
21		} elseif (strpos($table_schema, 'pgsql') !== false) {
22			return 'PostgreSQL';
23		} elseif (strpos($table_schema, 'sqlite') !== false) {
24			return 'SQLite';
25		}
26	}
27
28	return 'Unknown';
29}
30
31private function get_db_version() {
32	global $wpdb;
33	return $wpdb->db_version();
34}
35
36private function get_server_type() {
37	if (isset($_SERVER['SERVER_SOFTWARE'])) {
38		return explode(' ', $_SERVER['SERVER_SOFTWARE'])[0];
39	}
40	return 'Unknown';
41}
42
43private function get_server_version() {
44	$uname = php_uname('s');
45
46	$serverTypes = [
47		'Apache' => 'Apache',
48		'Nginx' => 'Nginx',
49		'LiteSpeed' => 'LiteSpeed'
50	];
51
52	if (isset($serverTypes[$uname])) {
53		return $serverTypes[$uname];
54	}
55
56	return '0.0.0';
57}

現在您應該擁有收集 WordPress 外掛程式停用回饋所需的一切。 根據需要進行修改以滿足您的需求。

開始收集停用回饋

如果您已按照上述步驟操作,當使用者嘗試停用您的外掛程式時,應該會出現回饋模式:

WordPress 外掛程式停用回饋

使用者可以輸入停用您的插件的原因。 您可以隨時從 API 檢索所有收集的回饋。

API 文檔

基本端點:

https://api.mecanik.dev/v1/developer

WordPress 回饋端點:

https://api.mecanik.dev/v1/developer/{account_id}/wp-feedback

取得反饋

  • 方法: GET
  • 網址: https://api.mecanik.dev/v1/developer/{account_id}/wp-feedback?region=[region]
  • 網址參數:
    • region (必填): 反饋所存儲的地區代碼。可以是 `wnam`, `enam`, `weur`, `eeur`, 或 `apac`。
  • 範疇: read:wp_feedback
  • 標頭:
    • Authorization: Bearer token 用於訪問。
  • 回應:
    • 200 OK 若成功返回反饋數據。
    • 400 Bad Request 若地區無效。
    • 403 Forbidden 若令牌未被授權。
    • 404 Not Found 若令牌不存在。
    • 406 Not Acceptable 若提供了無效的地區。

儲存反饋

  • 方法: PUT

  • 網址: https://api.mecanik.dev/v1/developer/{account_id}/wp-feedback

  • 範疇: write:wp_feedback
  • 標頭:

    • Authorization: Bearer token 用於訪問。
    • Content-Type: application/json
  • 內容:

    • JSON 物件包含:
      • reason (必填): 使用者停用的原因。允許的格式: `string`。
      • comments (必填): 使用者停用的評論。允許的格式: `string`。
      • wp_plugin_name (必填): 目前的WordPress插件名稱。允許的格式: `string`。
      • wp_plugin_version (必填): 目前的WordPress插件版本。允許的格式: `0.0.0.0`。
      • wp_site_url (必填): 目前的WordPress網址。允許的格式: `string`。
      • wp_version (必填): 目前的WordPress版本。允許的格式: `0.0.0.0`。
      • wp_locale (必填): 目前的WordPress地區設定。允許的格式: `string`。
      • wp_multisite (必填): 若目前的WordPress安裝為多站點。允許的格式: `boolean`。
      • php_version (必填): 目前的PHP版本。允許的格式: `0.0.0.0`。
      • db_type (必填): 目前的資料庫伺服器類型。允許的格式: `string`。
      • db_version (必填): 目前的資料庫伺服器版本。允許的格式: `0.0.0.0`。
      • server_type (必填): 目前的網頁伺服器類型。允許的格式: `string`。
      • server_version (必填): 目前的網頁伺服器版本。允許的格式: `0.0.0.0`。
      • date_created (必填): 創建反饋的日期/時間。允許的格式: `YYYY-MM-DD HH:MM:SS`。
      • region (必填):儲存回饋的區域代碼。 它可以是`wnam`、`enam`、`weur`、`eeur`, 或 `apac`。
  • 回應:

    • 200 OK 若成功儲存反饋。
    • 400 Bad Request 若提供的參數中有任何一項是無效的。
    • 403 Forbidden 若令牌未被授權或被撤銷/封鎖。
    • 404 Not Found 若令牌不存在。
    • 406 Not Acceptable 若提供了無效的地區。
    • 500 Internal Server Error 若儲存反饋時出現錯誤。

刪除反饋

  • 方法: DELETE
  • 網址: https://api.mecanik.dev/v1/developer/{account_id}/wp-feedback
  • 範疇: delete:wp_feedback
  • 標頭:
    • Authorization: Bearer token 用於訪問。
  • 回應:
    • 200 OK 若成功刪除反饋。
    • 403 Forbidden 若令牌未被授權。
    • 404 Not Found 若指定的反饋 ID 不存在。
    • 500 Internal Server Error 若刪除反饋時出現錯誤。

結論

擁有這樣的回饋系統將對你的插件開發產生巨大的影響。 我希望這篇文章對您有所幫助,並且您可以使用我的 API 來改進您的 WordPress 外掛。

我將來可能會引入啟動回饋,但我對此非常懷疑,因為用戶無法「選擇加入」或「選擇退出」它。 因此,目前我們只會收到停用回饋。

如果您有任何回饋或建議,請隨時使用下面的評論系統。