Skip to content

การผสานรวม Webhook

Webhook ของ SORI API จะแจ้งระบบของคุณเกี่ยวกับเหตุการณ์สำคัญที่เกิดขึ้นภายใน แพลตฟอร์ม SORI เมื่อเชื่อมต่อ endpoint ของคุณเอง คุณจะตอบสนองต่อกิจกรรมของ แคมเปญ การยืนยันตัวตนของอุปกรณ์ และการอัปเดตโดยผู้ดูแลระบบได้แบบเกือบเรียลไทม์

ภาพรวม

SORI API มีฟังก์ชัน Webhook สำหรับส่ง payload แบบ JSON ที่มีโครงสร้างทันทีที่ เกิดเหตุการณ์สำคัญ โดยกำหนดค่า Webhook ได้ภายใน SORI Console และรองรับหมวดหมู่ ต่อไปนี้:

  • เหตุการณ์แคมเปญ (`campaign.*`) ทริกเกอร์เมื่ออุปกรณ์รู้จำแคมเปญได้ หรือเมื่อผู้ใช้คลิกไปยัง action URL
  • เหตุการณ์การยืนยันตัวตน (`authentication`) ทริกเกอร์เมื่ออุปกรณ์ลงชื่อเข้าใช้ผ่านขั้นตอนการยืนยันตัวตนของ SORI สำเร็จ
  • เหตุการณ์เกี่ยวกับสื่อ (Material) ของผู้ดูแลระบบ (`admin.material.*`)การแจ้งเตือนแบบเลือกใช้ ซึ่งส่งออกมาเมื่อมีการสร้าง อัปเดต หรือลบสื่อภายใน Console

การแจ้งเตือนแบบเกือบเรียลไทม์ช่วยให้คุณสามารถ:

  • การวิเคราะห์ทันที ติดตามและวิเคราะห์ประสิทธิภาพของแคมเปญทันทีที่มีกิจกรรมเกิดขึ้น
  • การตรวจสอบการยืนยันตัวตน กระทบยอดการเข้าสู่ระบบของอุปกรณ์กับบันทึกเซสชันของคุณเอง
  • การตรวจจับการทุจริต ตรวจจับรูปแบบที่ผิดปกติทันทีที่เกิดขึ้น
  • แดชบอร์ดสด แสดงข้อมูลล่าสุดบนแดชบอร์ด

การตั้งค่า Webhook

SORI มีสองวิธีในการกำหนดค่า endpoint ของ Webhook:

URL ของ Webhook ส่วนกลาง

  • ตั้งค่าในส่วน Settings
  • ใช้กับทุกแคมเปญโดยค่าเริ่มต้น
  • ทำหน้าที่เป็น endpoint สำรองเมื่อแคมเปญไม่ได้กำหนดค่าแทนที่

URL ของ Webhook เฉพาะแคมเปญ

  • กำหนดค่าใน Advanced settings ของแต่ละแคมเปญ
  • แทนที่ URL ของ Webhook ส่วนกลางสำหรับแคมเปญนั้นโดยเฉพาะ
  • มีประโยชน์เมื่อแคมเปญแต่ละรายการต้องใช้การจัดการเฉพาะ

การสมัครรับเหตุการณ์ (Settings → Webhooks)

ใน Account Settings คุณสามารถเลือกหมวดหมู่เหตุการณ์ที่บัญชีจะรับได้:

  • Campaign events: สมัครรับการแจ้งเตือน campaign.*(กิจกรรม impression และ click)
  • Authentication events: สมัครรับเหตุการณ์authentication ที่ส่งออกมาระหว่างอุปกรณ์เข้าสู่ระบบ
  • Administrative events: สมัครรับการแจ้งเตือนadmin.material.* ที่ส่งเมื่อผู้ใช้ Console จัดการสื่อ

บัญชีใหม่จะเปิดใช้ Campaign events และ Authentication events โดยค่าเริ่มต้น ผู้ดูแลระบบสามารถปรับช่องทำเครื่องหมายเหล่านี้ได้ทุกเมื่อ และการเปลี่ยนแปลงจะมีผล ทันทีต่อการส่ง Webhook ครั้งถัดไป

วิธีตั้งค่า Webhook

  1. เตรียม endpoint แบบ HTTPS บนเซิร์ฟเวอร์เพื่อรับเหตุการณ์ Webhook
  2. กำหนดค่าอย่างใดอย่างหนึ่งต่อไปนี้:
    • URL ของ Webhook ส่วนกลางใน Settings หรือ
    • URL ของ Webhook เฉพาะแคมเปญในการตั้งค่าของแต่ละแคมเปญ
  3. เลือกหมวดหมู่เหตุการณ์ที่ต้องการรับใน Settings → Webhooks
  4. ตรวจสอบว่า endpoint รองรับคำขอ POST ที่มี payload แบบ JSON และตอบกลับ อย่างรวดเร็ว (ภายในห้าวินาที)

ประเภทเหตุการณ์

payload ของ Webhook แต่ละรายการมีฟิลด์ event ซึ่งเก็บชื่อเหตุการณ์มาตรฐาน เพื่อความชัดเจน การผสานรวมใหม่ควรแยกการทำงานตามค่า event

เหตุการณ์การแสดงผลแคมเปญ (campaign.impression)

ส่งเมื่อแคมเปญแสดงบนอุปกรณ์ของผู้ใช้สำเร็จ เหตุการณ์นี้พร้อมใช้งานเมื่อเปิดใช้ Campaign events

เหตุการณ์การคลิกแคมเปญ (campaign.click)

ส่งเมื่อผู้ใช้แตะแคมเปญและถูกเปลี่ยนเส้นทางไปยัง action URL เหตุการณ์นี้พร้อมใช้งาน เมื่อเปิดใช้ Campaign events

เหตุการณ์การยืนยันตัวตน (authentication)

ส่งหลังจากอุปกรณ์ยืนยันตัวตนกับ SORI เสร็จสมบูรณ์ payload มีพารามิเตอร์ query ที่ส่งมาพร้อมกับคำขอยืนยันตัวตน ซึ่งใช้เชื่อมโยงการเข้าสู่ระบบกับตัวระบุเซสชัน ของคุณเองได้

การจัดการเหตุการณ์ Webhook

เมื่อ endpoint ได้รับเหตุการณ์ Webhook จะมี payload แบบ JSON ที่ระบุรายละเอียด ของเหตุการณ์ ตัวอย่างของเหตุการณ์แต่ละประเภทแสดงไว้ด้านล่าง ฟิลด์ที่ระบุเป็น null อาจถูกละไว้ทั้งหมดเมื่อไม่มีค่า

Schema ของ payload

ฟิลด์ต่อไปนี้จะถูกส่งมากับ Webhook ของแคมเปญทุกรายการ เว้นแต่จะระบุไว้เป็นอย่างอื่น

ฟิลด์ประเภทคำอธิบาย
eventstringชื่อเหตุการณ์มาตรฐาน เช่น campaign.impression, campaign.click หรือ authentication
event_typestringสำเนาเดิมของ event ซึ่งยังส่งออกมาเพื่อรองรับความเข้ากันได้ย้อนหลัง
account_idstringตัวระบุบัญชี SORI ที่เป็นเจ้าของแคมเปญ
created_atISO 8601 stringเวลาฝั่งเซิร์ฟเวอร์เมื่อสร้างออบเจ็กต์เหตุการณ์
timestampISO 8601 stringเวลาประทับการส่งที่เพิ่มก่อนส่งออก ใช้ประโยชน์ในการตรวจสอบ idempotency
activity_idstringตัวระบุที่ไม่ซ้ำกันของ impression หรือ click นั้น (เฉพาะเหตุการณ์แคมเปญ)
device_idstringอุปกรณ์/เซสชันที่ทริกเกอร์เหตุการณ์ หากมีข้อมูล
platformstringแพลตฟอร์มไคลเอนต์ที่ SDK รายงาน (Android, iOS เป็นต้น)
metadataobjectคู่คีย์-ค่าแบบกำหนดเองที่ส่งต่อจาก SDK หรือคำขอยืนยันตัวตน
geolocation.viewer_countrystringประเทศที่ได้จาก CloudFront GeoIP (ส่งคืน Unknown หากตรวจหาไม่ได้)
geolocation.viewer_regionstringภูมิภาค/รัฐที่ได้จากการค้นหา GeoIP
geolocation.viewer_citystringเมืองที่ได้จากการค้นหา GeoIP
campaign.idstringตัวระบุแคมเปญที่ปรับให้อยู่ในรูปแบบมาตรฐาน ซึ่งรับประกันว่าตรงกับ ID ใน Console
campaign.namestringชื่อแคมเปญที่แสดง ณ เวลาที่เกิดเหตุการณ์
campaign.tagsstring[]แท็กที่กำหนดให้แคมเปญ (อาร์เรย์ว่างหากไม่มี)
campaign.imagestring (URL)URL แบบ HTTPS ของภาพขนาดย่อของแคมเปญ หากกำหนดไว้
material.idstringตัวระบุสื่อที่รู้จำได้ (เฉพาะเหตุการณ์แคมเปญ)
material.namestringชื่อสื่อ โดยจะละฟิลด์นี้เมื่อไม่มีสื่อที่เกี่ยวข้อง
material.tagsstring[]แท็กที่จัดเก็บไว้ในระเบียนสื่อ (อาร์เรย์ว่างหากไม่มี)
material.imagestring (URL)URL ของภาพตัวอย่างสื่อ หากมี

ฟิลด์เดิม

event_type, campaign_id, campaign_name, material_id และ material_name เป็นฟิลด์ซ้ำแบบเดิมที่คงไว้เพื่อรองรับความเข้ากันได้ย้อนหลังเท่านั้น และจะถูกนำออก ในรุ่นถัดไป โปรดปรับการผสานรวมให้ใช้ฟิลด์ event ร่วมกับออบเจ็กต์ campaign และ material ที่ซ้อนอยู่ เพื่อความชัดเจน payload ตัวอย่างด้านล่างจึงไม่รวม คีย์ที่เลิกใช้เหล่านี้

สำหรับเหตุการณ์ impression:

json
{
  "event": "campaign.impression",
  "account_id": "acc_123456",
  "created_at": "2025-10-14T05:25:12.421Z",
  "activity_id": "act_7890",
  "device_id": "device_abc",
  "platform": "Android",
  "metadata": {
    "session": "abcd-1234"
  },
  "geolocation": {
    "viewer_country": "United States",
    "viewer_region": "Michigan",
    "viewer_city": "Ann Arbor"
  },
  "campaign": {
    "id": "cmp_1234",
    "name": "Fall Promotion",
    "tags": [
      "retail",
      "autumn"
    ],
    "image": "https://cdn.soriapi.com/campaigns/cmp_1234.png"
  },
  "material": {
    "id": "mat_5678",
    "name": "Audio Spot 15s",
    "tags": [
      "audio",
      "15s"
    ],
    "image": "https://cdn.soriapi.com/materials/mat_5678.png"
  },
  "timestamp": "2025-10-14T05:25:12.421Z"
}

สำหรับเหตุการณ์ click:

json
{
  "event": "campaign.click",
  "account_id": "acc_123456",
  "created_at": "2025-10-14T05:26:03.009Z",
  "activity_id": "act_7890",
  "device_id": "device_abc",
  "platform": "Android",
  "metadata": {
    "session": "abcd-1234",
    "utm_source": "push"
  },
  "geolocation": {
    "viewer_country": "United States",
    "viewer_region": "Michigan",
    "viewer_city": "Ann Arbor"
  },
  "campaign": {
    "id": "cmp_1234",
    "name": "Fall Promotion",
    "tags": [
      "retail",
      "autumn"
    ],
    "image": "https://cdn.soriapi.com/campaigns/cmp_1234.png"
  },
  "material": {
    "id": "mat_5678",
    "name": "Audio Spot 15s",
    "tags": [
      "audio",
      "15s"
    ],
    "image": "https://cdn.soriapi.com/materials/mat_5678.png"
  },
  "timestamp": "2025-10-14T05:26:03.009Z"
}

สำหรับเหตุการณ์การยืนยันตัวตน:

json
{
  "event": "authentication",
  "account_id": "acc_123456",
  "created_at": "2025-10-14T05:15:44.832Z",
  "device_id": "device_abc",
  "platform": "Android",
  "metadata": {
    "app_version": "1.8.0",
    "session": "abcd-1234"
  },
  "geolocation": {
    "viewer_country": "United States",
    "viewer_region": "Michigan",
    "viewer_city": "Ann Arbor"
  },
  "timestamp": "2025-10-14T05:15:44.832Z"
}

Metadata แบบกำหนดเอง

ฟิลด์ metadata คือแมปแบบคีย์-ค่าที่ SDK ส่งมา (สำหรับเหตุการณ์แคมเปญ) หรือมาจากพารามิเตอร์ query ของคำขอยืนยันตัวตน (สำหรับเหตุการณ์การยืนยันตัวตน) ฟิลด์นี้ใช้ระบุผู้ใช้หรืออุปกรณ์และส่งบริบทเพิ่มเติมได้ โดยเป็นฟิลด์ที่เลือกใช้ได้ โปรดดูรายละเอียดเพิ่มเติมในส่วน ตัวให้บริการ Metadata

หมายเหตุเกี่ยวกับข้อมูลตำแหน่ง

ค่าตำแหน่งทางภูมิศาสตร์อยู่ภายในออบเจ็กต์ geolocation ข้อมูลนี้อ้างอิงจาก การประมาณค่าของ CloudFront GeoIP และอาจไม่แม่นยำเสมอไป หากไม่มีข้อมูลที่แน่นอน ระบบจะส่งคืนค่า Unknown

ข้อกำหนดในการตอบกลับ

endpoint ของ Webhook ควร:

  • ตอบกลับด้วยรหัสสถานะ 2xx เพื่อยืนยันว่าได้รับข้อมูลแล้ว
  • ประมวลผลเหตุการณ์แบบอะซิงโครนัสหากทำได้ เพื่อหลีกเลี่ยงการบล็อก
  • จัดการเหตุการณ์แบบ idempotent (โดยใช้เวลาประทับหรือ activity ID)
  • ตอบกลับภายใน 5 วินาที เพื่อหลีกเลี่ยงการหมดเวลา

ข้อควรพิจารณาด้านความปลอดภัย

  • ใช้ HTTPS สำหรับ endpoint ของ Webhook ทุกครั้งที่ทำได้ เพื่อรักษาความเป็นส่วนตัวของข้อมูล
  • ตรวจสอบโครงสร้าง payload ที่เข้ามาและยืนยันค่า event
  • เก็บ URL ของ Webhook ไว้เป็นความลับ
  • เมื่อกำหนดค่า app_id และ secret_key แล้ว ให้ตรวจสอบ header X-SORI-Signature กับสำเนา payload ของคุณเพื่อยืนยันความถูกต้อง

การจัดการข้อผิดพลาด

หาก endpoint รับเหตุการณ์ไม่สำเร็จ SORI API Server จะ:

  • ลองส่งรายการที่ล้มเหลวใหม่สูงสุด 3 ครั้ง
  • ใช้การหน่วงเวลาแบบทวีคูณ (exponential backoff) ระหว่างการลองใหม่แต่ละครั้ง
  • ยกเลิกเหตุการณ์หลังจากลองใหม่ครบทุกครั้งแล้ว

ตัวอย่างการนำไปใช้

Python (FastAPI)

python
from fastapi import FastAPI, Request

app = FastAPI()

@app.post("/webhook")
async def webhook(request: Request):
    payload = await request.json()
    event = payload.get("event")

    if event == "campaign.impression":
        # Handle impression event
        pass
    elif event == "campaign.click":
        # Handle click event
        pass
    elif event == "authentication":
        # Handle authentication event
        pass

    return {"status": "success"}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=3000)

Node.js (Express)

typescript
import express from "express";

const app = express();
app.use(express.json());

app.post("/webhook", (req, res) => {
  const payload = req.body;
  const event = payload.event;

  if (event === "campaign.impression") {
    // Handle impression event
  } else if (event === "campaign.click") {
    // Handle click event
  } else if (event === "authentication") {
    // Handle authentication event
  }

  res.status(200).send({ status: "success" });
});

app.listen(3000, () => {
  console.log("Server is running on port 3000");
});