← กลับไปหน้าบทความ
ขั้นสูง (MarTech)

เว็บแบบหน้าเดียวเปลี่ยนเนื้อหาแล้วแท็กไม่ยิงซ้ำ ตั้ง Trigger ยังไง

ทีมบรรณาธิการ linli01 พ.ย. 09:28อัปเดต 01 พ.ย. 09:28อ่าน 3 นาที
เว็บแบบหน้าเดียวเปลี่ยนเนื้อหาแล้วแท็กไม่ยิงซ้ำ ตั้ง Trigger ยังไง
บทความนี้จัดทำเพื่อความรู้ ชื่อธุรกิจ ตัวเลข หรือบทสนทนาที่ไม่มีแหล่งอ้างอิงกำกับเป็นกรณีตัวอย่างเพื่ออธิบายแนวคิด ดูรายละเอียดที่ นโยบายกองบรรณาธิการ

สรุปสั้น ๆ

เว็บ Single Page App เปลี่ยนหน้าด้วย History API โดยไม่โหลดเอกสารใหม่ trigger Page View ของ GTM จึงยิงเพียงครั้งแรกครั้งเดียว ทางแก้คือใช้ trigger History Change หรือให้แอป push dataLayer event เมื่อหน้าใหม่เรนเดอร์เสร็จ แล้วระวังกับดักสามข้อ คือยิงซ้ำสองรอบ ชื่อหน้าที่ยังเป็นของหน้าก่อน และการเปิด page changes ของ Enhanced Measurement ซ้อนกับ trigger ที่ทำเอง

ลองนึกถึงทีมโฆษณาของร้านขายเครื่องประดับที่เปิดรายงาน Pages and screens ใน GA4 แล้วเห็นว่าหน้าแรกกินยอดดูเกือบทั้งหมด หน้าสินค้ามียอดแค่หลักสิบ ทั้งที่ลูกค้าในแชทบอกว่าไล่ดูกันหลายชิ้นก่อนทัก เว็บนี้สร้างด้วย React และไม่มีการโหลดหน้าใหม่เลยตอนกดเมนู

สิ่งที่เกิดขึ้นคือ GTM รู้จักแค่การโหลดเอกสาร ส่วนแอปที่เปลี่ยนเนื้อหาด้วย JavaScript และแก้ URL ผ่าน history.pushState เบราว์เซอร์ไม่ได้ถือว่าเป็นหน้าใหม่ แท็กที่ผูกกับ Page View จึงยิงเพียงรอบเดียวตอนเข้าเว็บ ปุ่ม LINE ที่ถูกวาดใหม่ในแต่ละหน้าก็พลอยหลุดจากการติดตามไปด้วย

ทำไม Page View ยิงครั้งเดียว และดูอย่างไรว่าเว็บของคุณเป็นแบบนี้

trigger Page View ผูกกับเหตุการณ์ที่ GTM โหลดพร้อมเอกสารใหม่ ใน SPA เอกสารถูกโหลดครั้งเดียวและแอปสลับเนื้อหาข้างในเอง วิธีตรวจเร็วที่สุดคือเปิด Tag Assistant ของ GTM แล้วกดไล่ห้าหน้าบนเว็บ ถ้าแถบซ้ายของ Preview มี Container Loaded และ Window Loaded แค่ชุดเดียวไม่เพิ่มเลย นั่นคือสัญญาณว่าเป็น SPA

อีกวิธีคือดูใน GA4 ว่า views per session ใกล้ 1.0 ผิดปกติ หรือหน้าลึกแทบไม่มียอด ขณะที่ฝั่งแชทบอกว่าลูกค้าดูหลายหน้า เมื่อเห็นแบบนี้ปัญหาอยู่ที่ trigger ไม่ใช่ที่พฤติกรรมของลูกค้า

ทางเลือกสามทาง และจะเลือกทางไหน

ทางเลือกทำงานอย่างไรเหมาะเมื่อข้อจำกัด
trigger History ChangeGTM ฟังการเรียก pushState, replaceState, popstate และการเปลี่ยน hashแก้โค้ดเว็บไม่ได้ยิงซ้ำได้ และ page title อาจยังเป็นหน้าก่อน
Enhanced Measurement แบบ Page changesGA4 ส่ง page_view เองเมื่อประวัติเบราว์เซอร์เปลี่ยนใช้ GA4 อย่างเดียวและโครงเว็บไม่ซับซ้อนไม่ส่งต่อให้ Meta หรือ TikTok และซ้อนกับ trigger ที่ทำเองได้
dataLayer.push จากแอปโค้ดเว็บ push event พร้อม page_path และ page_title หลังเรนเดอร์เสร็จแก้โค้ดได้ ต้องการข้อมูลที่ตรงต้องให้นักพัฒนาทำและทดสอบ

ตั้ง History Change ให้ไม่ยิงเกินความจำเป็น

ถ้าแก้โค้ดเว็บไม่ได้ History Change คือทางที่เร็วที่สุด ผมตั้งตามลำดับนี้

  1. สร้าง trigger ชนิด History Change ตั้งชื่อให้รู้ว่าคือหน้าเสมือน เช่น HC - virtual page
  2. เปิด built-in variables กลุ่ม History ได้แก่ History Source, New History Fragment, Old History Fragment, New History State และ Old History State ไว้ใช้ตรวจใน Preview
  3. ดูใน Preview ว่าการเปลี่ยนหน้าหนึ่งครั้งมี History Change กี่ตัว ถ้าเห็นสองตัวติดกัน (pushState ตามด้วย replaceState) ให้เพิ่มเงื่อนไขกรองตามค่า History Source แต่ตรวจก่อนว่าเว็บไม่ได้ใช้ replaceState เปลี่ยนหน้าจริง
  4. สร้างแท็ก GA4 Event ชื่อ page_view ผูกกับ trigger นี้ ส่ง page_location เป็นตัวแปร Page URL ซึ่งอ่านค่า ณ เวลาที่ event เกิด จึงเป็น URL ของหน้าใหม่
  5. ปิด Page changes ใน Enhanced Measurement ของ data stream ถ้าใช้แท็กเอง ไม่งั้นจะได้ page_view สองใบต่อหนึ่งหน้า
  6. ไล่คลิกห้าหน้าใน Preview แล้วนับ page_view ต้องเท่ากับหนึ่งต่อหนึ่งหน้า และ page_location ต้องเป็นหน้าที่เปลี่ยนไป

กับดักที่ทำให้ตัวเลขดูถูกแต่ผิด

  • ยิงซ้ำ router บางตัวเรียก pushState แล้ว replaceState ต่อทันที หรือมี Enhanced Measurement เปิดซ้อนอีกชั้น ผลคือยอดดูหน้าเป็นสองเท่า ขั้นตอนตรวจ event ซ้ำดูได้ใน เรื่อง conversion ที่ถูกนับซ้ำ
  • page title เก่า ตอนที่ History Change เกิด แอปอาจยังไม่ได้อัปเดต document.title ทำให้ page_view ใหม่พก title ของหน้าก่อนไป ทางแก้ที่ตรงสุดคือให้แอป push event หลังอัปเดต title แล้ว
  • page_referrer ค้าง ตัวแปร Referrer ของ GTM อ่านจากเอกสารที่โหลดครั้งแรก หน้าเสมือนทุกหน้าจึงอ้างอิงจากภายนอกตลอด ให้ส่ง page_referrer เองด้วยค่า Old URL
  • UTM ไม่อยู่ใน URL ของหน้าถัดไป พารามิเตอร์ติดอยู่ที่หน้าแรกเท่านั้น ระบบเก็บค่าของเราจึงต้องไม่พึ่ง URL ปัจจุบัน ให้จดลงคุกกี้ตั้งแต่เข้าเว็บ ตามวิธีใน เก็บ UTM ก่อนเข้า LINE

ปุ่ม LINE ใน SPA ถูกวาดใหม่ทุกครั้งที่เปลี่ยนหน้า

trigger คลิกที่อ้าง id หรือ class ที่สร้างอัตโนมัติ เช่น btn-3f9a พังง่ายมาก เพราะเครื่องมือ build ที่สร้างชื่อ class แบบแฮชเปลี่ยนค่าทุกครั้งที่ deploy ปุ่มเดิมจึงหลุดจาก trigger เงียบ ๆ โดยไม่มีใครเห็นจนยอดตก

วิธีที่ผมขอให้นักพัฒนาทำคือใส่แอตทริบิวต์คงที่ เช่น data-cta='line' บนปุ่มทุกจุด แล้วให้ trigger ใช้ Click Element ที่ตรงกับ CSS selector นั้น ถ้าเป็นปุ่มที่ไม่ใช่ลิงก์ <a> trigger แบบ Just Links จะไม่ทำงาน ต้องใช้ All Elements หรือให้แอป push event เอง ซึ่งเป็นทางที่เสถียรที่สุด ดูรูปแบบ event ได้ที่ GTM custom event สำหรับ LINE และโครง dataLayer ใน dataLayer สำหรับ LINE conversion

สรุป

ถ้าแก้โค้ดเว็บได้ ให้ขอให้แอป push dataLayer event เมื่อหน้าเรนเดอร์เสร็จ แล้วใช้ History Change เป็นแผนสำรองเท่านั้น เหตุผลคือแอปรู้ว่าหน้าพร้อมแล้ว ส่วน GTM รู้แค่ว่า URL เปลี่ยน

ไม่ว่าเลือกทางไหน ให้นับ page_view ใน Preview ว่าเป็นหนึ่งต่อหนึ่งหน้า และให้ปุ่ม LINE มีแอตทริบิวต์คงที่ก่อนปล่อยทุกครั้ง

  • SPA ไม่โหลดเอกสารใหม่ จึงไม่มี Page View ให้ GTM ยิงซ้ำ
  • dataLayer.push จากแอปแม่นที่สุด History Change เป็นทางลัดที่ต้องตรวจเรื่องยิงซ้ำ
  • ปิด Enhanced Measurement Page changes เมื่อใช้ trigger ของตัวเอง
  • ปุ่ม LINE ต้องมีแอตทริบิวต์คงที่ เช่น data-cta
  • pixel ของ Meta และ TikTok ต้องสั่ง PageView เองเมื่อ route เปลี่ยน

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

เว็บ Next.js แบบ client-side routing ต้องทำอะไรเป็นพิเศษไหม

ต้องมีการส่ง page_view เมื่อ pathname เปลี่ยน ฝั่งนักพัฒนาควร push event เข้า dataLayer ทุกครั้งที่ route เปลี่ยนและเรนเดอร์เสร็จ ถ้าใช้ History Change แทน ให้ทดสอบเรื่องยิงซ้ำเป็นพิเศษ เพราะ router ตัวใหม่ ๆ เรียก replaceState บ่อย

Enhanced Measurement Page changes กับ History Change อันไหนดีกว่า

ถ้าใช้ GA4 อย่างเดียว Enhanced Measurement ตั้งง่ายกว่า แต่ถ้าต้องส่งหน้าเสมือนไป Meta หรือ TikTok ด้วย ต้องมี trigger หรือ dataLayer event ของตัวเอง และต้องปิด Page changes ไม่ให้ซ้อน

Meta pixel กับ TikTok pixel ต้องยิง PageView เองใน SPA ไหม

ต้อง โค้ดฐานของ pixel ยิง PageView ตอนโหลดเอกสารเท่านั้น เมื่อ route เปลี่ยนต้องสั่งเอง เช่น fbq('track', 'PageView') ของ Meta และ ttq.page() ของ TikTok ผ่านแท็กที่ผูกกับ trigger หน้าเสมือน

เว็บที่ใช้ hash เช่น /#/product ใช้ Page View ได้ไหม

Page View ใช้ไม่ได้ เพราะการเปลี่ยน hash ไม่โหลดเอกสารใหม่ ให้ใช้ History Change ซึ่งครอบคลุมการเปลี่ยน hash ด้วย แต่ควรตรวจว่ามียิงซ้ำหรือไม่

DebugView ขึ้น page_view สองครั้งต่อหนึ่งหน้า แปลว่าอะไร

ส่วนใหญ่แปลว่ามีสองแหล่งส่ง page_view ซ้อนกัน เช่น Enhanced Measurement กับแท็กที่สร้างเอง หรือ History Change ยิงสองรอบจาก router ให้เปิด Preview ดูว่าแท็กไหนยิงและปิดหนึ่งในนั้น

วัด Conversion LINE ทุกแบรนด์ รวมศูนย์ที่เดียว

องค์กรที่มีหลายแบรนด์ หลายสาขา หลาย LINE OA linli รวม Tracking และส่ง Conversion กลับทุกแพลตฟอร์ม พร้อม Custom Limit เริ่มฟรี 14 วัน

ติดต่อทีม Sales

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

ให้เซิร์ฟเวอร์เป็นคนเขียนคุกกี้แทน JavaScript ต่างกันตรงไหนและได้อะไรกลับมา

ให้เซิร์ฟเวอร์เป็นคนเขียนคุกกี้แทน JavaScript ต่างกันตรงไหนและได้อะไรกลับมา

คุกกี้ที่เซิร์ฟเวอร์เขียนผ่านหัว Set-Cookie อยู่ได้นานกว่าและสคริปต์อ่านไม่ได้ บทความนี้เทียบสองวิธี วิธีตั้งค่า และขอบเขตที่มันช่วยเก็บรหัสคลิกไม่ได้
ส่งข้อมูลลูกค้าไทยออกไปที่แพลตฟอร์มโฆษณาต่างประเทศ ต้องทำอะไรให้ถูกกฎ

ส่งข้อมูลลูกค้าไทยออกไปที่แพลตฟอร์มโฆษณาต่างประเทศ ต้องทำอะไรให้ถูกกฎ

ทุกครั้งที่ยิง CAPI ข้อมูลลูกค้าไทยเดินทางไปเซิร์ฟเวอร์ต่างประเทศ บทความนี้ไล่ว่ามาตรา 28 และ 29 หมายถึงอะไรกับทีมแอด และเอกสารอะไรที่ควรมีในมือ
ธุรกิจขนาดไหนต้องมีเจ้าหน้าที่คุ้มครองข้อมูล และถ้ายังไม่มีควรทำอะไรก่อน

ธุรกิจขนาดไหนต้องมีเจ้าหน้าที่คุ้มครองข้อมูล และถ้ายังไม่มีควรทำอะไรก่อน

ขนาดบริษัทไม่ใช่ตัวตัดสินว่าต้องมี DPO แต่ลักษณะข้อมูลและกิจกรรมหลักต่างหาก บทความนี้ไล่เกณฑ์มาตรา 41 และลำดับงานสำหรับธุรกิจที่ยังไม่มีคนรับหน้าที่นี้