ลิงก์ติดตาม (Tracking Token / Redirect)
ภาพรวม
เมื่อผู้ใช้กดลิงก์ที่ระบบส่งออกไป เราต้องบันทึกให้ได้ว่า "ใครกด ลิงก์ไหน จากที่ใด" ก่อนพาผู้ใช้ไปยังหน้าปลายทาง โมดูลนี้รับผิดชอบฝั่ง สร้างลิงก์ติดตาม ส่วนการ redirect จริงเกิดขึ้นที่ client-api และ client-web
ระบบมีกลไกสองแบบ แบ่งตามชนิดของ content:
| ชนิด content | กลไก | ผู้รับผิดชอบ |
|---|---|---|
| Rich Menu | token-based ผ่าน TrackingTokenService | cms-api (โมดูลนี้) |
| Lead Generation Form | token-based | cms-api (โมดูลนี้) |
| Campaign | RedirectService ภายนอก | worker |
โมดูล internal/modules/tracking ไม่เปิด HTTP route ใด ๆ เพราะโมดูลต้นทางใน NestJS
ก็ไม่มี controller เช่นกัน โมดูลนี้ทำหน้าที่เป็น provider ที่ export TrackingTokenService
ให้โมดูล LINE Message API และ Rich Menu เรียกใช้
Business Flow
-
ผู้ใช้สร้าง rich menu ที่มีปุ่มเป็นลิงก์ จากนั้น
richmenu/tracking_adapter.goเรียกTrackingTokenService -
service สร้าง token ที่ห่อข้อมูลไว้ในตัวเอง แล้วบันทึกลงตาราง
tracking_token -
โหมดการทำงานเลือกด้วย env
TRACKING_REDIRECT_MODE- ค่า
builtinใช้ token เข้ารหัสของระบบเราเองที่internal/core/trackinglink - ค่าอื่น ๆ ซึ่งมีค่าเริ่มต้นเป็น
legacyใช้ redirect service เดิมที่internal/externals/redirects
- ค่า
-
โครงสร้าง token ในโหมด builtin นิยามอยู่ที่
internal/core/trackinglink/token.gobytes = 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 เสถียร -
ลิงก์ที่ฝังอยู่ใน rich menu จึงเป็น URL ที่มี token นี้ประกอบอยู่
-
เมื่อผู้ใช้กดลิงก์ ฝั่ง client-api จะถอดรหัส token บันทึก event ลงตาราง
tracking_line_usersแล้ว redirect ไปยังปลายทาง -
ผลการติดตามดูได้ผ่านโมดูล Tracking LINE Users และหน้ารายงานของ rich menu
ตัวเข้ารหัสฝั่ง cms-api กับตัวถอดรหัสฝั่ง client-api ถูก pin ไว้กับ reference token ชุดเดียวกัน หากฝั่งใดฝั่งหนึ่งเปลี่ยนไปจนไม่ตรงกัน ลิงก์ทั้งหมดที่ส่งออกไปแล้วจะใช้งานไม่ได้ทันที
ไฟล์และฟังก์ชันหลัก
| ไฟล์ | บทบาท |
|---|---|
internal/modules/tracking/service.go | TrackingTokenService — port ของ tracking-token.service.ts |
internal/modules/tracking/repository.go | อ่านและเขียนตาราง tracking_token |
internal/modules/tracking/controller.go | RegisterRoutes เป็น no-op ไม่ลงทะเบียน route ใด |
internal/core/trackinglink/token.go | สร้าง token AES-256-GCM สำหรับโหมด builtin |
internal/core/trackinglink/config.go | Mode() และ IsBuiltin() อ่านค่าจาก TRACKING_REDIRECT_MODE |
internal/externals/redirects/redirects.go | client ของ 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 - Environment —
TRACKING_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