ドキュメント
アウトバウンド Webhook:ペイロードと署名
AutoPSEO のアラートとレポートを、署名付き JSON として任意の HTTPS エンドポイントで受信できます。リクエストヘッダー、本文のフィールド、イベントタイプ、署名の検証方法を説明します。
アウトバウンド Webhook は、AutoPSEO のアラート、定期レポート、テストメッセージ、レポートサマリーを、お客様が運用するエンドポイントに送信する機能です。メッセージ 1 件につき JSON の POST を 1 回送り、HMAC-SHA256 で署名します。Zapier、Make、n8n、インシデント管理ツール、自社のコードなどと連携できます。Slack や Teams のアカウントは必要ありません。記事をサイトに配信する Webhook をお探しの場合、それはコンテンツエンジンの機能です。コンテンツ配信をご覧ください。
Webhook を追加する
- Outbound webhooks セクションで New webhook をクリックします。
- Name を入力し、エンドポイントの URL を貼り付けます。URL は公開された HTTPS である必要があります。プレーンな
http、localhost、.localや.internalで終わる名前、ドットを含まないホスト、プライベートまたはリンクローカルの IP アドレスは使用できません。 - 保存後に表示される署名シークレットをコピーします。表示されるのは、このとき 1 回だけです。
- 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 文字の小文字 16 進数 |
以下は、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 文字の 16 進数文字列。リクエストごとに新しく生成されます |
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 | アラートルールが発火したとき(スケジュール実行、または 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 には、レポートの 2 つの期間それぞれについて clicks、impressions、ctr、position が入ります。各検出器が何を計測するかは、アラートで説明しています。
署名の検証方法
署名は、AutoPSEO が送信したバイト列そのものに対する HMAC-SHA256 です。Webhook の署名シークレットを鍵として計算し、sha256= と小文字の 16 進数を連結した形式で記載されます。検証の手順は次のとおりです。
- JSON をパースする前に、リクエスト本文を生のまま読み取ります。パースして再びシリアライズすると、バイト列が変わる場合があります。
- そのバイト列に対して HMAC-SHA256 を計算します。シークレットは、表示された 64 文字の文字列をそのままテキストとして使います。16 進数としてデコードしないでください。
- 計算結果の先頭に
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 は、2 つのバッファの長さが異なると例外をスローするため、先に長さを比較しています。
配信のルール
- 各メッセージの送信は 1 回のみで、タイムアウトは 10 秒です。2xx 以外の応答はすべて失敗として扱われ、ステータスコードとレスポンス本文の冒頭部分が Delivery history に記録されます。
- リダイレクトには追従しません。3xx の応答は失敗となり、最終的な URL を使用するよう案内するメモが残ります。
- タイマーによる再試行は行いません。送信に失敗したアラートは送信済みとして記録されないため、次回のチェックで再度評価され、まだ発火していれば送信されます。ほとんどの検出器では翌朝、インデックス状態の変化(
index_flip)では次の 1 時間後です。送信に失敗した定期レポートは、同じ期間内に再送されません。エンドポイントを修正したあとで Send now を使用してください。 idはリクエストごとに作成されるため、イベントではなく配信を識別する値です。アラートの重複を排除するには、event_type、site_url、occurred_atの日付を組み合わせてください。ルールが同じプロパティに送信するのは、UTC の 1 日につき最大 1 回です。ただし、誰かが Test rule を実行した場合は除きます。
署名シークレット
署名シークレットが表示されるのは、Webhook を保存したときの 1 回だけで、一覧には二度と表示されません。受信側の設定に、保護対象のエンドポイントとあわせて、すぐに保管してください。
URL 自体は暗号化されて保存され、一覧にはホスト名と末尾の数文字だけが表示されます。Webhook を削除すると、その Webhook に送信するルールもすべて削除されます。JSON ではなく、Teams チャンネルに読みやすいカードとして表示したい場合は、Microsoft Teams をご利用ください。