← กลับไปหน้าบทความ
ส่ง Conversion กลับ

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

02 ส.ค. 04:22 · อ่าน 1 นาที
ยอด 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 ไม่ตรงกัน ซึ่งเป็นสาเหตุร่วมของทั้งปัญหานับซ้ำและปัญหายอดหาย

ขั้นตอนแก้ไขที่ใช้ได้จริง

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

ตัวอย่างตัวเลขก่อนและหลังแก้

ช่วงเวลาConversion ที่ระบบนับยอดปิดการขายจริงส่วนต่าง
ก่อนแก้ (สัปดาห์ที่มีบั๊ก)9648+100%
หลังแก้ idempotency key4948+2%

สรุป

การนับซ้ำเป็นบั๊กที่อันตรายเพราะมันไม่ส่งเสียงเตือนตัวเอง ตัวเลขที่สูงขึ้นมักถูกตีความว่าเป็นข่าวดีก่อนเสมอ กว่าจะรู้ว่าซ้ำก็อาจผ่านไปหลายสัปดาห์แล้ว

idempotency คือรากฐานที่มองข้ามกันบ่อยที่สุดตอนออกแบบระบบส่ง event ทั้งที่เป็นเรื่องพื้นฐานที่ป้องกันปัญหาได้ตั้งแต่ต้นทาง

  • ยอดที่พุ่งขึ้นแบบไม่มีเหตุผลรองรับ ควรตรวจสอบก่อนดีใจ ไม่ใช่หลังทีมงบใช้ตัวเลขไปแล้ว
  • event ID ที่คำนวณจากรหัสออเดอร์ ป้องกันการนับซ้ำได้ดีกว่าค่าสุ่มหรือเวลาปัจจุบัน
  • ถ้ามีหลาย integration ยิง event ควรมีจุดเดียวรับผิดชอบส่งออกจริง
  • ทดสอบการยิงซ้ำด้วยมือก่อนใช้งานจริง เพื่อยืนยันว่าระบบป้องกันได้ผล

คำถามที่พบบ่อย

การนับซ้ำแบบนี้ทำให้เสียเงินโฆษณาโดยตรงไหม

ทางอ้อมมากกว่าทางตรง ตัวมันเองไม่ได้ทำให้จ่ายค่าโฆษณาแพงขึ้นทันที แต่ทำให้อัลกอริทึมเรียนรู้ผิด แล้วไปทุ่มงบให้กลุ่มเป้าหมายที่ดูเหมือนซื้อซ้ำบ่อย ทั้งที่จริงซื้อครั้งเดียว ผลคืองบถูกจัดสรรผิดทิศทางในระยะยาว

Idempotency key ต่างจาก event ID ทั่วไปตรงไหน

event ID ทั่วไปอาจเป็นค่าอะไรก็ได้ที่ไม่ซ้ำในทางเทคนิค แต่ idempotency key ต้องเป็นค่าที่คำนวณซ้ำได้จากข้อมูลเดิมเสมอ เช่นมาจากรหัสออเดอร์ ทำให้ต่อให้ retry กี่ครั้งค่าก็ยังเหมือนเดิม ปลายทางจึงรู้จักและข้ามซ้ำได้

ถ้าเจอว่านับซ้ำไปแล้วหลายสัปดาห์ ควรแจ้งแพลตฟอร์มโฆษณาให้แก้ตัวเลขย้อนหลังไหม

แพลตฟอร์มส่วนใหญ่ไม่มีกลไกให้ ‘ลบ’ conversion ที่นับไปแล้วย้อนหลัง สิ่งที่ทำได้คือแก้ไขระบบให้ถูกต้องจากจุดนี้ไปข้างหน้า แล้วอธิบายกับทีมว่าช่วงที่ผ่านมาตัวเลขคลาดเคลื่อนเท่าไหร่ เพื่อไม่ให้เอาไปตัดสินใจงบผิด

ปัญหานี้เกิดกับทุกแพลตฟอร์มพร้อมกันไหม หรือเกิดเฉพาะบางที่

ขึ้นอยู่กับว่า integration ไหนมีปัญหาการยิงซ้ำ ถ้าโค้ดต้นทางยิงซ้ำไปทุกปลายทางพร้อมกัน ก็จะเห็นปัญหาซ้ำในทุกแพลตฟอร์ม แต่ถ้าเป็นปัญหาเฉพาะ integration ตัวใดตัวหนึ่ง ก็จะเห็นซ้ำเฉพาะแพลตฟอร์มที่ integration นั้นเชื่อมอยู่

มีวิธีทดสอบไหมว่าระบบป้องกันการนับซ้ำได้ผลจริงก่อนใช้งานจริง

ลองยิง event เดียวกันซ้ำสองสามครั้งด้วยมือในสภาพแวดล้อมทดสอบ แล้วดูว่าปลายทางบันทึกเป็นกี่รายการ ถ้าออกแบบถูกต้องควรเห็นแค่รายการเดียวไม่ว่าจะยิงกี่รอบก็ตาม

อยากวัดผลโฆษณาเข้า LINE ให้ถึงยอดขาย?

ทดลองใช้ linli ฟรี 14 วัน ไม่ต้องใช้บัตรเครดิต

เริ่มทดลองใช้ฟรี

บทความที่เกี่ยวข้อง

คู่มือเริ่มต้น LINE Conversion Tracking ในไทย ตั้งแต่ติดตั้งจนวัดยอดขายจริง
คู่มือเริ่มต้น LINE Conversion Tracking ในไทย ตั้งแต่ติดตั้งจนวัดยอดขายจริง
สำหรับคนที่เพิ่งเริ่มทำ LINE Conversion Tracking บทความนี้รวมทุกขั้นตอนตั้งแต่นิยาม Funnel ติดตั้งระบบ เชื่อมแพลตฟอร์ม จนถึงวางแผนช่วงทดลองใช้ให้ตัดสินใจได้จริงก่อนหมด Trial
LINE Tracking กับ PDPA ธุรกิจไทยควรเก็บข้อมูลอย่างไรให้เหมาะสม
LINE Tracking กับ PDPA ธุรกิจไทยควรเก็บข้อมูลอย่างไรให้เหมาะสม
ระบบ Tracking ไม่ได้ทำให้ธุรกิจผ่าน PDPA โดยอัตโนมัติ บทความนี้อธิบายว่าธุรกิจยังต้องรับผิดชอบอะไรเองบ้าง ตั้งแต่ Legal Basis ไปจนถึงการจำกัดข้อมูลที่ส่งไปแพลตฟอร์มโฆษณา
วิธีติดตั้ง Tracking Link และ Tracking Script สำหรับปุ่ม LINE บนเว็บไซต์
วิธีติดตั้ง Tracking Link และ Tracking Script สำหรับปุ่ม LINE บนเว็บไซต์
ก่อนติดตั้ง Tracking Link หรือ Script บนปุ่ม LINE ต้องเตรียมอะไรบ้าง บทความนี้เล่าขั้นตอนจริงตั้งแต่สิทธิ์เข้าถึงเว็บ ไปจนถึง Test Journey ก่อนเปิดใช้งาน ไม่ใช่แค่ก็อปโค้ดไปวาง