ข้ามไปยังเนื้อหา
เอกสารประกอบ

Outbound webhook: payload และลายเซ็น

รับการแจ้งเตือนและรายงานจาก AutoPSEO เป็น JSON ที่มีลายเซ็นที่ปลายทาง HTTPS ใดก็ได้ ครอบคลุม request header, ฟิลด์ใน body, ประเภทอีเวนต์ และวิธีตรวจสอบลายเซ็น

บัญชี → Slack, Teams และเว็บฮุค → เว็บฮุคขาออกต้องสมัครสมาชิกหรือทดลองใช้อ่าน 4 นาที

Outbound webhook จะส่งการแจ้งเตือน รายงานที่ตั้งเวลาไว้ ข้อความทดสอบ และสรุปรายงานจาก AutoPSEO ไปยังปลายทางที่คุณดูแลเอง โดยส่งเป็น JSON POST หนึ่งครั้งต่อหนึ่งข้อความ และลงลายเซ็นด้วย HMAC-SHA256 ใช้ได้กับ Zapier, Make, n8n, เครื่องมือจัดการเหตุการณ์ หรือโค้ดของคุณเอง โดยไม่ต้องมีบัญชี Slack หรือ Teams หากต้องการ webhook ที่ส่งบทความไปยังเว็บไซต์ของคุณ นั่นเป็นส่วนของ content engine ดูการส่งมอบเนื้อหา

เพิ่ม webhook

  1. ในส่วน Outbound webhooks คลิก New webhook
  2. ตั้ง Name แล้ววาง URL ของปลายทาง ต้องเป็น HTTPS สาธารณะเท่านั้น ระบบจะปฏิเสธ http ธรรมดา, localhost, ชื่อที่ลงท้ายด้วย .local หรือ .internal, โฮสต์ที่ไม่มีจุด และ IP แบบ private หรือ link-local
  3. คัดลอกลายเซ็นลับ (signing secret) ที่แสดงหลังบันทึก ระบบจะแสดงให้ดูเพียงครั้งเดียวเท่านั้น
  4. คลิก Send test เพื่อส่งอีเวนต์ test จากนั้นผูกรายงานที่ตั้งเวลาหรือการแจ้งเตือนเข้ากับ webhook

หน้าตาของ webhook request

ทุกข้อความเป็น POST ที่มี header ดังนี้

Headerค่า
Content-Typeapplication/json
User-AgentAutoPSEO-Webhook/1.0
X-AutoPSEO-Eventประเภทอีเวนต์ เช่น traffic_drop
X-AutoPSEO-Signaturesha256= ตามด้วยอักขระเลขฐานสิบหกตัวพิมพ์เล็ก 64 ตัว

ด้านล่างคือการแจ้งเตือนทราฟฟิกลดลงของ property แบบ domain จากรอบ 06:00 UTC วันที่ 12 ตุลาคม 2026 จัดรูปแบบให้อ่านง่าย (ที่ส่งจริงเป็น 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 ตัวอักษร ใหม่ทุก request
event_typeสิ่งที่เกิดขึ้น (ดูหัวข้อถัดไป)
severitycritical, high, medium หรือ low สำหรับการแจ้งเตือน และ info สำหรับรายงาน สรุป และการทดสอบ
site_idid ของ property ใน AutoPSEO หรือ null สำหรับการทดสอบและ property เดโม
site_urlproperty ของ Search Console เช่น sc-domain:example.com หรือ https://www.example.com/ หรือ null สำหรับการทดสอบ
occurred_atเวลาที่สร้างข้อความ ในรูปแบบ ISO 8601 เป็น UTC
title, textหัวข้อและประโยคสรุปที่ Slack และ Teams แสดง
urlรายงานใน AutoPSEO หรือ null สำหรับการทดสอบ
payload.fieldsค่าที่มีป้ายกำกับ ซึ่ง Slack แสดงเป็น fields และ Teams แสดงเป็น facts
payload.tablecolumns และ 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 ruledetector, window, range (ช่วงวันที่ หรือ null สำหรับ index_flip, rank_drop และ audit_regression), result
scheduled_reportรายงานที่ตั้งเวลาไว้ถูกส่งออก ทั้งตามกำหนดเวลาหรือผ่าน Send nowreportType (summary, queries, pages หรือ rankings), range (ช่วงวันที่พร้อม label), totals, previous
report_summaryมีผู้ใช้กด Send to Slack ในหน้ารายงานไม่มี ตัวเลขอยู่ใน fields และ table
testมีผู้ใช้คลิก Send test ที่ webhooksample ซึ่งเป็น true เสมอ

result ทวนสิ่งที่ detector วัดได้ ได้แก่ fired, metric, value, baseline, change (เป็น null เมื่อไม่มีข้อมูลให้เปรียบเทียบ), severity และ summary และสำหรับ anomaly จะมี z ซึ่งเป็น modified z-score เพิ่มเข้ามา ส่วน totals และ previous เก็บ clicks, impressions, ctr และ position ของสองช่วงเวลาในรายงาน รายละเอียดว่า detector แต่ละตัววัดอะไรอยู่ในหัวข้อการแจ้งเตือน

วิธีตรวจสอบลายเซ็น

ลายเซ็นคือ HMAC-SHA256 ของไบต์ที่ AutoPSEO ส่งมาตามจริงทุกไบต์ โดยใช้ signing secret ของ webhook เป็นกุญแจ และเขียนเป็น sha256= ตามด้วยเลขฐานสิบหกตัวพิมพ์เล็ก วิธีตรวจสอบมีดังนี้

  1. อ่าน raw request body ก่อนแปลง JSON เพราะการ parse แล้วแปลงกลับเป็นข้อความอีกครั้งอาจทำให้ไบต์เปลี่ยนไป
  2. คำนวณ HMAC-SHA256 จากไบต์เหล่านั้น โดยใช้ secret เป็นข้อความ คือสตริง 64 ตัวอักษรตามที่แสดงทุกประการ ไม่ต้องถอดรหัสจากเลขฐานสิบหก
  3. เติม sha256= นำหน้าผลลัพธ์ แล้วเปรียบเทียบกับ header X-AutoPSEO-Signature แบบ constant time
  4. ปฏิเสธ request หากไม่ตรงกัน แต่ถ้าตรงให้ตอบกลับด้วยสถานะ 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);

ต้องตรวจความยาวก่อน เพราะ timingSafeEqual ของ Node จะ throw error เมื่อ buffer สองตัวมีความยาวไม่เท่ากัน

กฎการส่งมอบ

  • แต่ละข้อความถูกส่งเพียงหนึ่งครั้ง โดยมี timeout 10 วินาที การตอบกลับด้วยสถานะใดก็ตามที่ไม่ใช่ 2xx ถือว่าล้มเหลว และจะถูกเก็บไว้ใน Delivery history พร้อมรหัสสถานะและส่วนต้นของ response body ที่คุณตอบกลับ
  • ระบบไม่ตามการ redirect การตอบกลับ 3xx จะถือว่าล้มเหลว พร้อมข้อความแนะนำให้ใช้ URL ปลายทางจริง
  • ไม่มีการลองส่งซ้ำตามเวลา การแจ้งเตือนที่ส่งไม่สำเร็จจะไม่ถูกทำเครื่องหมายว่าส่งแล้ว ดังนั้นการตรวจครั้งถัดไปจะประเมินใหม่และส่งอีกครั้งหากยังเข้าเงื่อนไข ซึ่งสำหรับ detector ส่วนใหญ่คือเช้าวันถัดไป และสำหรับ index flip คือชั่วโมงถัดไป ส่วนรายงานที่ตั้งเวลาไว้และส่งไม่สำเร็จจะไม่ถูกส่งซ้ำในรอบเดียวกัน ให้ใช้ Send now หลังแก้ไขปลายทางแล้ว
  • id ถูกสร้างใหม่ทุก request จึงระบุถึงการส่งแต่ละครั้ง ไม่ใช่ตัวอีเวนต์ หากต้องการกรองการแจ้งเตือนซ้ำ ให้ใช้ event_type, site_url และวันที่ของ occurred_at ร่วมกัน เพราะกฎหนึ่งข้อจะส่งไม่เกินหนึ่งครั้งต่อ property ต่อวัน UTC เว้นแต่มีผู้ใช้สั่ง Test rule

ลายเซ็นลับ (signing secret)

AutoPSEO แสดง signing secret เพียงครั้งเดียวตอนที่คุณบันทึก webhook และจะไม่แสดงในรายการอีก ให้เก็บไว้ในการตั้งค่าของตัวรับทันที ควบคู่กับปลายทางที่มันปกป้องอยู่

ตัว URL ถูกเก็บแบบเข้ารหัส และในรายการจะแสดงเฉพาะโฮสต์กับอักขระท้ายสุดเท่านั้น การลบ webhook จะลบทุกกฎที่ส่งมายัง webhook นั้นด้วย หากต้องการการ์ดที่อ่านง่ายในช่อง Teams แทนที่จะเป็น JSON ให้ดู Microsoft Teams

ให้คอนเทนต์ SEO ของคุณทำงานอัตโนมัติ

เชื่อมต่อ Search Console และเว็บไซต์ของคุณ AutoPSEO จะสแกนและวางแผนหัวข้อแรกให้ทันที ไม่ต้องใช้บัตรเครดิต