Skip to main content

ติดตามการเพิ่มเพื่อน

ภาพรวม

ติดตามการเพิ่มเพื่อน (Friend Track) คือโมดูลสำหรับสร้างแคมเปญวัดผลการชวนเพิ่มเพื่อน แต่ละแคมเปญมี token ประจำตัวที่ใช้เป็นตัวระบุลิงก์ชวนเพิ่มเพื่อน เมื่อผู้ใช้เปิดลิงก์จะถูกนับเป็นการเข้าชม และเมื่อกดเพิ่มเพื่อนสำเร็จจะถูกนับเป็นการติดตาม ระบบจะเก็บข้อมูลทั้งสองส่วนไว้ให้ดูเป็นรายงานอัตราการเปลี่ยนเป็นเพื่อน (conversion) ต่อแคมเปญ

จุดเด่นของโมดูลนี้มี 2 อย่าง

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

โมดูลแบ่งเป็น 3 หน้า คือ หน้ารายการแคมเปญ, หน้าฟอร์มสร้างและแก้ไข และหน้ารายงานผล

Business Flow

หน้ารายการแคมเปญ

  1. เปิดหน้ารายการ ระบบตรวจสิทธิ์แล้วโหลดรายการแคมเปญโดยเรียงตามวันที่สร้างล่าสุด
  2. ตัวกรองมี 2 ตัว คือช่องค้นหาที่ยิงคำขอทันทีเมื่อพิมพ์ และตัวเลือกสถานะเปิด/ปิดใช้งาน ทั้งสองตัวจะรีเซ็ตกลับไปหน้าแรกของตารางเสมอ
  3. คอลัมน์ประกอบด้วย ลำดับ, ชื่อแคมเปญ (คลิกเพื่อเข้าไปแก้ไข), token, สถานะ, จำนวนการเข้าชม, จำนวนการติดตาม, อัตราการเปลี่ยนเป็นเพื่อน และวันที่สร้าง
  4. ปุ่มคำสั่งต่อแถวมี 3 ปุ่ม คือ ดูรายงาน, แก้ไข และลบ โดยการลบต้องยืนยันก่อนและแสดงผลลัพธ์ผ่านหน้าต่างสำเร็จหรือหน้าต่างล้มเหลว

หน้าฟอร์มสร้างและแก้ไข

  1. หน้าฟอร์มแยกโหมดจากพารามิเตอร์ id โดยไม่มี id คือสร้างใหม่ และมี id คือแก้ไข ทั้งสองโหมดใช้ตัวตรวจสิทธิ์ระดับ "ดูข้อมูล" ตัวเดียวกัน
  2. ระบบโหลดข้อมูลประกอบ 2 ชุด คือ รายการ merge tag จากโมดูลข้อความเทมเพลต (ใช้เป็นตัวเลือกคีย์คุณสมบัติ) และข้อมูลแคมเปญเดิมในกรณีแก้ไข
  3. ฟิลด์ในฟอร์มประกอบด้วย
    • ชื่อแคมเปญ (บังคับ)
    • สถานะ เป็นสวิตช์เปิด/ปิด โดยค่าเริ่มต้นในโหมดสร้างคือเปิดใช้งาน
    • token พร้อมปุ่มสร้างให้อัตโนมัติเป็นสตริง 16 ตัวอักษร ถ้าเว้นว่างไว้ระบบหลังบ้านจะสร้างให้เอง
    • คำอธิบาย
    • ตั้งค่าคุณสมบัติ เป็นรายการคู่คีย์-ค่าที่เพิ่มลบได้ โดยคีย์เลือกจากรายการ merge tag
    • คีย์คุณสมบัติอ้างอิง เป็นตัวเลือกจากรายการคุณสมบัติที่ตั้งค่าไว้ ใช้ระบุว่าจะเก็บรหัสอ้างอิงของลิงก์ย่อยไว้ที่ช่องใด
  4. เมื่อกดบันทึก ระบบจะเปิดหน้าต่างยืนยันก่อน จากนั้นจึงประกอบข้อมูลส่ง โดยแปลงรายการคู่คีย์-ค่าเป็นวัตถุเดียว ตัดคำนำหน้า custom. ออกจากคีย์ให้ตรงกับรูปแบบที่ระบบจัดเก็บ และแปลงสวิตช์สถานะเป็นข้อความ
  5. เมื่อเปิดแคมเปญเดิมขึ้นมาแก้ไข ระบบจะแปลงข้อมูลกลับด้านตรงข้าม คือคลี่วัตถุกลับเป็นรายการ และเติมคำนำหน้า custom. คืนให้กับคีย์ที่ไม่ใช่คุณสมบัติมาตรฐานของ LINE
  6. หากบันทึกไม่สำเร็จและเซิร์ฟเวอร์ส่งข้อผิดพลาดรายฟิลด์กลับมา ระบบจะแสดงข้อความใต้ฟิลด์ที่เกี่ยวข้องโดยตรง

รหัสอ้างอิงและลิงก์รายบุคคล

การ์ดรหัสอ้างอิงจะปรากฏเฉพาะในโหมดแก้ไข เพราะต้องมีรหัสแคมเปญอยู่ก่อน

  1. รูปแบบไฟล์ที่รองรับคือ CSV ที่มีรหัสอ้างอิงหนึ่งรายการต่อหนึ่งแถว หัวตารางจะมีหรือไม่มีก็ได้ โดยหน้าจอแสดงตัวอย่างรูปแบบไว้ให้
  2. ปุ่มดาวน์โหลดเทมเพลตสร้างไฟล์ตัวอย่างขึ้นในเบราว์เซอร์ทันทีโดยไม่ต้องเรียกเซิร์ฟเวอร์
  3. การอัปโหลดส่งไฟล์เข้าสู่ระบบเพื่อประมวลผลเบื้องหลัง เมื่อสำเร็จหน้าจอจะแจ้งสถานะและจำนวนรายการที่บันทึกได้ การตรวจความถูกต้องของเนื้อไฟล์ทำที่ฝั่งเซิร์ฟเวอร์ทั้งหมด
  4. หลังอัปโหลด ระบบจะดึงสถานะงานมาแสดง เมื่อสถานะเป็นเสร็จสิ้นแล้วจึงจะเปิดใช้งานปุ่มดาวน์โหลดลิงก์ พร้อมแสดงจำนวนรายการที่บันทึกสำเร็จและที่ถูกข้าม โดยระบบจะตรวจสถานะเฉพาะตอนเปิดหน้าและหลังอัปโหลด หากงานยังประมวลผลไม่เสร็จผู้ใช้ต้องรีเฟรชหน้าเอง
  5. ปุ่มดาวน์โหลดลิงก์จะดึงไฟล์ CSV ที่มีลิงก์ tracking ของแต่ละรหัสอ้างอิงมาบันทึกลงเครื่อง
  6. ลิงก์จริงที่แจกให้ผู้ใช้ปลายทางถูกประกอบขึ้นที่ฝั่งเซิร์ฟเวอร์ และส่งกลับมาในไฟล์นี้เท่านั้น ต่างจากโมดูลลิงก์รวมเนื้อหาหรือตัวสร้างเมนูที่ประกอบ URL เองในหน้าเว็บ หน้ารายการจึงแสดงเพียง token ไม่ใช่ URL เต็ม

หน้ารายงานผล

  1. หน้ารายงานอ่านรหัสแคมเปญจาก URL แล้วโหลดข้อมูล 2 ชุด คือข้อมูลแคมเปญ (ใช้ชื่อเป็นหัวข้อหน้า) และข้อมูลรายงานตามช่วงเวลาที่เลือก
  2. ตัวเลือกช่วงเวลาอยู่บนหัวการ์ดกราฟ และควบคุมทั้งกราฟและตารางผู้ใช้พร้อมกัน โดยค่าเริ่มต้นคือดูข้อมูลทั้งช่วง
  3. การ์ดสถิติ 4 ใบ แสดงจำนวนการเข้าชมทั้งหมด, จำนวนการติดตามทั้งหมด, อัตราการเปลี่ยนเป็นเพื่อน และจำนวนการเลิกติดตาม
  4. กราฟเส้นรายวัน วาดจากข้อมูลจริงที่เซิร์ฟเวอร์ส่งมาเป็นชุดข้อมูลตามวันที่ แสดง 2 เส้นคือการเข้าชมและการติดตาม หากไม่มีข้อมูลในช่วงที่เลือกจะแสดงข้อความแจ้งแทน
  5. ตารางผู้ใช้ แสดงรายชื่อผู้ที่เข้ามาผ่านแคมเปญนี้ พร้อมชื่อที่แสดง, LINE user ID, วันที่เข้าชม, วันที่ติดตาม, สถานะ, รหัสอ้างอิงของลิงก์ย่อยที่ผู้ใช้เข้ามา และประเภทผู้ใช้ โดยแบ่งหน้าแยกจากกราฟ

สรุปวงจรการใช้งาน

  1. ผู้ดูแลสร้างแคมเปญ ได้ token และตั้งค่าคุณสมบัติที่จะเขียนให้ผู้ใช้
  2. หากต้องการลิงก์แยกรายบุคคล ให้กลับเข้าโหมดแก้ไข อัปโหลดรายการรหัสอ้างอิง รอสถานะเสร็จสิ้น แล้วดาวน์โหลดไฟล์ลิงก์ไปแจก
  3. ผู้ใช้ปลายทางเปิดลิงก์ ระบบหลังบ้านบันทึกการเข้าชม และเขียนคุณสมบัติกับรหัสอ้างอิงให้ผู้ที่กดเพิ่มเพื่อน
  4. ผู้ดูแลกลับมาดูผลที่หน้ารายงาน เลือกช่วงวันที่ แล้วอ่านตัวเลขสรุป กราฟ และรายชื่อผู้ใช้
  5. เมื่อจบแคมเปญสามารถปิดใช้งานหรือลบแคมเปญออกได้

หน้าจอและองค์ประกอบหลัก

Route ทั้งสาม — หน้ารายการ (src/app/friend-track/page.tsx), หน้าฟอร์ม (.../form/page.tsx) และหน้ารายงาน (.../report/page.tsx) ทั้งหมดห่อด้วยตัวตรวจสิทธิ์เดียวกัน

ตัวควบคุมรายการ (src/components/friend-track/list/friend-track-list.container.tsx) — ดูแลการโหลดตาราง ตัวกรอง และการลบพร้อมหน้าต่างแสดงผลลัพธ์

ตัวควบคุมฟอร์ม (src/components/friend-track/form/friend-track-form.container.tsx) — ดูแลการโหลดและบันทึกข้อมูลแคมเปญ รวมถึงการแปลงรูปแบบคุณสมบัติทั้งขาเข้าและขาออก ส่วนตัวฟอร์ม (friend-track-form.tsx) ดูแล UI ทั้งหมดรวมถึงการ์ดรหัสอ้างอิง

ตัวควบคุมรายงาน (src/components/friend-track/report/friend-track-report.container.tsx) — ประกอบการ์ดสถิติ กราฟเส้น และตารางผู้ใช้เข้าด้วยกัน โดยใช้ตัวลงทะเบียนกราฟร่วมกับโมดูลแดชบอร์ด

เซอร์วิสกลาง (src/services/friend-track.service.ts) — ครอบคลุมการอ่านรายการ, อ่านรายตัว, สร้าง, แก้ไข, ลบ, ดึงรายงาน, อัปโหลดรหัสอ้างอิง, ตรวจสถานะงานอัปโหลด และดาวน์โหลดไฟล์ลิงก์

โครงสร้างข้อมูลสำคัญ — ข้อมูลแคมเปญเก็บชื่อ, token, คำอธิบาย, สถานะ, ชุดคุณสมบัติที่จะเขียน, คีย์คุณสมบัติอ้างอิง และตัวเลขสรุป ส่วนข้อมูลรายงานแบ่งเป็น 3 ส่วน คือตัวเลขสรุป, ชุดข้อมูลรายวันสำหรับกราฟ และรายการผู้ใช้พร้อมข้อมูลการแบ่งหน้า

จุดเชื่อมต่อกับฟีเจอร์อื่น

  • สิทธิ์การเข้าถึง — ใช้ subject friend-track โดยตรวจเฉพาะการกระทำ "ดูข้อมูล" ทุกหน้าใช้ตัวตรวจเดียวกัน รวมถึงหน้าฟอร์มที่สร้าง แก้ไข และอัปโหลดไฟล์ได้
  • ข้อความเทมเพลต (Template Message) — เป็นแหล่งของรายการ merge tag ที่ใช้เป็นตัวเลือกคีย์คุณสมบัติ หากบริการนี้ไม่ตอบสนอง ตัวเลือกจะว่าง
  • ตั้งค่าคุณสมบัติผู้ใช้ (Attribute Master) — เป็นแหล่งของตัวเลือกคีย์คุณสมบัติอ้างอิง โดยต้องสร้างคุณสมบัติไว้ก่อนจึงจะเลือกได้ ซึ่งหน้าจอมีคำแนะนำระบุไว้ชัดเจน
  • ระบบหลังบ้านและ webhook — การนับการเข้าชม การนับการติดตาม และการสร้างลิงก์ต่อรหัสอ้างอิง เป็นงานฝั่งเซิร์ฟเวอร์ทั้งหมด CMS ทำหน้าที่ตั้งค่าและอ่านผลเท่านั้น
  • โมดูลแดชบอร์ด — ใช้ตัวลงทะเบียนไลบรารีกราฟชุดเดียวกัน
  • คอมโพเนนต์ร่วมของ CMS — ส่วนหัวหน้า, หน้าต่างยืนยัน, หน้าต่างผลลัพธ์, สถานะกำลังโหลดแบบเต็มจอ และพื้นที่เลื่อนตาราง ใช้ชุดเดียวกับหน้าอื่นทั้งระบบ

รายละเอียดฝั่ง Backend (CMS API)

ฟีเจอร์นี้พาดผ่าน 3 ส่วนของ backend คือ โมดูลแคมเปญติดตามเพื่อน (internal/modules/friendtrack/), โมดูลค้นหาผู้ใช้จาก tracking log และกลไกสร้างลิงก์ติดตามที่ไม่มี HTTP route ของตัวเอง

สิทธิ์ที่ต้องมี

  • ทุก route ของ /api/friend-track ถูกครอบด้วย ModuleGate("friend-track") จริง ถ้าองค์กรไม่ได้เปิดโมดูลนี้ คำขอถูกปฏิเสธก่อนถึง handler
  • policy ที่ประกาศไว้แยกละเอียดกว่าที่หน้าเว็บตรวจ: การอ่านรายการเป็น readAll, การอ่านรายตัว/รายงาน/ดาวน์โหลด/ดูสถานะเป็น read, การสร้างเป็น create, การอัปโหลดรหัสอ้างอิงถูกจัดเป็น update (ไม่ใช่ create) และการลบเป็น delete — หน้าเว็บตรวจแค่การกระทำ "ดูข้อมูล" การแยกจึงมีผลจริงที่ฝั่งเซิร์ฟเวอร์เท่านั้น
  • ข้อสังเกต: policy ของโมดูล friend-track ยังถูกนำไปใช้เป็น metadata ของ GET /api/apps และ PUT /api/apps/:appId ด้วย ซึ่งยกมาตามระบบเดิม จึงเป็นความผูกพันที่ไม่ตรงกับชื่อโมดูลและควรระวังเมื่อจะปรับสิทธิ์

การอัปโหลดรหัสอ้างอิงจำนวนมาก

  • POST /api/friend-track/:id/refs/upload รับไฟล์แบบ multipart แล้วเขียนลงฐานข้อมูล ด้วยคำสั่ง SQL แบบ batch ที่มีเงื่อนไข "ถ้าซ้ำให้ข้าม" ออกแบบมารองรับ ref หลักพันถึงหลักหมื่นรายการ เช่น ref ต่อพนักงาน ต่อสาขา หรือต่อ QR แต่ละใบ
  • เพราะมีการกันซ้ำในตัว การอัปโหลดไฟล์เดิมซ้ำจึงไม่สร้างรายการซ้ำ และใช้เป็นวิธี "เติม ref เพิ่ม" ได้อย่างปลอดภัย
  • GET /api/friend-track/:id/refs/status ใช้ poll สถานะงานอัปโหลด (กำลังทำ / เสร็จ / ผิดพลาด) เพราะงานไม่ได้เสร็จภายในคำขอเดียว
  • GET /api/friend-track/:id/refs/download สตรีมไฟล์ CSV ของลิงก์และ ref ทั้งหมดลง response โดยตรง ไม่โหลดทั้งก้อนเข้าหน่วยความจำ

รายงานและการนับ

GET /api/friend-track/:id/report กรองตามช่วงเวลาและ ref ได้ ข้อควรรู้ด้านประสิทธิภาพ: การนับจำนวนผู้ใช้ในรายงานทำโดยดึงแถวทั้งหมดออกมาแล้วนับความยาว ไม่ได้ใช้คำสั่งนับของฐานข้อมูล ซึ่งยกพฤติกรรมมาจากระบบเดิมตรง ๆ ผลคือแคมเปญที่มีผู้ใช้จำนวนมากจะทำให้รายงานหน่วงและกินหน่วยความจำมากกว่าที่ควร

ใครเป็นคนบันทึกว่า "เพื่อนคนนี้มาจาก ref ไหน"

CMS API ไม่ได้เป็นผู้บันทึกเหตุการณ์นี้ — เมื่อมีคนกดลิงก์แล้วเพิ่มเพื่อน บริการ webhook เป็นฝ่ายรับ event จาก LINE แล้วเขียนลงตาราง friend_track_event โดยผูกกับแคมเปญและ ref ที่ใช้ CMS ทำหน้าที่ตั้งค่าและอ่านผลเท่านั้น ผลที่ตามมาคือถ้าบริการ webhook มีปัญหา ตัวเลขในรายงานจะขาดหายโดยที่หน้า CMS ไม่แสดงความผิดพลาดใด ๆ

ค้นหาผู้ใช้จาก tracking log

POST /api/tracking-line-users เป็น endpoint เดียวที่ใช้เจาะจากพฤติกรรมกลับมาเป็นรายชื่อคน (เช่น "ใครกดลิงก์นี้บ้าง") โดยรับรายการ tracking key แล้วค้นตาราง tracking_line_users และเชื่อมกลับไปที่ข้อมูลผู้ใช้ LINE

  • ขอบเขตข้อมูลอ่านจาก context ของ request จึงจำกัดอยู่ที่ OA ที่กำลังทำงานอยู่
  • endpoint นี้ผ่านแค่ JwtAuth ระดับ global ไม่มี ModuleGate ต่างจาก /api/friend-track
  • ผลลัพธ์ถูกส่งกลับตามที่ค้นได้โดยไม่แปลงรูป
  • ข้อควรระวัง: ถ้าคำขอไม่ได้ส่งรายการ tracking key มา หรือส่งมาผิดชนิด backend จะตอบเป็นสถานะ 500 พร้อมรหัสข้อผิดพลาดทั่วไป ไม่ใช่ 400 พร้อมข้อความบอกว่าอะไรผิด — พฤติกรรมนี้จงใจคงไว้ให้ตรงกับระบบเดิม ฝั่งเรียกจึงต้องตรวจ payload ให้ครบก่อนส่ง

ลิงก์ติดตามถูกสร้างอย่างไร

กลไกสร้างลิงก์ติดตามอยู่ในโมดูล internal/modules/tracking/ ซึ่ง ไม่เปิด HTTP route ใด ๆ เลย เป็นเพียงบริการภายในที่โมดูลริชเมนูและโมดูลส่งข้อความเรียกใช้ ประเด็นที่ควรรู้:

  • โหมดการทำงานเลือกด้วยตัวแปรสภาพแวดล้อม TRACKING_REDIRECT_MODE — โหมด builtin ใช้ token ที่ระบบเข้ารหัสเอง ส่วนค่าอื่น (ค่าเริ่มต้นคือโหมดเดิม) จะส่งต่อให้บริการ redirect ภายนอก
  • โหมด builtin ห่อข้อมูลไว้ในตัว token เองด้วยการเข้ารหัสแบบ AES-256-GCM แล้วเข้ารหัสเป็นข้อความ URL-safe ตัว token จึงระบุได้ว่ามาจากริชเมนูหรือจากฟอร์มเก็บข้อมูล โดยไม่ต้องค้นฐานข้อมูลก่อน
  • เมื่อผู้ใช้กดลิงก์ บริการ client-api เป็นฝ่ายถอดรหัส token บันทึกเหตุการณ์ลง tracking_line_users แล้วจึง redirect ไปยังปลายทาง
  • คำเตือนสำคัญ: ตัวเข้ารหัสฝั่ง CMS API กับตัวถอดรหัสฝั่ง client-api ถูกตรึงให้ตรงกัน ถ้าฝั่งใดฝั่งหนึ่งเปลี่ยนรูปแบบ token ลิงก์ที่ส่งออกไปแล้วทั้งหมดจะใช้ไม่ได้ทันที และไม่มีทางกู้คืนนอกจากออกลิงก์ใหม่
  • ลิงก์ของแคมเปญ (campaign) ใช้คนละเส้นทาง คือใช้บริการ redirect ที่ฝั่ง worker ไม่ได้ผ่านกลไก token นี้

ตารางที่เกี่ยวข้อง

friend_track_campaign, friend_track_event, tracking_token, tracking_line_users, line_user และ line_oa