Skip to main content

ลิงก์ติดตาม (Tracking Token / Redirect)

ภาพรวม

เมื่อผู้ใช้กดลิงก์ที่ระบบส่งออกไป เราต้องบันทึกให้ได้ว่า "ใครกด ลิงก์ไหน จากที่ใด" ก่อนพาผู้ใช้ไปยังหน้าปลายทาง โมดูลนี้รับผิดชอบฝั่ง สร้างลิงก์ติดตาม ส่วนการ redirect จริงเกิดขึ้นที่ client-api และ client-web

ระบบมีกลไกสองแบบ แบ่งตามชนิดของ content:

ชนิด contentกลไกผู้รับผิดชอบ
Rich Menutoken-based ผ่าน TrackingTokenServicecms-api (โมดูลนี้)
Lead Generation Formtoken-basedcms-api (โมดูลนี้)
CampaignRedirectService ภายนอกworker

โมดูล internal/modules/tracking ไม่เปิด HTTP route ใด ๆ เพราะโมดูลต้นทางใน NestJS ก็ไม่มี controller เช่นกัน โมดูลนี้ทำหน้าที่เป็น provider ที่ export TrackingTokenService ให้โมดูล LINE Message API และ Rich Menu เรียกใช้

Business Flow

  1. ผู้ใช้สร้าง rich menu ที่มีปุ่มเป็นลิงก์ จากนั้น richmenu/tracking_adapter.go เรียก TrackingTokenService

  2. service สร้าง token ที่ห่อข้อมูลไว้ในตัวเอง แล้วบันทึกลงตาราง tracking_token

  3. โหมดการทำงานเลือกด้วย env TRACKING_REDIRECT_MODE

    • ค่า builtin ใช้ token เข้ารหัสของระบบเราเองที่ internal/core/trackinglink
    • ค่าอื่น ๆ ซึ่งมีค่าเริ่มต้นเป็น legacy ใช้ redirect service เดิมที่ internal/externals/redirects
  4. โครงสร้าง token ในโหมด builtin นิยามอยู่ที่ internal/core/trackinglink/token.go

    bytes = keyId(1) ‖ nonce(12) ‖ ciphertext ‖ tag(16) // AES-256-GCM, AAD "tracking-link-v1"
    token = base64url_nopad(bytes)

    ภายใน payload มี field ct ที่มีค่าเป็น "rich_menu" หรือ "lead_gen" โดยลำดับ key ถูกกำหนดคงที่เพื่อให้ผลลัพธ์ระดับ byte เสถียร

  5. ลิงก์ที่ฝังอยู่ใน rich menu จึงเป็น URL ที่มี token นี้ประกอบอยู่

  6. เมื่อผู้ใช้กดลิงก์ ฝั่ง client-api จะถอดรหัส token บันทึก event ลงตาราง tracking_line_users แล้ว redirect ไปยังปลายทาง

  7. ผลการติดตามดูได้ผ่านโมดูล Tracking LINE Users และหน้ารายงานของ rich menu

warning

ตัวเข้ารหัสฝั่ง cms-api กับตัวถอดรหัสฝั่ง client-api ถูก pin ไว้กับ reference token ชุดเดียวกัน หากฝั่งใดฝั่งหนึ่งเปลี่ยนไปจนไม่ตรงกัน ลิงก์ทั้งหมดที่ส่งออกไปแล้วจะใช้งานไม่ได้ทันที

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

ไฟล์บทบาท
internal/modules/tracking/service.goTrackingTokenService — port ของ tracking-token.service.ts
internal/modules/tracking/repository.goอ่านและเขียนตาราง tracking_token
internal/modules/tracking/controller.goRegisterRoutes เป็น no-op ไม่ลงทะเบียน route ใด
internal/core/trackinglink/token.goสร้าง token AES-256-GCM สำหรับโหมด builtin
internal/core/trackinglink/config.goMode() และ IsBuiltin() อ่านค่าจาก TRACKING_REDIRECT_MODE
internal/externals/redirects/redirects.goclient ของ redirect service เดิมสำหรับโหมด legacy
internal/modules/richmenu/tracking_adapter.goจุดที่โมดูล rich menu เรียกใช้บริการนี้

Endpoint — ไม่มี โมดูลนี้ไม่เปิด route

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

  • Permission — ไม่มี route จึงไม่มี guard ใด ๆ การควบคุมสิทธิ์เกิดที่โมดูลผู้เรียก
  • ตารางที่เกี่ยวข้องtracking_token, tracking_line_users และ content_page_utm
  • EnvironmentTRACKING_REDIRECT_MODE เลือกได้ระหว่าง builtin และ legacy ส่วนคีย์ AES อ้างอิงด้วย keyId ที่ฝังอยู่ใน token
  • Cross-service — line-management-client-api-go ทำหน้าที่ถอดรหัส token ส่วน worker ใช้ RedirectService สำหรับลิงก์ของแคมเปญ
  • เอกสารออกแบบdocs/superpowers/specs/2026-07-06-builtin-tracking-redirect-design.md
  • โมดูลที่เกี่ยวข้อง — Rich Menu, LINE Message API, Tracking LINE Users และ Campaign Management