Skip to main content

การคำนวณสถิติ Campaign

ภาพรวม​

หลังจากส่ง campaign ออกไปแล้ว ระบบต้องรายงานให้ได้ว่าเข้าถึงผู้ใช้กี่คน มีคนอ่านและคลิกเท่าไร และลิงก์ไหนถูกคลิกมากที่สุด

งานนี้คือ consumer ที่คำนวณตัวเลขเหล่านั้นจากตาราง tracking_log แล้วเขียนผลกลับลงตาราง campaign เพื่อให้ CMS อ่านไปแสดงผลได้ทันทีโดยไม่ต้อง aggregate ใหม่ตอน query

การคำนวณถูก trigger ได้ 2 ทาง คือ (1) cron รายชั่วโมงที่กวาด campaign ซึ่งถูกทำเครื่องหมายว่า dirty ไว้ใน Redis และ (2) การ publish ตรงเข้า queue เมื่อต้องการคำนวณ campaign ใดเป็นการเฉพาะ

Business Flow​

ฝั่ง scanner (cron บน profile cron-scheduler)​

  1. ทุกชั่วโมงตรงตาม cron 0 * * * * CampaignStatScannerService จะสแกน Redis เพื่อหา key รูปแบบ CAMPAIGN_STAT_DIRTY:<campaignId> ซึ่ง key เหล่านี้ถูกตั้งโดยเส้นทาง tracking ทุกครั้งที่มี click หรือ read เข้ามา
  2. แกะ campaign id ออกจากชื่อ key แล้ว publish 1 job ต่อ 1 campaign เข้า queue calculate_campaign_stat
  3. หากไม่พบ key dirty เลย จะข้ามรอบนั้นไป เพื่อไม่ให้เสีย query ฐานข้อมูลโดยเปล่าประโยชน์

ฝั่ง consumer (profile main)​

  1. รับ payload ที่มีฟิลด์ campaignId และ date ซึ่งเป็น optional ทั้งคู่ หากไม่ระบุ campaignId ระบบจะคำนวณ ทุก campaign ที่มีสถานะ sent และยังอยู่ในช่วง tracking period ซึ่งมีค่าเริ่มต้น 90 วันนับจาก start_date
  2. calculateCampaignStats คำนวณตัวเลขรวมจาก tracking_log ได้แก่
    • totalRecipient — จำนวนผู้รับ โดยกรณี broadcast จะใช้จำนวน follower จาก LINE Insight API
    • totalReach — จำนวน line_uid ที่ไม่ซ้ำกันซึ่งมี activity
    • totalActivity — จำนวน activity ทั้งหมด
    • totalUniqueClick — จำนวน line_uid ที่ไม่ซ้ำกันซึ่งมี action_type เป็น click
    • totalFirstClick — จำนวนการคลิกครั้งแรกของ event ที่ type เป็น uri หรือ postback
    • ทุกตัวเลขใช้เกณฑ์กรองว่า line_uid ต้องไม่เป็น NULL และไม่เท่ากับ -
  3. summarizeCampaignStats สรุปตัวเลขรายลิงก์และรายรูปลงในคอลัมน์ template_tracking โดยแยกตามประเภท flex, tappableImage, image และ video พร้อม join กับตาราง rich_message เพื่อระบุว่าลิงก์แต่ละ index คืออะไร
    • จำนวน read นับจาก event ประเภท asset ส่วนจำนวน click นับจาก event ประเภท uri และ postback
  4. เขียนผลลัพธ์ทั้งหมดกลับลงตาราง campaign ทั้งคอลัมน์สถิติและ template_tracking

ไฟล์และฟังก์ชันหลัก​

  • internal/campaign/campaign.go
    • Service.ProcessCalculateCampaignStat(ctx, payload) — entry point ของ consumer
    • calculateCampaignStats() และ getLineFollowerCount()
    • ค่าคงที่ defaultCampaignTrackingPeriodDays เท่ากับ 90
    • struct CampaignStatPayload ซึ่งมีฟิลด์ CampaignID และ Date
  • internal/campaign/stats.go
    • countUniqueLineUID(), countActivity(), countFirstClick()
    • summarizeCampaignStats(), queryClicks(), queryAssetReads()
  • internal/campaign/consumer.go — Consumer.HandleCalculateCampaignStat
  • internal/cronscheduler/campaign_stat_scanner.go — CampaignStatScannerService.Run(ctx) และค่าคงที่ campaignDirtyKeyPrefix
  • Queue: consume calculate_campaign_stat บน profile main โดยมี cron บน profile cron-scheduler เป็นผู้ publish

จุดเชื่อมต่อกับ Service อื่น​

  • ตาราง tracking_log — เป็นแหล่งข้อมูลดิบทั้งหมด โดยใช้คอลัมน์ campaign_id, line_uid, action_type, type, rich_message_index และ created_date
  • ตาราง campaign — ปลายทางที่เขียนผลลัพธ์ และ ตาราง rich_message — อ่านโครงสร้างเพื่อ map index กลับไปยังลิงก์
  • Redis — key CAMPAIGN_STAT_DIRTY:* ทำหน้าที่บอกว่า campaign ใดมีข้อมูลใหม่ที่ต้องคำนวณ
  • LINE API — GET /v2/bot/insight/followers สำหรับหาค่า totalRecipient ของ campaign แบบ broadcast
  • ผู้ใช้ผลลัพธ์ — cms-api-go ในโดเมน campaign-management ซึ่งเป็นผู้แสดงหน้ารายงาน campaign