ยอด Conversion เพิ่มเป็นสองเท่าข้ามคืน: เคสนับซ้ำที่ทำให้งบโฆษณาบิดเบือน

สรุปสั้น ๆ
ยอด Conversion ที่พุ่งขึ้นผิดปกติโดยไม่มียอดขายจริงรองรับ มักมาจากการนับซ้ำ ไม่ใช่ยอดขายที่ดีขึ้นจริง สาเหตุหลักคือขาด idempotency key ที่ทำให้ระบบรู้ว่าเหตุการณ์นี้เคยส่งไปแล้ว การแก้ที่ถูกจุดคือออกแบบ event ID ให้ไม่ซ้ำและผูกกับออเดอร์จริงเสมอ
แอดมินของร้านเครื่องใช้ไฟฟ้ารายหนึ่งทักมาถามผมด้วยน้ำเสียงตื่นเต้นปนสงสัยว่า ‘พี่ครับ วันนี้ Conversion ขึ้น 96 ทั้งที่เมื่อวานได้แค่ 48 ยอดขายดีขึ้นเท่าตัวจริงเหรอ’ ผมขอให้เขาส่งรายชื่อลูกค้าที่ปิดการขายมาเทียบ แล้วก็เจอสิ่งที่คาดไว้ตั้งแต่แรก — ออเดอร์เดิม 48 รายการ ถูกนับซ้ำเป็น 2 รอบพอดี
การนับซ้ำแบบนี้อันตรายกว่าที่คิด เพราะมันไม่ได้ทำให้แค่ ‘ตัวเลขดูดี’ แบบผิด ๆ เท่านั้น มันยังทำให้อัลกอริทึมโฆษณาคิดว่ากลุ่มเป้าหมายกลุ่มหนึ่งเปลี่ยนใจซื้อบ่อยกว่าความเป็นจริง แล้วเทงบไปหากลุ่มนั้นมากขึ้น ทั้งที่จริง ๆ คนกลุ่มนั้นซื้อแค่ครั้งเดียว
5 สาเหตุที่ทำให้ Conversion เดียวถูกนับซ้ำ
- ไม่มี idempotency key — ระบบไม่มีวิธีจำว่า event นี้เคยส่งไปแล้ว พอมีการ retry (เช่นเครือข่ายสะดุด) ก็ยิงซ้ำโดยไม่รู้ตัว
- Webhook จาก LINE ยิงมาซ้ำสองครั้งสำหรับเหตุการณ์เดียว — เป็นพฤติกรรมปกติของหลายระบบ webhook ที่จะส่งซ้ำถ้าไม่ได้รับการตอบรับเร็วพอ ฝั่งรับต้องรับมือเรื่องนี้เอง
- แอดมินกดยืนยันปิดการขายซ้ำในระบบ — เช่นกดปุ่มสองครั้งเพราะหน้าจอโหลดช้า ทำให้ระบบสร้าง event สองตัวจากการกระทำเดียว
- มีสอง integration ยิง event เดียวกันพร้อมกัน — เช่นทั้งระบบ CRM และระบบแชทบอทต่างก็ยิง conversion event ให้ออเดอร์เดียวกันโดยไม่รู้ว่าอีกฝั่งก็ยิงเหมือนกัน
- ไม่มี event ID ที่ผูกกับออเดอร์แบบตายตัว — ถ้า event ID เปลี่ยนไปทุกครั้งที่ยิง (เช่นใช้เวลาปัจจุบันเป็นส่วนหนึ่งของ ID) ปลายทางจะไม่มีทางรู้เลยว่านี่คือ event เดิมที่เคยเห็นแล้ว
หัวใจของการแก้ปัญหานี้คือ Deduplication Key
หลักการง่าย ๆ คือทุก event ที่ยิงออกไปต้องมี ID เฉพาะตัวที่คำนวณจากข้อมูลของออเดอร์นั้นเอง เช่นรหัสออเดอร์บวกกับประเภทเหตุการณ์ ไม่ใช่สุ่มหรือใช้เวลาปัจจุบัน เพราะถ้าใช้เวลาปัจจุบัน ทุกครั้งที่ retry ID ก็จะเปลี่ยนไปเรื่อย ๆ ทำให้ปลายทางไม่มีทางรู้ว่าซ้ำ
ถ้าอยากเข้าใจเรื่องนี้ลึกขึ้นว่า ID ที่ออกแบบผิดพลาดนำไปสู่ปัญหาแบบไหนได้บ้าง ลองอ่านเพิ่มเติมที่เรื่อง event ID ไม่ตรงกัน ซึ่งเป็นสาเหตุร่วมของทั้งปัญหานับซ้ำและปัญหายอดหาย
ขั้นตอนแก้ไขที่ใช้ได้จริง
- ตรวจสอบว่าระบบปัจจุบันมีการสร้าง event ID แบบไหน ถ้ายังใช้เวลาปัจจุบันหรือค่าสุ่ม ให้เปลี่ยนเป็นค่าที่คำนวณจากรหัสออเดอร์แทน
- เพิ่มการตรวจสอบฝั่งรับ (ก่อนยิงออกจริง) ว่า event ID นี้เคยถูกส่งไปแล้วหรือยัง ถ้าเคยแล้วให้ข้าม ไม่ต้องยิงซ้ำ
- ถ้ามีหลาย integration ที่อาจยิง event เดียวกัน ให้กำหนดให้มีจุดเดียวเป็นผู้รับผิดชอบส่งออกจริง จุดอื่นส่งแค่สัญญาณภายในไม่ใช่ยิงตรงไปปลายทางเอง
- ตั้งเวลาหน่วง (debounce) ในฝั่งแอดมิน เพื่อกันการกดปุ่มซ้ำเร็วเกินไปสร้าง event ซ้ำจากการกระทำเดียว
- ย้อนดูข้อมูลย้อนหลังเพื่อประเมินว่าซ้ำไปเท่าไหร่แล้ว แล้วแจ้งแก้ไขตัวเลขที่ผิดเพี้ยนไปกับทีมที่ใช้ข้อมูลนี้ตัดสินใจงบ ถ้าไม่แน่ใจว่าที่แก้ไปถูกจุดหรือยัง ให้เปิดtest event toolยืนยันซ้ำอีกครั้ง
ตัวอย่างตัวเลขก่อนและหลังแก้
| ช่วงเวลา | Conversion ที่ระบบนับ | ยอดปิดการขายจริง | ส่วนต่าง |
|---|---|---|---|
| ก่อนแก้ (สัปดาห์ที่มีบั๊ก) | 96 | 48 | +100% |
| หลังแก้ idempotency key | 49 | 48 | +2% |
สรุป
การนับซ้ำเป็นบั๊กที่อันตรายเพราะมันไม่ส่งเสียงเตือนตัวเอง ตัวเลขที่สูงขึ้นมักถูกตีความว่าเป็นข่าวดีก่อนเสมอ กว่าจะรู้ว่าซ้ำก็อาจผ่านไปหลายสัปดาห์แล้ว
idempotency คือรากฐานที่มองข้ามกันบ่อยที่สุดตอนออกแบบระบบส่ง event ทั้งที่เป็นเรื่องพื้นฐานที่ป้องกันปัญหาได้ตั้งแต่ต้นทาง
- ยอดที่พุ่งขึ้นแบบไม่มีเหตุผลรองรับ ควรตรวจสอบก่อนดีใจ ไม่ใช่หลังทีมงบใช้ตัวเลขไปแล้ว
- event ID ที่คำนวณจากรหัสออเดอร์ ป้องกันการนับซ้ำได้ดีกว่าค่าสุ่มหรือเวลาปัจจุบัน
- ถ้ามีหลาย integration ยิง event ควรมีจุดเดียวรับผิดชอบส่งออกจริง
- ทดสอบการยิงซ้ำด้วยมือก่อนใช้งานจริง เพื่อยืนยันว่าระบบป้องกันได้ผล
คำถามที่พบบ่อย
การนับซ้ำแบบนี้ทำให้เสียเงินโฆษณาโดยตรงไหม
ทางอ้อมมากกว่าทางตรง ตัวมันเองไม่ได้ทำให้จ่ายค่าโฆษณาแพงขึ้นทันที แต่ทำให้อัลกอริทึมเรียนรู้ผิด แล้วไปทุ่มงบให้กลุ่มเป้าหมายที่ดูเหมือนซื้อซ้ำบ่อย ทั้งที่จริงซื้อครั้งเดียว ผลคืองบถูกจัดสรรผิดทิศทางในระยะยาว
Idempotency key ต่างจาก event ID ทั่วไปตรงไหน
event ID ทั่วไปอาจเป็นค่าอะไรก็ได้ที่ไม่ซ้ำในทางเทคนิค แต่ idempotency key ต้องเป็นค่าที่คำนวณซ้ำได้จากข้อมูลเดิมเสมอ เช่นมาจากรหัสออเดอร์ ทำให้ต่อให้ retry กี่ครั้งค่าก็ยังเหมือนเดิม ปลายทางจึงรู้จักและข้ามซ้ำได้
ถ้าเจอว่านับซ้ำไปแล้วหลายสัปดาห์ ควรแจ้งแพลตฟอร์มโฆษณาให้แก้ตัวเลขย้อนหลังไหม
แพลตฟอร์มส่วนใหญ่ไม่มีกลไกให้ ‘ลบ’ conversion ที่นับไปแล้วย้อนหลัง สิ่งที่ทำได้คือแก้ไขระบบให้ถูกต้องจากจุดนี้ไปข้างหน้า แล้วอธิบายกับทีมว่าช่วงที่ผ่านมาตัวเลขคลาดเคลื่อนเท่าไหร่ เพื่อไม่ให้เอาไปตัดสินใจงบผิด
ปัญหานี้เกิดกับทุกแพลตฟอร์มพร้อมกันไหม หรือเกิดเฉพาะบางที่
ขึ้นอยู่กับว่า integration ไหนมีปัญหาการยิงซ้ำ ถ้าโค้ดต้นทางยิงซ้ำไปทุกปลายทางพร้อมกัน ก็จะเห็นปัญหาซ้ำในทุกแพลตฟอร์ม แต่ถ้าเป็นปัญหาเฉพาะ integration ตัวใดตัวหนึ่ง ก็จะเห็นซ้ำเฉพาะแพลตฟอร์มที่ integration นั้นเชื่อมอยู่
มีวิธีทดสอบไหมว่าระบบป้องกันการนับซ้ำได้ผลจริงก่อนใช้งานจริง
ลองยิง event เดียวกันซ้ำสองสามครั้งด้วยมือในสภาพแวดล้อมทดสอบ แล้วดูว่าปลายทางบันทึกเป็นกี่รายการ ถ้าออกแบบถูกต้องควรเห็นแค่รายการเดียวไม่ว่าจะยิงกี่รอบก็ตาม
บทความที่เกี่ยวข้อง


