บทความ
เรื่องราว ความรู้ และประสบการณ์จากการสร้างเว็บไซต์และ Web Application
PDPA เว็บไซต์ ทำ Cookie Consent ใน Next.js | KittiStackBlogทำเว็บไซต์PDPA เว็บไซต์ ทำ Cookie Consent ใน Next.js
สรุปว่าเว็บไซต์ต้องขอความยินยอมคุกกี้แบบไหนตาม PDPA แบนเนอร์ต้องมีปุ่มอะไร และโค้ด Next.js ที่ไม่ให้ Google Analytics ทำงานจนกว่าผู้ใช้จะกดยอมรับ
Kittipong C.
ทีมงาน KittiStack
October 27, 2026·5 min read
PDPA เว็บไซต์ และวิธีทำ Cookie Consent ใน Next.js
ตามหลัก PDPA เว็บไซต์ที่เก็บข้อมูลผู้เข้าชมผ่านคุกกี้ เช่น ใช้ Google Analytics หรือ Facebook Pixel ต้องขอความยินยอมก่อน ตามพ.ร.บ.คุ้มครองข้อมูลส่วนบุคคล พ.ศ. 2562 ส่วนคุกกี้ที่เว็บต้องใช้เพื่อให้ทำงานได้ เช่น คุกกี้ล็อกอินหรือตะกร้าสินค้า ไม่ต้องขอ แต่ต้องบอกในนโยบายคุกกี้
ปัญหาที่เจอบ่อยกับเว็บ Next.js คือมีแบนเนอร์ขึ้นมาก็จริง แต่ Google Analytics เริ่มเก็บข้อมูลตั้งแต่ก่อนผู้ใช้กดอะไร แบบนี้แบนเนอร์มีไว้ดูอย่างเดียว ด้านล่างจะแยกให้ดูว่าคุกกี้แบบไหนต้องขอ แบนเนอร์ต้องมีอะไร และโค้ดที่ทำให้ตัววัดผลรอจนผู้ใช้ยินยอมจริง
PDPA เว็บไซต์ต้องขอความยินยอมคุกกี้แบบไหน
วิธีแบ่งที่ใช้กันทั่วไปคือแบ่งตามหน้าที่ของคุกกี้ เว็บของ สคส. เอง ก็ให้ผู้ใช้เปิดปิดคุกกี้ได้ทีละประเภท ยกเว้นคุกกี้ที่จำเป็น
#Next.js#PDPA#Cookie Consent#Google Analytics
ตัวอย่าง
คุกกี้ที่จำเป็น | session ล็อกอิน, ตะกร้าสินค้า, ค่าที่จำว่าผู้ใช้เลือกอะไรในแบนเนอร์ | ไม่ต้อง แต่ต้องแจ้งในนโยบาย |
คุกกี้วิเคราะห์ | Google Analytics, Microsoft Clarity, Hotjar | ต้องขอ |
คุกกี้การตลาด | Facebook Pixel, Google Ads, TikTok Pixel | ต้องขอ |
คุกกี้ตั้งค่า | ภาษา ธีมมืดหรือสว่าง ที่ไม่จำเป็นต่อการใช้งาน | ขึ้นกับการใช้งาน ส่วนใหญ่ควรขอ |
ข้อนี้ใช้กับสคริปต์ของบุคคลที่สามด้วย ถ้าใส่ปุ่มแชตหรือวิดีโอ YouTube ที่วางคุกกี้ เจ้าของเว็บยังเป็นผู้ควบคุมข้อมูลที่ต้องขอความยินยอมเอง
แบนเนอร์คุกกี้ต้องมีอะไรบ้าง
มาตรา 19 ของ PDPA กำหนดให้การขอความยินยอมต้องแยกส่วนให้ชัดเจน อ่านเข้าใจง่าย และผู้ใช้ต้องถอนความยินยอมได้ง่ายเท่ากับตอนให้ เมื่อแปลงเป็นหน้าตาแบนเนอร์ จะได้ของที่ควรมีดังนี้
- ✦ข้อความสั้น ๆ บอกว่าใช้คุกกี้ทำอะไร พร้อมลิงก์ไปนโยบายคุกกี้หรือนโยบายความเป็นส่วนตัว
- ✦ปุ่ม "ยอมรับทั้งหมด" และปุ่ม "ปฏิเสธ" ที่หาเจอง่ายพอกัน ไม่ใช่ซ่อนปุ่มปฏิเสธไว้ในหน้าตั้งค่า
- ✦ปุ่ม "ตั้งค่า" ที่เปิดให้เลือกทีละประเภท
- ✦ทางกลับมาเปลี่ยนใจภายหลัง เช่น ลิงก์ "ตั้งค่าคุกกี้" ที่ footer ทุกหน้า
สิ่งที่ไม่ควรทำคือเขียนว่า "ใช้งานเว็บต่อถือว่ายอมรับคุกกี้" แล้วมีแค่ปุ่มปิด เพราะผู้ใช้ไม่มีทางปฏิเสธจริง และคุกกี้วิเคราะห์ก็ทำงานไปแล้ว
ทำ Cookie Consent ใน Next.js ให้ Analytics รอความยินยอมจริง
Google มีกลไกชื่อ Consent Mode v2 ที่ให้ตั้งค่าเริ่มต้นเป็น "ไม่ยินยอม" แล้วค่อยอัปเดตเมื่อผู้ใช้กดยอมรับ ในโหมดนี้แท็กของ Google จะไม่เขียนคุกกี้วิเคราะห์จนกว่าค่าจะเปลี่ยนเป็น granted
1. ตั้งค่าเริ่มต้นเป็น denied ก่อนโหลด gtag
ใส่สคริปต์นี้ใน app/layout.tsx ลำดับสำคัญมาก ต้องตั้งค่า consent ก่อนบรรทัด gtag('config') เสมอ
import Script from "next/script";
const GA_ID = process.env.NEXT_PUBLIC_GA_ID;
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="th">
<body>
{children}
<Script src={`https://www.googletagmanager.com/gtag/js?id=${GA_ID}`} strategy="afterInteractive" />
<Script id="ga-consent" strategy="afterInteractive">{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
var consent = 'denied';
try { consent = localStorage.getItem('cookie-consent') === 'granted' ? 'granted' : 'denied'; } catch (e) {}
gtag('consent', 'default', {
analytics_storage: consent,
ad_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied'
});
gtag('js', new Date());
gtag('config', '${GA_ID}');
`}</Script>
</body>
</html>
);
}
โค้ดนี้อ่านค่าที่ผู้ใช้เคยเลือกไว้จาก localStorage ถ้ายังไม่เคยเลือกหรือเคยปฏิเสธ ค่าจะเป็น denied ตั้งแต่ request แรก
2. แบนเนอร์ที่อัปเดตค่าเมื่อผู้ใช้เลือก
แบนเนอร์ต้องเป็น Client Component เพราะใช้ localStorage และปุ่มกด
"use client";
import { useEffect, useState } from "react";
declare global { interface Window { gtag?: (...args: unknown[]) => void } }
export function CookieBanner() {
const [open, setOpen] = useState(false);
useEffect(() => {
try { setOpen(!localStorage.getItem("cookie-consent")); } catch { setOpen(true); }
}, []);
function choose(value: "granted" | "denied") {
try { localStorage.setItem("cookie-consent", value); } catch {}
window.gtag?.("consent", "update", { analytics_storage: value });
setOpen(false);
}
if (!open) return null;
return (
<div role="dialog" aria-label="การตั้งค่าคุกกี้" className="fixed bottom-4 inset-x-4 rounded-xl border bg-white p-4 shadow">
<p>เว็บนี้ใช้คุกกี้วิเคราะห์เพื่อดูว่าหน้าไหนมีคนอ่าน อ่านรายละเอียดใน <a href="/privacy">นโยบายความเป็นส่วนตัว</a></p>
<div className="mt-3 flex gap-2">
<button onClick={() => choose("granted")}>ยอมรับทั้งหมด</button>
<button onClick={() => choose("denied")}>ปฏิเสธ</button>
</div>
</div>
);
}
ตัวอย่างนี้มีคุกกี้ต้องขอแค่ประเภทเดียว (วิเคราะห์) จึงใช้สองปุ่มพอ ถ้าเว็บมีทั้งวิเคราะห์และการตลาด ให้เพิ่มหน้าตั้งค่าที่เปิดปิดทีละประเภท แล้วส่งค่าแยกกัน เช่น ad_storage สำหรับโฆษณา
3. ให้ผู้ใช้เปลี่ยนใจได้
ใส่ปุ่ม "ตั้งค่าคุกกี้" ที่ footer แล้วให้ปุ่มนั้นลบค่าเดิมและเปิดแบนเนอร์อีกครั้ง ถ้าผู้ใช้เปลี่ยนจากยอมรับเป็นปฏิเสธ ให้เรียก gtag('consent', 'update', { analytics_storage: 'denied' }) ด้วย ไม่อย่างนั้นแท็กจะยังทำงานต่อจนกว่าจะรีเฟรชหน้า
4. ตรวจว่าใช้ได้จริง
เปิดหน้าเว็บในหน้าต่างไม่ระบุตัวตน แล้วดูแท็บ Application ของ DevTools ก่อนกดปุ่มใด ๆ ต้องไม่มีคุกกี้ชื่อขึ้นต้นด้วย _ga จากนั้นกดยอมรับ คุกกี้ _ga จึงควรเพิ่มขึ้นมา ถ้าเห็น _ga ตั้งแต่โหลดหน้าแรก แปลว่าลำดับสคริปต์ผิด
เขียนเองหรือใช้บริการสำเร็จรูป
เขียนเองเหมาะกับเว็บที่มีสคริปต์ติดตามไม่กี่ตัวและอยากคุมหน้าตาเอง เว็บที่มีแท็กหลายตัวผ่าน Google Tag Manager หรือมีทีมการตลาดเพิ่มสคริปต์บ่อย ใช้บริการแบบ Consent Management Platform จะง่ายกว่า บริการของไทยอย่าง Cookie Wow สแกนหาคุกกี้ในเว็บให้ บล็อกสคริปต์จนกว่าผู้ใช้ยินยอม และบันทึกการให้ความยินยอมไว้บนคลาวด์
ไม่ว่าเลือกแบบไหน ต้องมีหน้านโยบายความเป็นส่วนตัวที่บอกว่าเก็บข้อมูลอะไร ใช้ทำอะไร ส่งต่อให้ใคร และผู้ใช้ติดต่อขอใช้สิทธิ์ได้ทางไหน ถ้าเว็บกำลังจะทำใหม่ งาน รับทำเว็บไซต์บริษัท ของ KittiStack รวมแบนเนอร์คุกกี้และหน้านโยบายแบบนี้ไว้แล้ว
คำถามที่พบบ่อย
ถ้าเว็บใช้แต่คุกกี้ที่จำเป็นต่อการทำงาน ไม่ต้องขอความยินยอม แต่ควรมีนโยบายความเป็นส่วนตัวบอกว่าใช้คุกกี้อะไร ก่อนตัดสินใจให้เช็กว่าปลั๊กอิน แชต หรือวิดีโอที่ฝังไว้ไม่ได้วางคุกกี้ของบุคคลที่สาม
กฎหมายไม่ได้กำหนดสีหรือขนาด แต่หลักของมาตรา 19 คือการปฏิเสธหรือถอนความยินยอมต้องง่ายพอกับการให้ ปุ่มปฏิเสธที่ต้องกดเข้าไปหาอีกสองชั้นจึงเสี่ยงที่จะไม่ผ่านหลักนี้
ควรเก็บ เพราะผู้ควบคุมข้อมูลต้องพิสูจน์ได้ว่าได้รับความยินยอมจริง อย่างน้อยให้เก็บว่าผู้ใช้เลือกอะไร เมื่อไหร่ และเวอร์ชันของข้อความแบนเนอร์ที่เห็น การเก็บแค่ใน localStorage ใช้จำค่าได้ แต่ไม่ใช่หลักฐาน
เมื่อผู้ใช้ปฏิเสธ Analytics จะไม่เขียนคุกกี้ และรายงานจะเห็นข้อมูลน้อยลง ตัวเลขผู้เข้าชมใน GA4 จึงต่ำกว่าความจริงเสมอ ถ้าต้องการตัวเลขรวมแบบหยาบ ๆ ให้ดูจาก log ของโฮสติ้งหรือ Search Console ประกอบ
สรุป
เริ่มจากทำรายการสคริปต์ทุกตัวในเว็บ แยกว่าตัวไหนจำเป็นและตัวไหนต้องขอ จากนั้นตั้ง Consent Mode เป็น denied ก่อนโหลดแท็ก ทำแบนเนอร์ที่ปฏิเสธได้จริง และทดสอบด้วย DevTools ว่าไม่มีคุกกี้วิเคราะห์ก่อนกดยอมรับ ถ้ายังไม่แน่ใจเรื่องอื่นของการทำให้ Google เห็นเว็บ อ่านต่อได้ที่ Next.js SEO ทำยังไง
บทความนี้เป็นข้อมูลทั่วไป ไม่ใช่คำปรึกษาทางกฎหมาย ถ้าเว็บเก็บข้อมูลอ่อนไหว เช่น ข้อมูลสุขภาพ ควรปรึกษานักกฎหมายด้าน PDPA