การขอความยินยอมคุกกี้สำหรับ Next.js, Gatsby และ Static Site: คู่มือการเชื่อมต่อสำหรับนักพัฒนา

ปัญหาการขอความยินยอมบน Static Site

เฟรมเวิร์ก JavaScript สมัยใหม่อย่าง Next.js, Gatsby และ Nuxt.js ได้เปลี่ยนวิธีการสร้างและส่งมอบหน้าเว็บไปอย่างสิ้นเชิง หน้าเว็บจะถูก prerender ตอน build time หรือบนเซิร์ฟเวอร์ แล้วจึงถูกhydrate บนฝั่ง client สิ่งนี้สร้างความท้าทายเฉพาะสำหรับการขอความยินยอมคุกกี้: แบนเนอร์ขอความยินยอมต้องพร้อมก่อนที่สคริปต์ติดตามใด ๆ จะทำงาน แต่ตัวหน้าเพจอาจถูกเรนเดอร์และแคชไว้ที่ edge แล้ว

CMP แบบดั้งเดิมถูกออกแบบมาสำหรับหน้า PHP ที่เรนเดอร์บนเซิร์ฟเวอร์หรือหน้า HTML แบบง่าย ๆ ที่โหลดเอกสารจากบนลงล่างอย่างเป็นลำดับ ในโลกของเฟรมเวิร์กที่มี code splitting, lazy loading และการเรนเดอร์ฝั่งเซิร์ฟเวอร์แบบสตรีมมิง สมมติฐานเหล่านั้นใช้ไม่ได้อีกต่อไป การตั้งค่าการขอความยินยอมให้ถูกต้องในสภาพแวดล้อมเหล่านี้จำเป็นต้องเข้าใจกระบวนการเรนเดอร์ให้ดี

ทำไมเรื่องเวลา (Timing) ถึงสำคัญกว่าที่คิด

ในหน้า HTML ปกติ การวางสคริปต์ CMP ไว้ใน <head> ก่อนสคริปต์อื่น ๆ เป็นเรื่องตรงไปตรงมา แต่ใน Next.js App Router หรือ Gatsby สถานการณ์ซับซ้อนกว่านั้น:

หลักการสำคัญคือ: ต้องจัดการ consent ในระดับสคริปต์ ไม่ใช่ระดับคอมโพเนนต์ React component ที่เรนเดอร์แบนเนอร์ขอความยินยอมจะช้าเกินไป หากมันกลายเป็น interactive ได้ก็ต่อเมื่อการ hydrate เสร็จแล้วเท่านั้น

การเชื่อมต่อกับ Next.js App Router

Next.js 13+ ที่มาพร้อม App Router มีวิธีจัดการสคริปต์รูปแบบใหม่ วิธีที่แนะนำสำหรับการเชื่อมต่อระบบขอความยินยอมมีดังนี้:

ขั้นตอนที่ 1: โหลดสคริปต์ CMP ใน Root Layout

ใช้คอมโพเนนต์ Script ของ Next.js พร้อมกลยุทธ์ beforeInteractive ในไฟล์ layout.tsx ระดับ root วิธีนี้จะบอก Next.js ให้ inject สคริปต์เข้าไปในเอกสาร HTML แรกก่อนที่การ hydrate จะเริ่ม:

กลยุทธ์ beforeInteractive มีความสำคัญอย่างยิ่ง กลยุทธ์เริ่มต้น afterInteractive จะโหลดสคริปต์หลังจากการ hydrate ซึ่งช้าเกินไปสำหรับการขอความยินยอม ด้วย beforeInteractive สคริปต์ CMP จะถูกใส่ใน HTML ที่เรนเดอร์จากเซิร์ฟเวอร์และทำงานในขณะที่หน้าโหลด

ขั้นตอนที่ 2: ตั้งค่า Default Consent ก่อน Google Tag

ก่อนสคริปต์ Google Tag Manager หรือ gtag.js ให้ใส่ inline script ที่ตั้งค่าสถานะ consent เริ่มต้น วิธีนี้ทำให้มั่นใจได้ว่าแม้ GTM จะโหลดก่อนที่แบนเนอร์ CMP จะปรากฏ มันก็ยังเคารพค่าปฏิเสธเริ่มต้นเหล่านั้น:

inline script นี้ควรถูกวางไว้ใน <head> ของ root layout ก่อนสคริปต์ CMP และ GTM ใน Next.js คุณสามารถใช้แท็ก <script> ปกติภายใน element <head> ของ layout เพื่อจุดประสงค์นี้

ขั้นตอนที่ 3: จัดการการเปลี่ยนเส้นทาง (Route Changes)

ในการนำทางแบบ single-page application สคริปต์ CMP จะโหลดเพียงครั้งเดียว แต่การเปลี่ยน route จะไม่ทำให้หน้าโหลดใหม่ทั้งหน้า CMP ของคุณจึงต้องคงอยู่ตลอดการนำทางฝั่ง client FlexyConsent จัดการเรื่องนี้ให้อัตโนมัติ — เมื่อโหลดแล้ว มันจะยังคงทำงานอยู่ในทุกการเปลี่ยน route โดยไม่ต้อง initialize ใหม่

การเชื่อมต่อกับ Next.js Pages Router

สำหรับโปรเจกต์ที่ยังใช้ Pages Router วิธีการจะคล้ายกันแต่ใช้ _document.tsx แทน root layout ให้วางสคริปต์ CMP ไว้ในคอมโพเนนต์ <Head> ของ custom Document class กลยุทธ์ beforeInteractive ใช้งานได้แบบเดียวกันใน Pages Router

ความแตกต่างสำคัญคือ _document.tsx จะเรนเดอร์บนเซิร์ฟเวอร์เท่านั้น ดังนั้นลอจิกการขอความยินยอมใด ๆ ที่อยู่ในนี้จะถูกใส่ใน HTML แรกที่ถูกส่งออกไปอย่างแน่นอน

การเชื่อมต่อกับ Gatsby Static Site

Gatsby จะสร้าง HTML แบบ static เต็มรูปแบบตอน build time ไม่มีการเรนเดอร์ฝั่งเซิร์ฟเวอร์ในตอน request ซึ่งทำให้บางอย่างง่ายขึ้นแต่ก็ทำให้บางอย่างซับซ้อนขึ้น:

แนวทาง build-time ของ Gatsby ทำให้ทุกไฟล์ HTML บน CDN ของคุณมีสคริปต์ consent อยู่ด้วย ซึ่งจริง ๆ แล้วถือว่าเหมาะมาก — ไม่มีลอจิกฝั่งเซิร์ฟเวอร์ให้ล้มเหลวหรือแคชผิดพลาด

ประเด็นที่ต้องคำนึงถึงใน Nuxt.js

Nuxt.js (พื้นฐานคือ Vue) มีรูปแบบของตัวเอง ใน Nuxt 3 ให้ใช้ composable useHead หรือการตั้งค่า app head ใน nuxt.config.ts เพื่อเพิ่มสคริปต์ CMP แบบ global Nuxt รองรับออปชัน body: false (ซึ่งจะวางสคริปต์ใน head) และแอตทริบิวต์ async สำหรับการโหลดแบบไม่บล็อกการเรนเดอร์

สำหรับโหมด server-side rendering ของ Nuxt หลักการเดียวกันยังใช้ได้: สคริปต์ CMP ต้องอยู่ใน HTML ตอบกลับแรก ไม่ใช่ถูก inject แบบไดนามิกโดย Vue component หลังจาก mount แล้ว

การหลีกเลี่ยง Layout Shift

แบนเนอร์ขอความยินยอมมักเป็นตัวการของ Cumulative Layout Shift (CLS) ซึ่งเป็น Core Web Vital ที่มีผลต่ออันดับ SEO เมื่อแบนเนอร์โผล่ขึ้นมาหลังจากหน้าเรนเดอร์แล้ว มันจะดันเนื้อหาลงหรือซ้อนทับเนื้อหาอย่างไม่คาดคิด

กลยุทธ์เพื่อลด CLS จากแบนเนอร์ขอความยินยอม:

แนวทางที่ไม่ผูกกับเฟรมเวิร์กของ FlexyConsent

FlexyConsent ถูกออกแบบมาให้ทำงานร่วมกับเฟรมเวิร์กใดก็ได้ — หรือแม้แต่ไม่มีเฟรมเวิร์กเลย — โดยทำงานในระดับสคริปต์แทนระดับคอมโพเนนต์ เหตุผลที่เรื่องนี้สำคัญมีดังนี้:

เคล็ดลับสำหรับนักพัฒนา: วิธีทดสอบที่ง่ายที่สุดว่าคุณเชื่อมต่อ CMP ได้ถูกต้องหรือไม่ คือเปิดแท็บ Network ในเบราว์เซอร์ กรองด้วยโดเมนของ Google แล้วรีโหลดหน้า ห้ามมี request ไปยัง Google ใด ๆ เกิดขึ้นก่อนที่คำสั่งตั้งค่า consent เริ่มต้นจะปรากฏใน console หากมี แสดงว่า CMP ของคุณโหลดช้าเกินไป

แพ็กเกจฟรีของ FlexyConsent รองรับจำนวน pageview ไม่จำกัด และทำงานร่วมกับ Next.js, Gatsby, Nuxt, Astro, SvelteKit, Remix และ HTML ธรรมดา การเชื่อมต่อเหมือนกันทั้งหมด: ใช้เพียงแท็กสคริปต์เดียว วางให้ถูกที่

← บล็อก อ่านทั้งหมด →