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.goConsumer.HandleCalculateCampaignStat
  • internal/cronscheduler/campaign_stat_scanner.goCampaignStatScannerService.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 APIGET /v2/bot/insight/followers สำหรับหาค่า totalRecipient ของ campaign แบบ broadcast
  • ผู้ใช้ผลลัพธ์ — cms-api-go ในโดเมน campaign-management ซึ่งเป็นผู้แสดงหน้ารายงาน campaign