Dokumentacja
Webhooki wychodzące: ładunek i podpis
Odbieraj alerty i raporty AutoPSEO jako podpisany JSON w dowolnym punkcie końcowym HTTPS: nagłówki żądania, pola treści, typy zdarzeń i sposób weryfikacji podpisu.
Webhook wychodzący wysyła alerty AutoPSEO, raporty cykliczne, wiadomości testowe i podsumowania raportów do punktu końcowego, który sam utrzymujesz, jako jedno żądanie JSON POST na wiadomość, podpisane algorytmem HMAC-SHA256. Możesz go użyć do zasilania Zapiera, Make, n8n, narzędzia do obsługi incydentów lub własnego kodu; konto Slack ani Teams nie jest do tego potrzebne. Szukasz webhooka, który dostarcza artykuły na Twoją stronę? Ten należy do silnika treści: zobacz content delivery.
Dodawanie webhooka
- W sekcji Outbound webhooks kliknij New webhook.
- Nadaj mu Name i wklej adres URL punktu końcowego. Musi to być publiczny adres HTTPS: zwykły
http,localhost, nazwy kończące się na.locallub.internal, hosty bez kropki oraz prywatne lub link-local adresy IP są odrzucane. - Skopiuj signing secret wyświetlony po zapisaniu. Pokazujemy go tylko ten jeden raz.
- Kliknij Send test, aby wysłać zdarzenie
test, a następnie podłącz do webhooka raporty cykliczne lub alerty.
Jak wygląda żądanie webhooka
Każda wiadomość to żądanie POST z następującymi nagłówkami:
| Header | Value |
|---|---|
Content-Type | application/json |
User-Agent | AutoPSEO-Webhook/1.0 |
X-AutoPSEO-Event | Typ zdarzenia, na przykład traffic_drop |
X-AutoPSEO-Signature | sha256= i 64 małe znaki szesnastkowe |
Oto alert o spadku ruchu dla usługi domenowej z uruchomienia o 06:00 UTC w dniu 12 października 2026, sformatowany dla czytelności (w rzeczywistości jest to zwarty JSON, a wartości id i site_id są zmyślone):
{
"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"
}
Pola najwyższego poziomu są takie same dla każdego zdarzenia:
| Field | What it holds |
|---|---|
id | Losowy 32-znakowy ciąg szesnastkowy, nowy dla każdego żądania |
event_type | Co się wydarzyło (zobacz następną sekcję) |
severity | critical, high, medium lub low dla alertów; info dla raportów, podsumowań i testów |
site_id | Identyfikator usługi w AutoPSEO lub null dla testów i usługi demonstracyjnej |
site_url | Usługa w Search Console, na przykład sc-domain:example.com lub https://www.example.com/, albo null dla testów |
occurred_at | Moment zbudowania wiadomości, jako znacznik czasu ISO 8601 w UTC |
title, text | Nagłówek i zdanie podsumowujące, które wyświetlają Slack i Teams |
url | Raport w AutoPSEO lub null dla testów |
payload.fields | Opisane wartości, które Slack pokazuje jako pola, a Teams jako fakty |
payload.table | columns i rows dla raportów i podsumowań, w pozostałych przypadkach null |
source | Zawsze autopseo |
Wskaźniki są ułamkami: change równe -0.25 oznacza spadek o 25%, a ctr równe 0.034 to 3,4%.
Typy zdarzeń
event_type | Wysyłane, gdy | Dodatkowe klucze w payload |
|---|---|---|
traffic_drop, traffic_spike, position_drop, ctr_drop, new_lost_rankings, anomaly, index_flip, rank_drop, audit_regression | Zadziała reguła alertu, zgodnie z harmonogramem lub przez Test rule | detector, window, range (daty, albo null dla index_flip, rank_drop i audit_regression), result |
scheduled_report | Wychodzi raport cykliczny, zgodnie z harmonogramem lub przez Send now | reportType (summary, queries, pages lub rankings), range (daty oraz label), totals, previous |
report_summary | Ktoś użyje Send to Slack na stronie raportu | Brak: liczby znajdują się w fields i table |
test | Ktoś kliknie Send test przy webhooku | sample, zawsze true |
result powtarza to, co zmierzył detektor: fired, metric, value, baseline, change (null, gdy nie ma z czym porównać), severity i summary, a dla anomaly także z, czyli zmodyfikowany z-score. totals i previous zawierają clicks, impressions, ctr i position dla dwóch okien czasowych raportu. To, co mierzy każdy detektor, opisano w sekcji Alerts.
Jak zweryfikować podpis
Podpis to HMAC-SHA256 dokładnie tych bajtów, które wysłał AutoPSEO, z kluczem w postaci signing secret webhooka, zapisany jako sha256= i małe znaki szesnastkowe. Aby go sprawdzić:
- Odczytaj surową treść żądania przed jakimkolwiek parsowaniem JSON. Ponowne sparsowanie i serializacja mogą zmienić bajty.
- Oblicz HMAC-SHA256 z tych bajtów, używając sekretu jako tekstu: 64-znakowego ciągu dokładnie tak, jak został wyświetlony, a nie zdekodowanego z postaci szesnastkowej.
- Dodaj prefiks
sha256=i porównaj wynik z nagłówkiemX-AutoPSEO-Signaturew stałym czasie. - Odrzuć żądanie, jeśli się różnią. W przeciwnym razie od razu odpowiedz statusem 2xx, a czasochłonną pracę wykonaj później.
Odbiornik dla Node.js bez zależności:
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);
Sprawdzenie długości jest na początku, ponieważ funkcja timingSafeEqual w Node zgłasza wyjątek, gdy bufory mają różną długość.
Zasady dostarczania
- Każda wiadomość dostaje jedną próbę z limitem czasu 10 sekund. Każda odpowiedź inna niż 2xx jest traktowana jako niepowodzenie i zapisywana w Delivery history wraz z kodem statusu i początkiem treści odpowiedzi.
- Przekierowania nie są śledzone. Odpowiedź 3xx kończy się niepowodzeniem z notatką, by użyć docelowego adresu URL.
- Nic nie jest ponawiane według harmonogramu. Nieudany alert nie jest oznaczany jako wysłany, więc przy następnym sprawdzeniu zostanie oceniony ponownie i opublikowany, jeśli nadal się uruchamia: następnego ranka dla większości detektorów, w kolejnej godzinie dla
index_flip. Nieudany raport cykliczny nie jest wysyłany ponownie w tym samym okresie, więc po naprawie punktu końcowego użyj Send now. idjest tworzony dla każdego żądania, więc identyfikuje dostarczenie, a nie zdarzenie. Aby deduplikować alerty, połączevent_type,site_urli datę zoccurred_at: reguła publikuje najwyżej raz na usługę na dobę UTC, chyba że ktoś uruchomi Test rule.
Signing secret
AutoPSEO pokazuje signing secret tylko raz, przy zapisie webhooka, a lista nigdy nie wyświetla go ponownie. Zapisz go od razu w konfiguracji swojego odbiornika, obok punktu końcowego, który chroni.
Sam adres URL jest przechowywany w postaci zaszyfrowanej, a lista pokazuje tylko jego host i ostatnie znaki. Usunięcie webhooka usuwa też wszystkie reguły, które na niego publikują. Jeśli zamiast JSON wolisz czytelną kartę na kanale Teams, skorzystaj z Microsoft Teams.