ติดตามผู้เข้าชมเว็บไซต์แบบเรียลไทม์โดยไม่ต้องสมัครสมาชิก
ลูกค้าคนหนึ่งต้องการดูว่าใครกำลังอยู่บนเว็บไซต์ของพวกเขาแบบเรียลไทม์
พวกเขาชอบวิดเจ็ตของ Tidio แต่ไม่อยากจ่ายค่าสมัครสมาชิก
ความท้าทายมีอยู่สองส่วน:
- เว็บไซต์ใช้ WordPress บนโฮสติ้งที่แตกต่างกัน
- ผมไม่สามารถเพิ่ม Firebase เข้าไปในระบบ WordPress ได้โดยตรง
ผมจึงสร้างตัวติดตาม (tracker) ภายนอกโดยใช้ Firebase และนี่คือวิธีการทำงานของมัน
วิธีการแก้ไขปัญหา
ผมใช้แท็ก script เพียงแท็กเดียวในส่วน header ของ WordPress โดยสคริปต์นี้จะเชื่อมต่อไปยังโปรเจกต์ Firebase ที่แยกเป็นอิสระ
• Live Presence: ผมใช้ Firebase Realtime Database ร่วมกับฟังก์ชัน onDisconnect() ซึ่งจะลบผู้ใช้ออกจากรายการ "ออนไลน์" โดยอัตโนมัติเมื่อพวกเขาปิดแท็บหรือการเชื่อมต่อขาดหายไป
• Visitor History: ผมใช้ Netlify Function ในการเขียนข้อมูลลงใน Firestore ซึ่งช่วยให้สามารถทำ IP geolocation ฝั่งเซิร์ฟเวอร์ได้
• Security: ผมใช้ anonymous authentication โดยผู้เข้าชมจะสามารถเขียนข้อมูลลงใน session node ของตนเองได้เท่านั้น และมีเพียงแอดมินเท่านั้นที่สามารถอ่านรายการทั้งหมดได้
บั๊กที่น่าปวดหัว
การสร้างสิ่งนี้ไม่ได้ราบรื่นนัก ผมต้องเจอกับอุปสรรคทางเทคนิคที่สำคัญ 3 ประการ
1. กับดักการทำ Caching
ประวัติการเข้าชมแสดงผลเป็นศูนย์ ผมพบว่าสคริปต์ตัวติดตามมีนโยบายการทำ cache นานถึงหนึ่งปี ทำให้ผู้เข้าชมยังคงใช้สคริปต์เวอร์ชันเก่าอยู่
- วิธีแก้: ผมตั้งนโยบายการทำ cache สำหรับสคริปต์ตัวติดตามไว้ที่ 5 นาที
2. ข้อผิดพลาด CORS ปลอม
เบราว์เซอร์รายงานข้อผิดพลาด CORS ผมนึกว่ามีปัญหาเรื่องการทำ domain whitelist แต่เมื่อลองทดสอบด้วย curl แบบง่ายๆ พบว่าเซิร์ฟเวอร์ทำงานได้ปกติ
ความจริงกลับเป็นอีกอย่าง คือเซิร์ฟเวอร์กำลังล่ม (crashing)
ใน Node.js หากคุณใช้ status code 204 คุณไม่สามารถใช้สตริงว่าง (empty string) เป็น body ได้ คุณต้องใช้ null เท่านั้น สตริงว่างทำให้เกิดการ crash ก่อนที่ CORS headers จะถูกส่งออกไป เบราว์เซอร์จึงไม่เห็น headers และสันนิษฐานว่าเป็นปัญหา CORS
- วิธีแก้: เปลี่ยน response body จาก
''เป็นnull
3. ช่องว่างของข้อมูลที่หายไป
ตัวกรองสำหรับ "วันนี้" หรือ "7 วันที่ผ่านมา" ไม่แสดงผลอะไรเลย และผู้ใช้บางรายแสดงตำแหน่งที่ตั้งเป็น "Unknown" สิ่งนี้เกิดขึ้นเพราะผมคำนวณ timestamp และตำแหน่งที่ตั้งเฉพาะในการโหลดหน้าเว็บครั้งแรกเท่านั้น หากผู้ใช้มี session เก่าค้างอยู่ในเบราว์เซอร์ เซิร์ฟเวอร์จะพลาดเหตุการณ์ "start" ไป
- วิธีแก้: ผมทำให้การคำนวณเป็นแบบ idempotent โดยตอนนี้สคริปต์จะคำนวณค่าเหล่านี้ใหม่ในทุกๆ event
บทเรียนสำคัญ
• ข้อผิดพลาด CORS ในเบราว์เซอร์ไม่ได้หมายถึงปัญหาการตั้งค่าเสมอไป แต่มันอาจซ่อนการล่มของเซิร์ฟเวอร์อยู่ ดังนั้นควรตรวจสอบ server logs ของคุณเสมอ
• การทดสอบด้วย curl POST ไม่ได้เป็นการทดสอบเบราว์เซอร์ เพราะเบราว์เซอร์จะส่งคำขอ OPTIONS preflight ไปก่อนเสมอ การทดสอบของคุณต้องรวมส่วนนี้ด้วยเพื่อให้ได้ผลลัพธ์ที่ถูกต้อง
• ใช้ null สำหรับ HTTP status ที่ "ไม่มีเนื้อหา" เช่น 204 อย่าใช้สตริงว่าง
