文档
出站 Webhook:载荷与签名
通过任意 HTTPS 端点接收带签名的 JSON 格式 AutoPSEO 告警和报告:包括请求头、请求体字段、事件类型以及签名验证方法。
出站 Webhook 会把 AutoPSEO 的告警、定时报告、测试消息和报告摘要发送到你自己运行的端点,每条消息对应一个使用 HMAC-SHA256 签名的 JSON POST 请求。你可以用它对接 Zapier、Make、n8n、故障管理工具或你自己的代码,无需 Slack 或 Teams 账号。想了解把文章投递到你网站的 Webhook?那属于内容引擎的功能,请参阅内容投递。
添加 Webhook
- 在出站 Webhook 区域,点击新建 Webhook。
- 为它设置名称,并粘贴端点的 URL。该 URL 必须是公网 HTTPS 地址:普通
http、localhost、以.local或.internal结尾的名称、不含点号的主机名,以及私有或链路本地 IP 地址都会被拒绝。 - 复制保存后显示的签名密钥。该密钥只会显示这一次。
- 点击发送测试以推送一条
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 中显示为事实项 |
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 | 告警规则触发时,按计划触发或通过测试规则触发 | detector、window、range(日期;index_flip、rank_drop 和 audit_regression 为 null)、result |
scheduled_report | 定时报告发出时,按计划发送或通过立即发送发送 | reportType(summary、queries、pages 或 rankings)、range(日期加 label)、totals、previous |
report_summary | 有人在报告页面使用发送到 Slack 时 | 无:数据位于 fields 和 table 中 |
test | 有人在该 Webhook 上点击发送测试时 | sample,始终为 true |
result 复述检测器的测量结果:fired、metric、value、baseline、change(无可比较对象时为 null)、severity 和 summary;anomaly 还会包含 z,即修正 z 分数。totals 和 previous 包含报告两个时间窗口的 clicks、impressions、ctr 和 position。各检测器的测量内容请参阅告警。
如何验证签名
签名是对 AutoPSEO 发送的原始字节计算的 HMAC-SHA256,以 Webhook 的签名密钥作为密钥,格式为 sha256= 加小写十六进制。验证步骤如下:
- 在进行任何 JSON 解析之前先读取原始请求体。解析后再序列化可能会改变字节内容。
- 对这些字节计算 HMAC-SHA256,密钥按文本使用:即所显示的 64 位字符串原样使用,不要按十六进制解码。
- 加上前缀
sha256=,并以恒定时间比较的方式将结果与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 的响应都视为失败,并连同状态码和你的响应体开头部分一起记录在投递历史中。
- 不会跟随重定向。3xx 响应会失败,并提示改用最终 URL。
- 不会按计时器重试。发送失败的告警不会被标记为已发送,因此下次检查时会重新评估,若仍然触发则再次推送:大多数检测器为次日早晨,索引状态翻转(index flip)为下一小时。发送失败的定时报告在同一周期内不会重发,请在修复端点后使用立即发送。
id是按请求生成的,因此它标识的是一次投递而不是一个事件。若要对告警去重,请组合使用event_type、site_url和occurred_at的日期:除非有人运行测试规则,否则一条规则对每个资源每个 UTC 日最多推送一次。
签名密钥
AutoPSEO 只在你保存 Webhook 时显示一次签名密钥,之后列表中不再显示。请立即将它与接收端的配置一起保存,并与它所保护的端点放在一起。
URL 本身以加密方式存储,列表中只显示其主机名和末尾几个字符。删除 Webhook 的同时也会删除所有向它推送的规则。如果想在 Teams 频道中看到可读的卡片而不是 JSON,请使用 Microsoft Teams。