จัดการแคมเปญ Broadcast
ภาพรวม
Campaign Management คือเครื่องมือที่ผู้ดูแล LINE OA ใช้ส่งข้อความออกไปหาเพื่อนใน OA โดยเลือกได้ว่าจะส่งหาทุกคน (Broadcast) หรือส่งเฉพาะกลุ่มเป้าหมายที่ระบุ (Multicast) และเลือกได้ว่าจะส่งทันที ตั้งเวลาส่งล่วงหน้า หรือเก็บเป็นฉบับร่างไว้ก่อน
จุดที่ควรเข้าใจตั้งแต่ต้นคือ แคมเปญไม่ได้สร้างเนื้อหาข้อความในตัวเอง แต่อ้างอิง Rich Message ที่ถูกสร้างและเปิดใช้งานไว้แล้วจากฟีเจอร์จัดการ Rich Message หน้าฟอร์มจะดึงเนื้อหามาแสดงตัวอย่างในกรอบแชทให้เห็นก่อนกดส่ง
นอกจากใช้ส่งข้อความ ฟีเจอร์นี้ยังเป็นหน้าดูผลลัพธ์ของแคมเปญที่ส่งไปแล้ว โดยแสดงตัวเลขสรุปการส่ง การอ่าน และการคลิก พร้อมรายละเอียดแยกรายปุ่มรายลิงก์ และเจาะลงไปดูรายชื่อผู้ใช้ที่อ่านหรือคลิกจริงได้
แคมเปญมี 4 สถานะ คือ ส่งแล้ว (sent) ตั้งเวลาไว้ (scheduled) ยกเลิก (cancel) และร่าง (draft) โดยหน้ารายการแยกเป็นแท็บตามสถานะเหล่านี้
Business Flow
1. หน้ารายการแคมเปญ
- เมื่อเปิดหน้า ระบบตรวจสิทธิ์การดูข้อมูลแคมเปญก่อน แล้วดึงข้อมูลสองชุดพร้อมกัน
- รายการตัวเลือกผู้รับสำหรับตัวกรอง โดยหากมีแคมเปญที่ส่งแบบ broadcast อยู่จริง ระบบจะเพิ่มตัวเลือก "เพื่อนทั้งหมดบน OA" ไว้บนสุดของรายการ แนวคิดคือไม่เสนอตัวเลือกที่ไม่มีข้อมูลรองรับ
- รายการแคมเปญ โดยเริ่มต้นที่แท็บ "ส่งแล้ว" เรียงจากใหม่ไปเก่า
- เงื่อนไขการค้นหาถูกบันทึกลง sessionStorage ทำให้เมื่อผู้ใช้กลับเข้ามาที่หน้านี้อีกครั้งจะเห็นตัวกรองเดิม
- การสลับแท็บสถานะจะรีเซ็ตตัวกรองทั้งชุดและตั้งลำดับการเรียงให้เหมาะกับแท็บนั้น
- แท็บส่งแล้วและตั้งเวลาไว้ เรียงตามวันที่ส่ง โดยแท็บตั้งเวลาไว้เรียงจากใกล้ที่สุดขึ้นก่อนเพื่อให้เห็นคิวที่กำลังจะถึง
- แท็บยกเลิกและร่าง เรียงตามวันที่แก้ไขล่าสุดจากใหม่ไปเก่า
- คอลัมน์วันที่เปลี่ยนความหมายตามแท็บด้วย คือเป็นวันที่ส่งในแท็บส่งแล้วและตั้งเวลาไว้ วันที่ยกเลิกในแท็บยกเลิก และวันที่แก้ไขล่าสุดในแท็บร่าง โดยกำกับไว้ว่าเป็นเวลาประเทศไทย
- แท็บส่งแล้วมีคอลัมน์เพิ่มแสดงจำนวนกิจกรรมทั้งหมด ซึ่งเรียงลำดับได้และคลิกเพื่อเข้าดูผลลัพธ์ของแคมเปญนั้น
- ตัวกรองมีสามช่อง คือ ค้นหาจากชื่อ เลือกผู้รับ และเลือกช่วงวันที่ ช่วงวันที่ที่กรอกจะถูกตีความเป็นเวลาประเทศไทยแล้วแปลงเป็นเวลามาตรฐานก่อนส่งไปยังเซิร์ฟเวอร์
- ปุ่มดำเนินการในแต่ละแถวเปลี่ยนตามสถานะของแคมเปญ
- ร่าง — แก้ไขและลบ
- ตั้งเวลาไว้ — ยกเลิก โดยต้องยืนยันผ่านกล่องข้อความก่อน
- ส่งแล้ว — ดูผลลัพธ์
- ทุกสถานะ — คัดลอกเพื่อสร้างแคมเปญใหม่จากต้นแบบเดิม
2. สร้างและแก้ไขแคมเปญ
- หน้าฟอร์มรองรับสี่โหมด คือ สร้างใหม่ แก้ไข คัดลอก และดูผลลัพธ์ โดยแยกจากพารามิเตอร์ใน URL
- ระบบโหลดข้อมูลประกอบให้พร้อมก่อน ได้แก่ รายการ Rich Message ที่เปิดใช้งานอยู่ และรายการกลุ่มเป้าหมาย ซึ่งค้นหาเพิ่มเติมได้แบบ debounce
- เลือกผู้รับ — เลือกระหว่างส่งหาเพื่อนทั้งหมดบน OA หรือส่งเฉพาะกลุ่มเป้าหมายที่ระบุ
- เลือกเนื้อหา — เลือก Rich Message จากรายการ เมื่อเลือกแล้วระบบจะแสดงตัวอย่างในกรอบแชททันที รวมถึงดึง Quick Reply ที่ผูกกับ Rich Message นั้นมาแสดงด้วย และสร้างภาพตัวอย่างจากวิดีโอให้อัตโนมัติหากยังไม่มี
- กฎเรื่อง merge tag — หากเลือกส่งแบบ broadcast ระบบจะกรอง Rich Message ที่มี merge tag ออกจากรายการให้เลือก เพราะการส่งหาทุกคนไม่มีข้อมูลรายบุคคลไปแทนค่าในข้อความได้ ส่วนการส่งแบบ multicast ที่เนื้อหามี merge tag ระบบจะเพิ่มตัวเลือกให้ระบุว่าจะข้ามผู้รับที่ข้อมูลไม่ครบหรือไม่
- เลือกวิธีส่ง — ส่งทันที ตั้งเวลา หรือเก็บเป็นร่าง
- กรณีตั้งเวลา — ระบบเติมวันเวลาให้อัตโนมัติเป็นปัจจุบันบวก 35 นาที แต่กฎการตรวจสอบจริงกำหนดว่าต้องห่างจากปัจจุบันอย่างน้อย 30 นาที ส่วนต่างห้านาทีคือช่วงเผื่อให้ผู้ใช้กรอกฟอร์มได้ทัน ระบบจะปิดตัวเลือกชั่วโมงและนาทีที่ผ่านมาแล้วหากเลือกเป็นวันนี้ และหากตรวจสอบไม่ผ่านจะแจ้งทั้งใต้ช่องเวลาและผ่านกล่องข้อความ
- เงื่อนไขการบันทึก — หากเก็บเป็นร่าง กรอกแค่ชื่อแคมเปญก็บันทึกได้ ทำให้ผู้ใช้ทยอยเตรียมงานได้ แต่หากเป็นการส่งจริงหรือตั้งเวลา ต้องกรอกชื่อ ผู้รับ เนื้อหา และวิธีส่งให้ครบ รวมถึงกลุ่มเป้าหมายเมื่อส่งแบบ multicast และวันเวลาเมื่อตั้งเวลา
- เมื่อกดบันทึก ระบบตรวจอีกชั้นว่าเวลาที่ตั้งไม่ใช่อดีต แล้วเปิดกล่องยืนยันที่ข้อความและปุ่มเปลี่ยนไปตามวิธีส่งที่เลือก
- เมื่อยืนยัน ระบบเรียก
POST /campaignสำหรับการสร้างและการคัดลอก หรือPUT /campaign/{id}สำหรับการแก้ไข หากเซิร์ฟเวอร์ระบุฟิลด์ที่ผิดพลาด ระบบจะแสดงข้อความรายฟิลด์
3. ดูผลลัพธ์ของแคมเปญที่ส่งแล้ว
- ในโหมดดูผลลัพธ์ ทุกช่องในฟอร์มถูกปิดการแก้ไข และเพิ่มคอลัมน์ข้อมูลการติดตามผลทางด้านขวา
- การ์ดสรุป 4 ใบ แสดงจำนวนที่ส่ง จำนวนที่เข้าถึง จำนวนผู้คลิกที่ไม่ซ้ำ และจำนวนคลิกทั้งหมด โดยการ์ดที่เกี่ยวกับการอ่านและการคลิกกดเข้าไปดูรายละเอียดได้
- ตารางแยกรายข้อความ — Rich Message หนึ่งชุดอาจมีหลายข้อความ แต่ละข้อความจะมีตารางของตัวเองพร้อมชื่อกำกับเป็น Message A, B, C ตามลำดับ โดยคอลัมน์ในตารางเปลี่ยนตามประเภทของข้อความ
- ข้อความตัวอักษรจะแจ้งว่าไม่สามารถติดตามการคลิกได้
- รูปภาพและวิดีโอใช้คอลัมน์จำนวนการดูทั้งหมดและจำนวนผู้ดูที่ไม่ซ้ำ
- รูปภาพที่มีพื้นที่กดได้ใช้คอลัมน์ตำแหน่ง ข้อมูล ประเภท จำนวนผู้คลิกที่ไม่ซ้ำ และจำนวนคลิกทั้งหมด
- ข้อความแบบ flex ใช้ชุดคอลัมน์เดียวกันแต่ไม่มีคอลัมน์ตำแหน่ง
- คอลัมน์ประเภทแปลค่าให้อ่านง่าย เช่น การสลับริชเมนู ลิงก์ ข้อความ และหมายเลขโทรศัพท์
- คลิกที่ตัวเลขในตารางหรือที่การ์ดสรุป จะเปิดแผงด้านข้างแสดงรายชื่อผู้ใช้ LINE ที่ทำกิจกรรมนั้นจริง พร้อมรูปโปรไฟล์ ชื่อ จำนวนครั้ง เวลาที่ทำครั้งแรกและครั้งล่าสุด และรองรับการแบ่งหน้า
หน้าจอและองค์ประกอบหลัก
หน้ารายการ
ตรรกะทั้งหมดของหน้ารายการรวมอยู่ที่ตัวควบคุม (src/components/campaign-management/list/campaign-management.container.tsx) ครอบคลุมการจัดการแท็บสถานะ ตัวกรอง การแบ่งหน้าและการเรียงลำดับ การยกเลิก และการลบ ส่วนตารางและฟอร์มตัวกรองเป็นคอมโพเนนต์แสดงผลแยกออกมา
หน้าฟอร์ม
หน้าฟอร์มแบ่งเป็นตัวควบคุมที่ดูแลการโหลดข้อมูล การยืนยัน และการบันทึก กับคอมโพเนนต์ฟอร์มที่รวมทั้งส่วนกรอกข้อมูล ส่วนแสดงตัวอย่างข้อความ และตารางผลลัพธ์ในโหมดดูผล
แผงรายชื่อผู้ใช้
แผงด้านข้างสำหรับดูรายชื่อผู้ใช้ที่อ่านหรือคลิกเป็นคอมโพเนนต์แยก โดยระบุเจาะจงได้ว่าเป็นปุ่มใดของข้อความใด ผ่านดัชนีที่อ้างอิงทั้งลำดับข้อความและลำดับปุ่มร่วมกัน
ปลายทาง API
| การทำงาน | ปลายทาง |
|---|---|
| รายการแคมเปญ | GET /campaign |
| ข้อมูลแคมเปญรายตัว | GET /campaign/{id} |
| ข้อมูลการติดตามผล | GET /campaign/campaign-tracking/{id} |
| รายชื่อผู้ใช้ที่อ่านหรือคลิก | GET /campaign/campaign-tracking/{id}/users |
| ตัวเลือกผู้รับสำหรับตัวกรอง | GET /campaign/recipients-dropdown |
| สร้างแคมเปญ | POST /campaign |
| แก้ไขหรือยกเลิกแคมเปญ | PUT /campaign/{id} |
| ลบแคมเปญร่าง | DELETE /campaign/{id} |
| รายการกลุ่มเป้าหมาย | GET /audiences |
| รายการ Rich Message | GET /rich-message/find-all-object |
| ข้อมูล Quick Reply สำหรับตัวอย่าง | GET /quick-reply/{id} |
จุดเชื่อมต่อกับฟีเจอร์อื่น
- จัดการ Rich Message — เป็น dependency บังคับ ต้องมี Rich Message ที่เปิดใช้งานอยู่ก่อนจึงจะสร้างแคมเปญได้
- กลุ่มเป้าหมาย — จำเป็นสำหรับการส่งแบบ multicast และคอลัมน์ผู้รับในตารางลิงก์กลับไปยังหน้ารายละเอียดของกลุ่มเป้าหมายนั้น
- Quick Reply — ใช้แบบอ่านอย่างเดียว เพื่อนำปุ่มตอบกลับที่ผูกกับ Rich Message มาแสดงในตัวอย่าง
- ปฏิทินวางแผนแคมเปญ — ใช้ข้อมูลชุดเดียวกันกับหน้านี้ และลิงก์กลับมาที่หน้าดูผลลัพธ์
- แดชบอร์ด — การ์ดกิจกรรมที่กำลังจะถึงบนแดชบอร์ดดึงแคมเปญที่ตั้งเวลาไว้จากโมดูลนี้
- สิทธิ์การเข้าถึง — โมดูล
campaignฝั่งเซิร์ฟเวอร์ปลดล็อกทั้งหน้านี้และปฏิทินวางแผนแคมเปญพร้อมกัน - ขอบเขตข้อมูล — ทุกคำขอถูกจำกัดขอบเขตอยู่ที่ LINE OA ที่ผู้ใช้เลือกไว้โดยอัตโนมัติ ผ่านข้อมูลที่แนบไปกับ token
รายละเอียดฝั่ง Backend (CMS API)
API ไม่ได้เป็นผู้ส่งข้อความ
ประเด็นสำคัญที่สุดของโมดูลนี้คือ cms-api ไม่ได้ยิงข้อความไปที่ LINE เอง เมื่อบันทึกแคมเปญ backend เพียงเขียนข้อมูลลงฐานข้อมูลแล้ว publish งานเข้า RabbitMQ ให้ worker เป็นผู้ส่งจริง คำขอจึงตอบกลับเร็วมากแม้จะส่งหาผู้รับจำนวนมหาศาล
ผลที่ตามมาซึ่งควรรู้: การกดส่งสำเร็จหมายถึง "รับงานเข้าคิวแล้ว" ไม่ใช่ "ส่งถึงผู้รับแล้ว" ถ้าข้อความไม่ถึงปลายทาง ปัญหาอาจอยู่ที่ worker หรือที่ LINE ไม่ใช่ที่ cms-api
คิวที่ระบบใช้แยกตามชนิดงาน
| กรณี | คิวที่ publish |
|---|---|
| ส่งหาเพื่อนทั้ง OA (broadcast) | line_broadcast_rich_message |
| ส่งเฉพาะกลุ่มเป้าหมาย (multicast) | line_multicast_rich_message |
| งานตั้งเวลาและงานประมวลผลรวม | process_campaign |
| การคลิกในแคมเปญที่ใช้เป็นทริกเกอร์ | campaign_click_trigger |
ข้อควรระวังสำหรับผู้พัฒนา: โครงสร้างข้อมูลที่ publish ถูกทำให้เหมือนกับระบบเวอร์ชันก่อนหน้าทุกไบต์ รวมถึงลำดับของคีย์ เพราะ worker ตัวเดิมยังอ่านคิวเดียวกันอยู่ การเปลี่ยนโครงสร้าง payload จะทำให้ worker ทำงานผิดพลาดทันที
กฎ merge tag ที่ backend ตรวจจริง
backend มีตัวตรวจว่าข้อความมี merge tag อยู่หรือไม่ ซึ่งเป็นตัวตัดสินว่าต้องส่งแบบ personalize รายคนหรือไม่ กฎที่ควรทราบคือ ต้องมีวงเล็บปีกกาคู่ปิดติดกันจริงจึงจะนับว่าเป็น merge tag เช่น รูปแบบอย่าง {{name}} จะถูกจับได้ แต่ข้อความที่พิมพ์วงเล็บไม่ครบจะไม่ถูกตรวจพบและจะถูกส่งออกไปตามตัวอักษร นี่คือเหตุผลที่หน้าเว็บกรอง Rich Message ที่มี merge tag ออกจากตัวเลือกเมื่อเลือกส่งแบบ broadcast
การติดตามผล
GET /api/campaign/campaign-tracking/:idคำนวณยอดสรุปด้วยการรวมข้อมูลระดับ SQL โดยตรง ไม่ได้ดึงข้อมูลดิบมานับในโค้ด จึงเร็วแม้แคมเปญมีผู้รับจำนวนมากGET /api/campaign/campaign-tracking/:id/usersรองรับการกรองด้วยประเภทกิจกรรม, URL ต้นทาง และลำดับของข้อความใน Rich Message พร้อมแบ่งหน้า — ตรงกับแผงด้านข้างที่เจาะดูรายชื่อผู้ใช้รายปุ่มรายลิงก์- ลิงก์ในแคมเปญใช้กลไกติดตามคนละแบบกับริชเมนู — แคมเปญแปลงลิงก์เป็น URL ติดตามผ่านบริการ redirect ฝั่ง worker ส่วนริชเมนูใช้ระบบลิงก์ติดตามแบบ token เข้าใจจุดนี้จะช่วยเวลาไล่ปัญหาตัวเลขคลิกไม่ตรง
สิทธิ์และการลบ
- ทุกเส้นทางของโมดูลนี้ถูกครอบด้วย ModuleGate ของโมดูล
campaignซึ่งเป็นการบังคับที่มีผลจริง ถ้าผู้ดูแลแพลตฟอร์มปิดโมดูลแคมเปญให้องค์กรใด ผู้ใช้ในองค์กรนั้นจะได้ 403 แม้เรียก API ตรง - ข้อมูลกำกับสิทธิ์รายการกระทำ (สร้าง แก้ไข ลบ) มีอยู่แต่ยังไม่บังคับใช้
DELETE /api/campaign/:idเป็น soft delete ส่วนการลบจริงมีเส้นทางแยกที่ต้องเป็น super admin และต้องส่งพารามิเตอร์ยืนยัน
ผลข้างเคียงและระบบที่เกี่ยวข้อง
- Redis cache — backend เก็บ cache ทั้งรายการและรายละเอียดแคมเปญ
- การอ้างอิงข้ามโมดูล — ตอนบันทึก backend เรียกใช้บริการจัดรูปแบบและตรวจสอบข้อความของ LINE ร่วมกับข้อมูล Rich Message และกลุ่มเป้าหมาย ดังนั้นการแก้ Rich Message หลังสร้างแคมเปญแล้วอาจกระทบเนื้อหาที่จะถูกส่งจริง
- การคลิกในแคมเปญเป็นแหล่งทริกเกอร์ได้ — เมื่อผู้รับคลิกลิงก์ ระบบสามารถ publish งานเข้าคิวทริกเกอร์ ทำให้กฎอัตโนมัติทำงานต่อได้