文件
外送 Webhook:payload 與簽章
將 AutoPSEO 的警示與報表以簽章 JSON 的形式傳送到任何 HTTPS 端點:涵蓋請求標頭、內文欄位、事件類型,以及簽章驗證方式。
外送 Webhook 會將 AutoPSEO 的警示、排程報表、測試訊息與報表摘要,傳送到由你自行架設的端點。每則訊息都是一個以 HMAC-SHA256 簽章的 JSON POST 請求。你可以用它串接 Zapier、Make、n8n、事件通報工具或自己的程式碼,不需要 Slack 或 Teams 帳號。想找的是把文章送到你網站的 webhook 嗎?那是內容引擎的功能,請參閱內容發布。
新增 Webhook
- 在「Outbound webhooks」區塊中,按一下 New webhook。
- 為它設定 Name,並貼上端點的 URL。URL 必須是公開的 HTTPS:純
http、localhost、以.local或.internal結尾的名稱、不含點號的主機名稱,以及私有或 link-local 的 IP 位址都會被拒絕。 - 儲存後,複製畫面上顯示的簽署密鑰(signing secret)。此密鑰只會顯示這一次。
- 按一下 Send test 傳送
test事件,接著將排程報表或警示綁定到這個 webhook。
Webhook 請求的內容
每則訊息都是一個 POST 請求,並帶有以下標頭:
| 標頭 | 值 |
|---|---|
Content-Type | application/json |
User-Agent | AutoPSEO-Webhook/1.0 |
X-AutoPSEO-Event | 事件類型,例如 traffic_drop |
X-AutoPSEO-Signature | sha256= 後接 64 個小寫十六進位字元 |
以下是某個網域資源在 2026 年 10 月 12 日 06:00 UTC 執行時產生的流量下降警示,為方便閱讀而排版(實際傳送時是精簡的 JSON,且 id 與 site_id 的值皆為虛構):
{
"id": "9b2e61f04c3a4d7e8f15a0b6c2d39e47",
"event_type": "traffic_drop",
"severity": "high",
"site_id": "4f0c1e9a2b7d4c58",
"site_url": "sc-domain:example.com",
"occurred_at": "2026-10-12T06:00:04.183Z",
"title": "Traffic drop: example.com",
"text": "Clicks 1,500 vs 2,000 in the previous window (-25.0%).",
"url": "https://app.autopseo.com/property/sc-domain%3Aexample.com",
"payload": {
"fields": [
{ "label": "Metric", "value": "clicks" },
{ "label": "Current", "value": "1,500" },
{ "label": "Baseline", "value": "2,000" },
{ "label": "Window", "value": "7 days (2026-10-05 → 2026-10-11 vs 2026-09-28 → 2026-10-04)" },
{ "label": "Change", "value": "-25.0%" }
],
"table": null,
"detector": "traffic_drop",
"window": 7,
"range": { "start": "2026-10-05", "end": "2026-10-11", "compStart": "2026-09-28", "compEnd": "2026-10-04" },
"result": {
"fired": true,
"metric": "clicks",
"value": 1500,
"baseline": 2000,
"change": -0.25,
"severity": "high",
"summary": "Clicks 1,500 vs 2,000 in the previous window (-25.0%)."
}
},
"source": "autopseo"
}
以下頂層欄位在所有事件中都相同:
| 欄位 | 內容 |
|---|---|
id | 隨機產生的 32 字元十六進位字串,每個請求都不同 |
event_type | 發生的事件(見下一節) |
severity | 警示為 critical、high、medium 或 low;報表、摘要與測試為 info |
site_id | AutoPSEO 為該資源指定的 ID;測試與示範資源則為 null |
site_url | Search Console 資源,例如 sc-domain:example.com 或 https://www.example.com/;測試時為 null |
occurred_at | 訊息建立的時間,以 UTC 的 ISO 8601 時間戳記表示 |
title、text | Slack 與 Teams 所顯示的標題與摘要句 |
url | AutoPSEO 中對應的報表連結;測試時為 null |
payload.fields | 具標籤的數值,在 Slack 中顯示為欄位,在 Teams 中顯示為 facts |
payload.table | 報表與摘要的 columns 和 rows,其他情況為 null |
source | 固定為 autopseo |
比率一律以小數表示:change 為 -0.25 代表下降 25%,ctr 為 0.034 代表 3.4%。
事件類型
event_type | 觸發時機 | payload 中額外的鍵 |
|---|---|---|
traffic_drop、traffic_spike、position_drop、ctr_drop、new_lost_rankings、anomaly、index_flip、rank_drop、audit_regression | 警示規則觸發時,無論是依排程或透過 Test rule | detector、window、range(日期範圍;index_flip、rank_drop 與 audit_regression 則為 null)、result |
scheduled_report | 排程報表送出時,無論是依排程或透過 Send now | reportType(summary、queries、pages 或 rankings)、range(日期加上 label)、totals、previous |
report_summary | 有人在報表頁面使用 Send to Slack | 無:數據都在 fields 與 table 中 |
test | 有人在 webhook 上按下 Send test | sample,固定為 true |
result 會重述偵測器所量測的結果:fired、metric、value、baseline、change(無可比較對象時為 null)、severity 與 summary;anomaly 另外還有 z,也就是修正後的 z 分數。totals 與 previous 則包含報表兩個時間區間的 clicks、impressions、ctr 與 position。各偵測器的量測內容,請參閱警示。
如何驗證簽章
簽章是以該 webhook 的簽署密鑰為金鑰,對 AutoPSEO 實際送出的原始位元組計算 HMAC-SHA256,並以 sha256= 加上小寫十六進位表示。驗證步驟如下:
- 在進行任何 JSON 解析之前,先讀取原始請求內文。解析後再序列化可能會改變位元組內容。
- 對這些位元組計算 HMAC-SHA256,密鑰以文字形式使用:即畫面上顯示的 64 字元字串原樣使用,不要以十六進位解碼。
- 在結果前加上
sha256=,再以恆定時間(constant-time)比較函式與X-AutoPSEO-Signature標頭比對。 - 若兩者不同,就拒絕該請求。否則請立即回應 2xx 狀態碼,耗時的處理留待之後再做。
以下是不需任何相依套件的 Node.js 接收端範例:
import { createServer } from 'node:http';
import { createHmac, timingSafeEqual } from 'node:crypto';
const secret = process.env.AUTOPSEO_WEBHOOK_SECRET;
createServer((req, res) => {
const chunks = [];
req.on('data', (chunk) => chunks.push(chunk));
req.on('end', () => {
const raw = Buffer.concat(chunks);
const expected = Buffer.from('sha256=' + createHmac('sha256', secret).update(raw).digest('hex'));
const received = Buffer.from(String(req.headers['x-autopseo-signature'] || ''));
if (received.length !== expected.length || !timingSafeEqual(received, expected)) {
res.writeHead(401).end();
return;
}
res.writeHead(204).end();
const event = JSON.parse(raw.toString('utf8'));
console.log(event.event_type, event.severity, event.site_url);
});
}).listen(8080);
必須先檢查長度,因為當兩個緩衝區長度不同時,Node 的 timingSafeEqual 會拋出例外。
傳送規則
- 每則訊息只會嘗試傳送一次,逾時時間為 10 秒。任何非 2xx 的回應都視為失敗,並連同狀態碼與回應內文開頭的部分內容,一併記錄在 Delivery history 中。
- 不會跟隨重新導向。若收到 3xx 回應,會判定為失敗,並提示你改用最終的 URL。
- 不會依計時器自動重試。失敗的警示不會被標記為已傳送,因此下一次檢查時會重新評估,若仍符合觸發條件就會再次發送:多數偵測器是隔天早上,索引狀態翻轉(index flip)則是下一個小時。失敗的排程報表在同一週期內不會重送,請在修復端點後使用 Send now。
id是依每個請求產生的,因此它代表的是一次傳送,而不是一個事件。若要對警示去重,請組合event_type、site_url與occurred_at的日期:除非有人執行 Test rule,否則一條規則對每個資源每個 UTC 日最多只會發送一次。
簽署密鑰
AutoPSEO 只會在你儲存 webhook 時顯示一次簽署密鑰,之後列表中不會再顯示。請立即將它與你的接收端設定一同存放,並與其所保護的端點放在一起。
URL 本身是加密儲存的,列表中只會顯示其主機名稱與最後幾個字元。刪除 webhook 時,也會一併刪除所有發送到該 webhook 的規則。如果你想在 Teams 頻道中看到易讀的卡片,而不是 JSON,請使用 Microsoft Teams。