{"id":31457,"date":"2024-01-22T11:03:21","date_gmt":"2024-01-22T17:03:21","guid":{"rendered":"https:\/\/wpengine.com\/builders\/?p=31457"},"modified":"2024-03-18T13:11:56","modified_gmt":"2024-03-18T18:11:56","slug":"cookie-policy-popups-in-headless-wp","status":"publish","type":"post","link":"https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/","title":{"rendered":"Cookie Policy Popups in headless WordPress with Next.js 14 and WPGraphQL \ud83c\udf6a"},"content":{"rendered":"\n<p>Cookie policies are guidelines and rules that govern how cookies are used on websites to respect user privacy and comply with legal regulations. In the context of headless WordPress, which involves a decoupled architecture where the frontend is separate from the WordPress backend, implementing cookie policies and a popup banner involves a few considerations and steps.<\/p>\n\n\n\n<p>In this article, we will take a look at how to implement cookie policy popups in headless using Next.js 13\/14 with two methods. The first one will only use the <code>cookies-next<\/code> npm package with full customization and WPGraphQL.&nbsp; The second will use a 3rd party service called Cookiebot.<\/p>\n\n\n\n<div class=\"wp-block-group has-polar-background-color has-background is-layout-flow wp-container-core-group-is-layout-7a03825d wp-block-group-is-layout-flow\" style=\"padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--40)\">\n<p class=\"has-large-font-size\"><strong>Table of Contents<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\" id=\"Prerequisites\">\n<li><a href=\"#prerequisites\">Prerequisites<\/a><\/li>\n\n\n\n<li><a href=\"#legal-compliances-and-cookie-usage\">Legal Compliances and Cookie Usage<\/a><\/li>\n\n\n\n<li><a href=\"#method1-wpgraphql-and-the-cookies-next-npm-package\">Method 1:&nbsp; WPGraphQL and The Cookies Next NPM Package<\/a><\/li>\n\n\n\n<li><a href=\"#create-the-declaration-and-policy-page-with-wpgraphql\">Create the Declaration and Policy Page with WPGraphQL<\/a><\/li>\n\n\n\n<li><a href=\"#method2-client-side-cookie-components-with-a-3rd-party-servivce\">Method 2: Client Side Cookie Components with a 3rd Party Service<\/a><\/li>\n\n\n\n<li><a href=\"#cookiebot\">Cookiebot<\/a><\/li>\n\n\n\n<li><a href=\"#cookiebot-scripts-in-nextjs14\">Cookiebot Scripts in Next.js 14<\/a><\/li>\n\n\n\n<li><a href=\"#set-the-consent-globally-in-nextjs\">Set the Consent Globally in Next.js<\/a><\/li>\n\n\n\n<li><a href=\"#testing-the-cookiebot-consent-banner\">Testing the Cookiebot Consent Banner<\/a><\/li>\n\n\n\n<li><a href=\"#create-the-declaration-and-privacy-policy-page\">Create the Declaration and Privacy Policy Page<\/a><\/li>\n\n\n\n<li><a href=\"#conclusion\">Conclusion<\/a><\/li>\n<\/ul>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"prerequisites\">Prerequisites<\/h2>\n\n\n\n<p>To benefit from this article, you will need to have a basic understanding of <a href=\"https:\/\/nextjs.org\/docs\">Next.js 14<\/a>, headless WordPress, <a href=\"https:\/\/www.wpgraphql.com\/\">WPGraphQL<\/a>, <a href=\"https:\/\/tailwindcss.com\/\">Tailwind styles<\/a>, and 3rd party script services.<\/p>\n\n\n\n<p>If you need a more basic tutorial, please reference <a href=\"https:\/\/wpengine.com\/builders\/next-js-13-and-wpgraphql-in-headless-wordpress\/\">my article on the subject matter here<\/a>.<br><\/p>\n\n\n\n<p>Before moving forward, we will be looking at the files in this example that I made here in<a href=\"https:\/\/github.com\/Fran-A-Dev\/cookie-policy-headlesswp\/tree\/main\"> my GitHub repo<\/a>.&nbsp; If you would rather spin up your own and just copy and paste the code blocks into yours, feel free to do so as well.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"legal-compliances-and-cookie-usage\">Legal Compliances and Cookie Usage<\/h2>\n\n\n\n<p><a href=\"https:\/\/secureprivacy.ai\/blog\/understanding-cookies-importance-of-cookie-compliance#:~:text=To%20comply%20with%20the%20GDPR,cookie%20preferences%20at%20any%20time.\">Laws like the EU&#8217;s General Data Protection Regulation (GDPR) and the California Consumer Privacy Act (CCPA)<\/a> have strict rules about cookie usage. They require clear consent from users before any non-essential cookies are stored on their devices.<\/p>\n\n\n\n<p>Websites must inform users about the cookies they use, what data they track, and obtain their consent. This is typically done through a cookie consent banner.<\/p>\n\n\n\n<p>There are essential cookies (necessary for website functionality) and non-essential cookies (like those for analytics and advertising). Only essential cookies can be set without explicit consent.<\/p>\n\n\n\n<p>Let\u2019s take a look at how users can consent with cookies and implement a cookie consent banner on our front-end Next.js 14 application.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"method1-wpgraphql-and-the-cookies-next-npm-package\">Method 1:&nbsp; WPGraphQL and The Cookies Next NPM Package<\/h2>\n\n\n\n<p>Let\u2019s take a look at how users can consent with cookies and implement a cookie consent banner on our front-end Next.js 14 application without a 3rd party service.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Client-Side Cookie Components&nbsp;<\/h3>\n\n\n\n<p>In this section, let\u2019s make a basic cookie consent banner that pops up when a user visits our site for the first time.&nbsp; This banner will block the user from interacting with the site until they accept the terms of usage, privacy policy, etc.&nbsp;<\/p>\n\n\n\n<p>I have a basic headless WordPress site on Next.js 14 already spun up that shows my first 5 blog posts.&nbsp; Let\u2019s take a look at the <code>app\/components\/CookieConsent.jsx<\/code> file:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-string\">\"use client\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { useState, useEffect } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { hasCookie, setCookie } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"cookies-next\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> Link <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/link\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">CookieConsent<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> &#91;showConsent, setShowConsent] = useState(<span class=\"hljs-literal\">true<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  useEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>    setShowConsent(hasCookie(<span class=\"hljs-string\">\"localConsent\"<\/span>));\n<\/span><\/span><span class='shcb-loc'><span>  }, &#91;]);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> acceptCookie = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>    setShowConsent(<span class=\"hljs-literal\">true<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>    setCookie(<span class=\"hljs-string\">\"localConsent\"<\/span>, <span class=\"hljs-string\">\"true\"<\/span>, {});\n<\/span><\/span><span class='shcb-loc'><span>  };\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (showConsent) {\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-literal\">null<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  }\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">return<\/span> (\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"fixed inset-0 bg-slate-700 bg-opacity-70 z-&#91;5000]\"<\/span>&gt;<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\" fixed-bottom-0 left-0 flex items-center justify-between px-4 py-8 bg-orange-400\"<\/span>&gt;<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"text-dark text-base mr-16\"<\/span>&gt;<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">          This site uses cookies to improve the UX. By using our site you<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">          consent to all the TOU in accordance with our{\" \"}<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Link<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"\/privacy\"<\/span>&gt;<\/span>Privacy Policy<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Link<\/span>&gt;<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">          <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"bg-blue-700 py-2 px-10 rounded \"<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">          <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{()<\/span> =&gt;<\/span> acceptCookie()}<\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        &gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">          Accept<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">  );<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">}<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>At the top of the file, we declare the <code>\u201cuse client\u201d<\/code> directive since we are going to be doing this on the client side.&nbsp; This is followed by imports that we will use in this file which are the <code>useState<\/code> and <code>useEffect<\/code> React hooks to manage state and lifecycle.&nbsp; The <code>hasCookie<\/code> and <code>setCookie<\/code> are functions we import from the <code>cookies-next<\/code> npm package we installed.&nbsp; As well as&nbsp;the <code>Link<\/code> component for client-side navigation from Next.js.<\/p>\n\n\n\n<p>After the import statements, we define the component and make it the default export of the module.&nbsp; We initialize the state variable <code>showConsent <\/code>with a default value of <code>true<\/code> which determines whether the consent banner should be displayed.<\/p>\n\n\n\n<p>Following that, we run the <code>useEffect<\/code> hook to perform the side effect to check for the presence of a cookie named <code>localConsent<\/code> when the component mounts.&nbsp; If the cookie is there, it sets <code>showConsent<\/code> to false which prevents the banner from popping up.<\/p>\n\n\n\n<p>Next, we define a function that will be called&nbsp;when the user clicks the <code>\u201cAccept\u201d<\/code> button on the banner.&nbsp; It sets <code>showConsent<\/code> to false to hide the banner and sets a cookie named <code>localConsent <\/code>to true indicating that consent has been given.<\/p>\n\n\n\n<p>Then, we have an if statement that says&nbsp;if <code>showConsent<\/code> is true, the component will render nothing and hide the banner.<\/p>\n\n\n\n<p>Lastly, the return statement renders the JSX and the actual banner on the screen with the <code>onClick<\/code> handler that accepts the cookie when clicked.<\/p>\n\n\n\n<p>To sum this up, the <code>CookieConsent<\/code> component uses local state and effect hooks to manage the display of a cookie consent banner based on the presence of a consent cookie. It provides a message about cookie usage and allows the user to accept the terms, which should hide the banner and set a cookie to remember the choice.<\/p>\n\n\n\n<p>When you visit <code>localhost:3000<\/code> after running the dev server, you should see this banner popup as a new user:<\/p>\n\n\n\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/2KHEafO5L0T448Pt-Kde0OVNBfFHMVZ_f6i7Yc_AywGJZ_GagQ5f_gTdjtHp5IN62Cx2Ss8sc0JkeQJAuN2noSc2NVRvUDJxmh-Emhqr4hD9LYkIAroTLz6K6WdDHKU1TEYiWW4p3LJl7AL9DS9C2t8\" width=\"624\" height=\"368\"><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"create-the-declaration-and-policy-page-with-wpgraphql\">Create the Declaration and Policy Page with WPGraphQL<\/h3>\n\n\n\n<div class=\"wp-block-group has-base-color has-text-color has-background has-link-color wp-elements-688844c5591b0d750f2228c71fe3f5ec has-global-padding is-layout-constrained wp-container-core-group-is-layout-c825ac28 wp-block-group-is-layout-constrained\" style=\"border-radius:12px;background-color:#180038;margin-bottom:var(--wp--preset--spacing--30);padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)\">\n<div class=\"wp-block-group alignwide is-content-justification-left is-layout-flex wp-container-core-group-is-layout-682063c7 wp-block-group-is-layout-flex\" style=\"padding-top:0;padding-right:0;padding-bottom:0;padding-left:0\">\n<div class=\"wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-e4830150 wp-block-group-is-layout-flex\">\n<div class=\"wp-block-outermost-icon-block\"><div class=\"icon-container\" style=\"width:38px\"><svg fill=\"none\" viewBox=\"0 0 38 30\" aria-label=\"Frost logo\"><path fill=\"currentColor\" fill-rule=\"evenodd\" d=\"M18.149.498c-.043.01-.16.025-.259.033-.406.03-.933.112-1.53.238-.205.043-.769.198-.98.269-.114.039-.574.207-.618.226l-.292.124c-.3.128-.74.346-1.01.502a4.92 4.92 0 0 1-.206.115 10.57 10.57 0 0 0-4.878 6.728c-.018.106-.035.118-.237.165-.17.039-.23.055-.54.147C3.36 10.302.453 13.9.037 18.401c-.045.49-.05 8.792-.006 9.065.18 1.094.97 1.87 2.052 2.012.375.049 4.136.05 4.527.002 1.185-.148 2.032-1.046 2.102-2.228.055-.925.614-1.62 1.403-1.745.29-.046.37-.05.528-.022.905.158 1.437.76 1.5 1.7.083 1.249.888 2.135 2.084 2.294.363.048 4.162.048 4.518 0 .633-.086 1.262-.421 1.616-.862l.124-.154c.13-.156.29-.575.341-.885.046-.277.047-8.617.002-8.907-.183-1.17-1.208-1.979-2.505-1.979-.386 0-1.057-.13-1.593-.306a5.82 5.82 0 0 1-3.868-4.496c-.16-.907-.112-1.586.187-2.655.417-1.494 1.717-2.941 3.22-3.585l.158-.068c.28-.121.809-.268 1.214-.336a5.03 5.03 0 0 1 1.98.042c2.288.53 3.911 2.078 4.476 4.272.198.768.189.427.19 7.436.002 3.432.012 6.28.023 6.399.304 3.24 2.565 5.63 5.713 6.037.829.107 1.116.107 1.8-.001 2.037-.322 3.807-1.829 4.698-4.001l.046-.112c.148-.36.347-1.107.407-1.53.119-.823.073-1.372-.15-1.817-.255-.508-.802-.924-1.493-1.137-.253-.078-.998-.08-1.2-.005-.026.01-.11.037-.183.06-.666.202-1.24.854-1.493 1.696-.03.101-.093.523-.093.63 0 .044-.02.162-.046.26-.44 1.724-2.917 1.715-3.316-.013-.03-.128-.034-.905-.034-6.275 0-6.296-.005-6.684-.089-7.276a11.333 11.333 0 0 0-.114-.742c-.012-.05-.042-.186-.066-.304-.734-3.596-3.431-6.625-6.951-7.805a9.125 9.125 0 0 0-.855-.246 7.503 7.503 0 0 0-.888-.179 18.617 18.617 0 0 0-.877-.117c-.28-.033-.874-.046-.977-.02Zm-.047 8.132c-1.224.212-1.998 1.382-1.8 2.72.027.186.034.213.115.462.554 1.717 3.03 1.998 3.992.452.055-.088.1-.165.1-.172 0-.006.025-.064.056-.128.131-.27.214-.68.214-1.052 0-1.52-1.194-2.539-2.677-2.282Zm-9.55 5.116c.577 2.153 2.094 4.3 3.988 5.648.78.554 1.328.849 2.38 1.28.077.031.556.195.675.23l.247.07.236.069.101.03.006 1.66c.006 1.695.002 1.779-.078 1.615-.772-1.58-2.366-2.836-4.134-3.256-.626-.149-.883-.178-1.552-.178-2.132.001-4.114 1.027-5.234 2.711-.17.254-.36.57-.412.686-.101.22-.1.256-.1-2.611 0-3 .005-3.148.129-3.748a5.873 5.873 0 0 1 1.94-3.294 5.92 5.92 0 0 1 1.518-.927c.222-.091.262-.09.29.015Z\" clip-rule=\"evenodd\"><\/path><\/svg><\/div><\/div>\n\n\n\n<p class=\"has-large-font-size\" style=\"font-style:normal;font-weight:800;letter-spacing:-1px\">WPGraphQL<\/p>\n<\/div>\n\n\n\n<p class=\"has-small-font-size wp-container-content-c86e52ed\" style=\"line-height:1.5\">An extendable GraphQL <br>schema &amp; API for WordPress.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-horizontal is-content-justification-center is-nowrap is-layout-flex wp-container-core-buttons-is-layout-3bdbf2e2 wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button is-style-outline-base\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/wpeng.in\/wpgraphql-builders\/\" style=\"border-radius:99px;padding-top:10px;padding-right:24px;padding-bottom:10px;padding-left:24px\" target=\"_blank\" rel=\"noreferrer noopener\">Download<\/a><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<p>Now, let\u2019s get stoked and take a look at using WPGraphQL to get the Policy Page data from WordPress into Next.js.&nbsp; Go to <code>app\/pricvacy-policywp\/page.jsx:<\/code><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { Suspense } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> Loading <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/loading\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">getPage<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> query = <span class=\"hljs-string\">`<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">    query GetPrivacyPolicyPage {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      page(id: \"\/privacy-policy\/\", idType: URI) {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        title<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        content<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">    }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">  `<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> res = <span class=\"hljs-keyword\">await<\/span> fetch(\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-string\">`<span class=\"hljs-subst\">${process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT}<\/span>?query=<span class=\"hljs-subst\">${<span class=\"hljs-built_in\">encodeURIComponent<\/span>(<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\"><span class=\"hljs-subst\">      query<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\"><span class=\"hljs-subst\">    )}<\/span>`<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>    {\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-attr\">method<\/span>: <span class=\"hljs-string\">\"GET\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-attr\">headers<\/span>: {\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-string\">\"Content-Type\"<\/span>: <span class=\"hljs-string\">\"application\/json\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>      },\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-attr\">cache<\/span>: <span class=\"hljs-string\">\"no-store\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>  );\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> responseBody = <span class=\"hljs-keyword\">await<\/span> res.json();\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (responseBody &amp;&amp; responseBody.data &amp;&amp; responseBody.data.page) {\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">return<\/span> responseBody.data.page;\n<\/span><\/span><span class='shcb-loc'><span>  } <span class=\"hljs-keyword\">else<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Error<\/span>(<span class=\"hljs-string\">\"Failed to fetch the privacy policy page\"<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>  }\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">PrivacyPolicy<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> page = <span class=\"hljs-keyword\">await<\/span> getPage();\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">return<\/span> (\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main<\/span>&gt;<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">nav<\/span>&gt;<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>{page.title}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">nav<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Suspense<\/span> <span class=\"hljs-attr\">fallback<\/span>=<span class=\"hljs-string\">{<\/span>&lt;<span class=\"hljs-attr\">Loading<\/span> \/&gt;<\/span>}&gt;<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"card\"<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span> <span class=\"hljs-attr\">dangerouslySetInnerHTML<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">__html:<\/span> <span class=\"hljs-attr\">page.content<\/span> }} \/&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Suspense<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">  );<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">}<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>We have a server component with our imports <code>Suspense<\/code> and <code>Loading<\/code>.&nbsp; <code>Suspense<\/code> comes from React and allows other components to wait for something before rendering.&nbsp; It handles the loading state of async operations like data fetching.&nbsp; <code>Loading<\/code> is our custom component that serves as the placeholder to let the user know an operation is in progress.<\/p>\n\n\n\n<p>Following that, we have an async function that defines the WPGraphQL query to fetch the title and content of a page with the <code>URI \u201c\/privacy-policy\/\u201d<\/code> hard coded since this is the only page we want to route to.<\/p>\n\n\n\n<p>We use the fetch API to make a GET request to the WPGraphQL endpoint in our environment variable.&nbsp; The query is URL encoded to ensure it&#8217;s transmitted correctly over HTTP.<\/p>\n\n\n\n<p>After the request, the JSON is parsed and checks if the data is present.<\/p>\n\n\n\n<p>Then we have an async component called <code>getPage<\/code> that fetches the data by calling <code>getPage<\/code> when rendered with some basic error handling to throw an error if the data is not present.<\/p>\n\n\n\n<p>&nbsp;Then we return it with the JSX and its format on the page.&nbsp; You should see this when you visit <code>localhost:3000\/privacy-policywp<\/code> after running the dev server:<\/p>\n\n\n\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/9ax74fAJMptE0qxjuXj1rsMZ_BlZf4EISUdQawu4qrFIr0pqMYOywYcFX_D2s30BvwdU5rhJ6zN8ho98EKeTAryJ7sC_XPKJkv9F4XYGXJbk05fybdDXLH-XysI5MeVFdW2SOySg6SS-j0M-fISOmKM\" width=\"624\" height=\"373\"><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Things to Consider When Implementing Without a 3rd Party Service<\/h3>\n\n\n\n<p>Choosing this method does give you full control&nbsp;and customization on creating your banner and policy page with no cost for a 3rd party service.&nbsp; However, you do have a bit more complexity in keeping up with compliance, testing the functionality, and no auto cookie scanning.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"method2-client-side-cookie-components-with-a-3rd-party-servivce\">Method 2: Client-Side Cookie Components with a 3rd Party Service<\/h2>\n\n\n\n<p>In this section, let&#8217;s make a cookie consent banner in our Next.js 14 app and offload it to a 3rd party service called Cookiebot.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"cookiebot\">Cookiebot<\/h3>\n\n\n\n<p><a href=\"https:\/\/www.cookiebot.com\/\">Cookiebot is a 3rd party service that supports website compliance<\/a> with privacy laws like the GDPR, ePR, and CCPA. It offers an automated platform that can handle user consent, cookie monitoring, and cookie control. Cookiebot enhances websites by providing a consent banner and tracking technology that informs visitors about the use of cookies, secures their consent, and honors their privacy preferences.<\/p>\n\n\n\n<p>By integrating with our headless website, it automatically scans and tracks all cookies and similar tracking technologies in use, providing detailed reports and ensuring that the website&#8217;s use of such technologies remains transparent and compliant with legislation.&nbsp;<\/p>\n\n\n\n<p>It also helps in maintaining an updated cookie policy and declaration, automatically reflecting any changes in the use of cookies on the website.&nbsp;&nbsp;<\/p>\n\n\n\n<p>When using this approach, a few factors to consider are the cost of the service, limited customization options, and integration complexity.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"cookiebot-scripts-in-nextjs14\">Cookiebot Scripts in Next.js 14<\/h3>\n\n\n\n<p>Let\u2019s take a look at the files and scripts we will need to make this work in our application.&nbsp;<em> (Just a note, I have already created a free-tier Cookiebot account.&nbsp; If you are following along step-by-step, please do so before moving forward)&nbsp;<\/em><\/p>\n\n\n\n<p>In your Cookiebot Admin UI, go to <em><code>Dashboard &gt; Configuration<\/code><\/em> and you should see this screen:<\/p>\n\n\n\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/EJpI59o12Yq0ToXAj3DKTIhYliYSCESkArCExX-W6tKNSbFS3ML7OeS9REXQyXsZGn7v20tUDdtCXx-RtNf_CVL8v4PW2GPe3AOhACTb0SKMGscED-9pve61VLP5ZEviHnQrhJygAaLBHM4HGe3eqUU\" width=\"624\" height=\"297\"><\/p>\n\n\n\n<p>This allows you to set up the UI of the banner.&nbsp; We will use the default setting to show on our Next.js front end in this example.<br><\/p>\n\n\n\n<p>The next page you will need to navigate to is <em><code>Dashboard &gt; Script Embeds<\/code><\/em>.&nbsp; You should see this page:<\/p>\n\n\n\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/OxbuTNaAScDkQpDADb086Bc-kX3BSv11rg8B36ukObmejpKuPkU2V-YsoZMhMPm3Lbn1pYPbHKZdF3BaUYiFewgB0pfMqYENlKLjBJIxNKvmGsTj4fqpckeS33N8-SL3hSYe7QiA0NuLr3aPmF6LxKY\" width=\"624\" height=\"305\"><\/p>\n\n\n\n<p>We will need both script tags to embed in our Next.js 14 components.<\/p>\n\n\n\n<p>Now, let&#8217;s take a look at our first component that dynamically inserts our Cookiebot script into our site at <code>app\/components\/CookieBotConsent.jsx<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-string\">\"use client\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { useEffect } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> CookieConsent = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  useEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">const<\/span> cmpScript = <span class=\"hljs-built_in\">document<\/span>.createElement(<span class=\"hljs-string\">\"script\"<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>    cmpScript.id = <span class=\"hljs-string\">\"Cookiebot\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>    cmpScript.src = <span class=\"hljs-string\">\"https:\/\/consent.cookiebot.com\/uc.js\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>    cmpScript.setAttribute(<span class=\"hljs-string\">\"data-cbid\"<\/span>, <span class=\"hljs-string\">\"your-cookiebot-id\"<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>    cmpScript.setAttribute(<span class=\"hljs-string\">\"type\"<\/span>, <span class=\"hljs-string\">\"text\/javascript\"<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>    cmpScript.setAttribute(<span class=\"hljs-string\">\"async\"<\/span>, <span class=\"hljs-string\">\"true\"<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>    cmpScript.setAttribute(<span class=\"hljs-string\">\"data-blockingmode\"<\/span>, <span class=\"hljs-string\">\"auto\"<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-built_in\">document<\/span>.head.appendChild(cmpScript);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-built_in\">document<\/span>.head.removeChild(cmpScript);\n<\/span><\/span><span class='shcb-loc'><span>    };\n<\/span><\/span><span class='shcb-loc'><span>  }, &#91;]);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-literal\">null<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>};\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> CookieConsent;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This file is very similar to the first section\u2019s component as we are going to use the client-side directive for this as well as the <code>useEffect<\/code> hook from React.<\/p>\n\n\n\n<p>We use the <code>useEffect<\/code> hook to execute side effects in the component and the empty dependency array ensures that the effect runs only once after the initial render.<\/p>\n\n\n\n<p>The focus in this component is on the script elements.&nbsp; Inside our <code>useEffect<\/code> hook, we have a variable that creates a new script element called <code>cmpScript<\/code>.&nbsp; This is where we load the Cookiebot script.<\/p>\n\n\n\n<p>Then we set all the attributes.&nbsp; I won\u2019t go over every attribute.&nbsp; The main ones I will focus on are:<\/p>\n\n\n\n<p><code>cmpScript.src = \"https:\/\/consent.cookiebot.com\/uc.js\"; <\/code>&#8211; This specifies the source of the script, pointing to the Cookiebot script.<\/p>\n\n\n\n<p><code>cmpScript.setAttribute(\"data-cbid\", \"your-cookiebot-id\");<\/code> &#8211; This sets your specific Cookiebot ID. Replace <code>\"your-cookiebot-id\"<\/code> with your actual Cookiebot ID.<\/p>\n\n\n\n<p><code>cmpScript.setAttribute(\"data-blockingmode\", \"auto\");<\/code> &#8211; This sets the blocking mode for scripts to <code>\"auto\"<\/code>, allowing Cookiebot to manage script blocking based on user consent.<\/p>\n\n\n\n<p>Following the running of those scripts, we append the element to the head of the document which injects the Cookiebot script into the page.<\/p>\n\n\n\n<p>Then we run a cleanup function that removes the script element from the document head when the component unmounts.&nbsp; This will prevent any unintended side effects.<\/p>\n\n\n\n<p>We are not rendering any JSX here as we are using Cookiebot to show a UI, so we return null.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"set-the-consent-globally-in-nextjs\">Set the Consent Globally in Next.js<\/h3>\n\n\n\n<p>The next step is to add the <code>CookieBotConsent<\/code> component to our global layout so that it appears on all pages of our site.&nbsp; In order to do this, we go to <code>app\/layout.jsx<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">\".\/globals.css\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { Rubik } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/font\/google\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> CookieBotConsent <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/components\/CookieBotConsent\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> Navbar <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/components\/Navbar\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> rubik = Rubik({ <span class=\"hljs-attr\">subsets<\/span>: &#91;<span class=\"hljs-string\">\"latin\"<\/span>] });\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> metadata = {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">title<\/span>: <span class=\"hljs-string\">\"Headless WordPress Example\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">description<\/span>: <span class=\"hljs-string\">\"Generated by Franly the Manly\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>};\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">RootLayout<\/span>(<span class=\"hljs-params\">{ children }<\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">return<\/span> (\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">html<\/span> <span class=\"hljs-attr\">lang<\/span>=<span class=\"hljs-string\">\"en\"<\/span>&gt;<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">body<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{rubik.className}<\/span>&gt;<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Navbar<\/span> \/&gt;<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        {children}<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">CookieBotConsent<\/span> \/&gt;<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">footer<\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">          <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">textAlign:<\/span> \"<span class=\"hljs-attr\">center<\/span>\", <span class=\"hljs-attr\">marginTop:<\/span> \"<span class=\"hljs-attr\">20px<\/span>\", <span class=\"hljs-attr\">fontSize:<\/span> \"<span class=\"hljs-attr\">14px<\/span>\" }}<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        &gt;<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">          \u00a9 2024 Fran Agulto Dev Stoke<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">footer<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">body<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">html<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">  );<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">}<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>CookiebotConsent<\/code> component is added under the Navbar, right before the footer.&nbsp; Now, this will appear on all our pages in the entire application.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"testing-the-cookiebot-consent-banner\">Testing the Cookiebot Consent Banner<\/h3>\n\n\n\n<p>To effectively test the Cookiebot consent banner, we have a few options. However, a key requirement is a publicly accessible domain, as well as ensuring cross-domain consistency within a live production environment. It&#8217;s important to note that using <code>localhost:3000<\/code> from the Next.js development server is not a viable option for this testing.<\/p>\n\n\n\n<p>The 3 ways you can test the banner are:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Get a<a href=\"https:\/\/developers.wpengine.com\/docs\/atlas\/overview\/\"> free Atlas sandbox account<\/a> or any host, spin up a live site with a URL&nbsp;<\/li>\n\n\n\n<li>Use the <a href=\"https:\/\/developers.wpengine.com\/docs\/atlas\/platform-guides\/preview-environments\/\">preview link feature off Atlas <\/a>on a feature branch<\/li>\n\n\n\n<li>Use a service like ngrok to tunnel a public domain to the localhost:3000 port<\/li>\n<\/ol>\n\n\n\n<p>(Please refer to the <a href=\"https:\/\/ngrok.com\/docs\">documentation if you choose the ngrok<\/a> setup)<\/p>\n\n\n\n<div class=\"wp-block-group has-base-color has-heliotrope-background-color has-text-color has-background has-link-color wp-elements-60580c77f35127ab4c58efd3ae854863 has-global-padding is-layout-constrained wp-container-core-group-is-layout-9b866ece wp-block-group-is-layout-constrained\" style=\"border-radius:12px;margin-bottom:var(--wp--preset--spacing--30);padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)\">\n<div class=\"wp-block-group alignwide is-content-justification-left is-layout-flex wp-container-core-group-is-layout-4bb02320 wp-block-group-is-layout-flex\" style=\"padding-top:0;padding-right:0;padding-bottom:0;padding-left:0\">\n<p style=\"font-size:26px;font-style:normal;font-weight:700;letter-spacing:-1px;line-height:1\">Headless<br>Platform<\/p>\n\n\n\n<p class=\"has-small-font-size wp-container-content-9cfa9a5a\" style=\"line-height:1.5\">The all-in-one platform for <br>radically fast headless sites.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-right is-nowrap is-layout-flex wp-container-core-buttons-is-layout-b315634e wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button is-style-outline-base\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/wpeng.in\/headless-platform\/\" style=\"border-radius:99px;padding-top:10px;padding-right:24px;padding-bottom:10px;padding-left:24px\" target=\"_blank\" rel=\"noreferrer noopener\">Try for free \u2192<\/a><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<p>Once you have chosen your method, go to your Cookiebot admin UI and navigate to <em><code>Dashboard &gt; Domains and Aliases<\/code><\/em>.&nbsp; You should see this page and once you click the button to add a domain, you are connected.<\/p>\n\n\n\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/e9Z1vsvmP0pG5nMUhfeohewE8VLECJAYXQdp07HehhKy2tAXngVfFR3xSvu2nJUjoj6lja6v_UJrxtzLDZJhXZMXjHdDVlAmQzjp0WUteFJv261aOrZin_KHPl8tjVA5hQsIQxyPegBfBvoS-biQhaw\" width=\"624\" height=\"353\"><\/p>\n\n\n\n<p>We now have a publicly accessible URL that Cookiebot can track and if I visit the site for the first time, the Cookie Consent banner pops up like so:<\/p>\n\n\n\n<p><img loading=\"lazy\" decoding=\"async\" width=\"624\" height=\"329\" src=\"https:\/\/lh7-us.googleusercontent.com\/zrfm7iz7eK02Ll57RJBtvhCm27XJI26eVa_TCX6iAnc3CEZxkAbsvfkw-3ZkLuoCYUGHbKnNreXuRD8258MUyiZnwv6YkLR8A8YhXWXd85c1zEZgSUBJwxZhfz2KR2_UU2rnSHbRXuvq-nWBuFvcjps\"><\/p>\n\n\n\n<p><img loading=\"lazy\" decoding=\"async\" width=\"624\" height=\"299\" src=\"https:\/\/lh7-us.googleusercontent.com\/C1Gu6X4hRvyQpohT52FC1qQSCxBx-eEdjPfjJuXrmkaa9pd5gGWz2yf1ruA5Vts2sS29IdTXfkU5iXrrCC64gdNLyi9VnUJZzqoVNTAekzikuxqTsQlKEZ3E1xH-W3JftTC1Lj2syEBV5sK7sLV2Ghs\"><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"create-the-declaration-and-privacy-policy-page\">Create the Declaration and Privacy Policy Page<\/h3>\n\n\n\n<p>The next component we will look at is a page that renders the Privacy Policy from Cookiebot. Navigate to <code>app\/components\/CookieBotDeclaration.jsx:<\/code><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">\"use client\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { useEffect } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> CookieDeclaration = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  useEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">const<\/span> cookieDeclarationScript = <span class=\"hljs-built_in\">document<\/span>.createElement(<span class=\"hljs-string\">\"script\"<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>    cookieDeclarationScript.id = <span class=\"hljs-string\">\"CookieDeclaration\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>    cookieDeclarationScript.src =\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-string\">\"https:\/\/consent.cookiebot.com\/your-cookiebot-id\/cd.js\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>    cookieDeclarationScript.setAttribute(<span class=\"hljs-string\">\"type\"<\/span>, <span class=\"hljs-string\">\"text\/javascript\"<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>    cookieDeclarationScript.setAttribute(<span class=\"hljs-string\">\"async\"<\/span>, <span class=\"hljs-string\">\"true\"<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-built_in\">document<\/span>.body.appendChild(cookieDeclarationScript);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-built_in\">document<\/span>.body.removeChild(cookieDeclarationScript);\n<\/span><\/span><span class='shcb-loc'><span>    };\n<\/span><\/span><span class='shcb-loc'><span>  }, &#91;]);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-literal\">null<\/span>; <span class=\"hljs-comment\">\/\/ The script itself handles rendering the cookie declaration<\/span>\n<\/span><\/span><span class='shcb-loc'><span>};\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> CookieDeclaration;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>I am not going to go over the entire code block because this is identical&nbsp; to the component we looked at that ran the <code>CookieBotConsent.jsx<\/code> file.&nbsp; The difference is that we are just running the script to render the Privacy Policy and Declaration page that comes from it.<\/p>\n\n\n\n<p>Lastly, we need to insert the component into our <code>privacy-policy<\/code> route segment folder which has the <code>page.jsx<\/code> file like so:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> CookieBotDeclaration <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/components\/CookieBotDeclaration\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> React <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> PrivacyPolicyPage = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">return<\/span> (\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Privacy Policy<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">     <\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">CookieBotDeclaration<\/span> \/&gt;<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">  );<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">};<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> PrivacyPolicyPage;<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>You should see this once you visit whatever your URL is <code>\/privacy-policy<\/code><\/p>\n\n\n\n<p><img loading=\"lazy\" decoding=\"async\" width=\"624\" height=\"341\" src=\"https:\/\/lh7-us.googleusercontent.com\/BV198eyuxzuLa3mHo0T5cyNAsoyQmbHqkid1sE_t9P_Idr5eeS3a_zkDbrBy7zpj3Pbzu3puq1XzXQx_Hwp7TWDSJ4jElIXnrF5Xk5--wcG2ZlmwYwAlXmUZK8JbtUxOL0FDPEw3ATplTJhFBw4VM84\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"conclusion\">Conclusion<\/h2>\n\n\n\n<p>Cookie Policy Popups&nbsp;are an important part of websites for legal compliance and user transparency\/trust.&nbsp; I hope you have a better understanding of how this works in headless WordPress, focusing on the frontend.<\/p>\n\n\n\n<p>As always, stoked to hear your feedback and any questions you might have on headless WordPress! Hit us up in our <a href=\"https:\/\/discord.com\/invite\/J2khkF9XYK\">Discord<\/a>!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Cookie policies are guidelines and rules that govern how cookies are used on websites to respect user privacy and comply with legal regulations. In the context of headless WordPress, which [&hellip;]<\/p>\n","protected":false},"author":20,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_EventAllDay":false,"_EventTimezone":"","_EventStartDate":"","_EventEndDate":"","_EventStartDateUTC":"","_EventEndDateUTC":"","_EventShowMap":false,"_EventShowMapLink":false,"_EventURL":"","_EventCost":"","_EventCostDescription":"","_EventCurrencySymbol":"","_EventCurrencyCode":"","_EventCurrencyPosition":"","_EventDateTimeSeparator":"","_EventTimeRangeSeparator":"","_EventOrganizerID":[],"_EventVenueID":[],"_OrganizerEmail":"","_OrganizerPhone":"","_OrganizerWebsite":"","_VenueAddress":"","_VenueCity":"","_VenueCountry":"","_VenueProvince":"","_VenueState":"","_VenueZip":"","_VenuePhone":"","_VenueURL":"","_VenueStateProvince":"","_VenueLat":"","_VenueLng":"","_VenueShowMap":false,"_VenueShowMapLink":false,"footnotes":""},"categories":[23],"tags":[],"class_list":["post-31457","post","type-post","status-publish","format-standard","hentry","category-headless"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Cookie Policy Popups in headless WordPress with Next.js 14 and WPGraphQL \ud83c\udf6a - Builders<\/title>\n<meta name=\"description\" content=\"Learn 2 methods on how to implement GDPR-compliant cookie policy popups in a headless WordPress environment using Next.js 14.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Cookie Policy Popups with Next.js 14 &amp; WPGraphQL \ud83c\udf6a\" \/>\n<meta property=\"og:description\" content=\"Learn 2 methods on how to implement GDPR-compliant cookie policy popups in a headless WordPress environment using Next.js 14 and WPGraphQL.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/\" \/>\n<meta property=\"og:site_name\" content=\"Builders\" \/>\n<meta property=\"article:published_time\" content=\"2024-01-22T17:03:21+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-03-18T18:11:56+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2024\/01\/YouTube-Video-Thumbnail-5.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1152\" \/>\n\t<meta property=\"og:image:height\" content=\"671\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Francis Agulto\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@wpebuilders\" \/>\n<meta name=\"twitter:site\" content=\"@wpebuilders\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Francis Agulto\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"31 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/cookie-policy-popups-in-headless-wp\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/cookie-policy-popups-in-headless-wp\\\/\"},\"author\":{\"name\":\"Francis Agulto\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/person\\\/bcdcb4ac0b215c34b6b30e440a24dc54\"},\"headline\":\"Cookie Policy Popups in headless WordPress with Next.js 14 and WPGraphQL \ud83c\udf6a\",\"datePublished\":\"2024-01-22T17:03:21+00:00\",\"dateModified\":\"2024-03-18T18:11:56+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/cookie-policy-popups-in-headless-wp\\\/\"},\"wordCount\":2059,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/cookie-policy-popups-in-headless-wp\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/lh7-us.googleusercontent.com\\\/2KHEafO5L0T448Pt-Kde0OVNBfFHMVZ_f6i7Yc_AywGJZ_GagQ5f_gTdjtHp5IN62Cx2Ss8sc0JkeQJAuN2noSc2NVRvUDJxmh-Emhqr4hD9LYkIAroTLz6K6WdDHKU1TEYiWW4p3LJl7AL9DS9C2t8\",\"articleSection\":[\"Headless\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/wpengine.com\\\/builders\\\/cookie-policy-popups-in-headless-wp\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/cookie-policy-popups-in-headless-wp\\\/\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/cookie-policy-popups-in-headless-wp\\\/\",\"name\":\"Cookie Policy Popups in headless WordPress with Next.js 14 and WPGraphQL \ud83c\udf6a - Builders\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/cookie-policy-popups-in-headless-wp\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/cookie-policy-popups-in-headless-wp\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/lh7-us.googleusercontent.com\\\/2KHEafO5L0T448Pt-Kde0OVNBfFHMVZ_f6i7Yc_AywGJZ_GagQ5f_gTdjtHp5IN62Cx2Ss8sc0JkeQJAuN2noSc2NVRvUDJxmh-Emhqr4hD9LYkIAroTLz6K6WdDHKU1TEYiWW4p3LJl7AL9DS9C2t8\",\"datePublished\":\"2024-01-22T17:03:21+00:00\",\"dateModified\":\"2024-03-18T18:11:56+00:00\",\"description\":\"Learn 2 methods on how to implement GDPR-compliant cookie policy popups in a headless WordPress environment using Next.js 14.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/cookie-policy-popups-in-headless-wp\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wpengine.com\\\/builders\\\/cookie-policy-popups-in-headless-wp\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/cookie-policy-popups-in-headless-wp\\\/#primaryimage\",\"url\":\"https:\\\/\\\/lh7-us.googleusercontent.com\\\/2KHEafO5L0T448Pt-Kde0OVNBfFHMVZ_f6i7Yc_AywGJZ_GagQ5f_gTdjtHp5IN62Cx2Ss8sc0JkeQJAuN2noSc2NVRvUDJxmh-Emhqr4hD9LYkIAroTLz6K6WdDHKU1TEYiWW4p3LJl7AL9DS9C2t8\",\"contentUrl\":\"https:\\\/\\\/lh7-us.googleusercontent.com\\\/2KHEafO5L0T448Pt-Kde0OVNBfFHMVZ_f6i7Yc_AywGJZ_GagQ5f_gTdjtHp5IN62Cx2Ss8sc0JkeQJAuN2noSc2NVRvUDJxmh-Emhqr4hD9LYkIAroTLz6K6WdDHKU1TEYiWW4p3LJl7AL9DS9C2t8\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/cookie-policy-popups-in-headless-wp\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Cookie Policy Popups in headless WordPress with Next.js 14 and WPGraphQL \ud83c\udf6a\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#website\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/\",\"name\":\"Builders\",\"description\":\"Reimagining the way we build with WordPress.\",\"publisher\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#organization\",\"name\":\"WP Engine\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/WP-Engine-Horizontal@2x.png\",\"contentUrl\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/WP-Engine-Horizontal@2x.png\",\"width\":348,\"height\":68,\"caption\":\"WP Engine\"},\"image\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/wpebuilders\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UCh1WuL54XFb9ZI6m6goFv1g\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/person\\\/bcdcb4ac0b215c34b6b30e440a24dc54\",\"name\":\"Francis Agulto\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/0c8a05c76944fc987d57296c96dc368055844527088c0aa44297edbfa8b82546?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/0c8a05c76944fc987d57296c96dc368055844527088c0aa44297edbfa8b82546?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/0c8a05c76944fc987d57296c96dc368055844527088c0aa44297edbfa8b82546?s=96&d=mm&r=g\",\"caption\":\"Francis Agulto\"},\"description\":\"Fran Agulto is a Developer Advocate at WP Engine. He is a lover of all things headless WordPress, Rock Climbing, and overall being stoked for people that love what they do and share that stoke with others! Follow me on Twitter for cool stoked headless WP!\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/author\\\/francis-agultowpengine-com-2-2-2-2-2-2-2-2-2-2-2-3\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Cookie Policy Popups in headless WordPress with Next.js 14 and WPGraphQL \ud83c\udf6a - Builders","description":"Learn 2 methods on how to implement GDPR-compliant cookie policy popups in a headless WordPress environment using Next.js 14.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/","og_locale":"en_US","og_type":"article","og_title":"Cookie Policy Popups with Next.js 14 & WPGraphQL \ud83c\udf6a","og_description":"Learn 2 methods on how to implement GDPR-compliant cookie policy popups in a headless WordPress environment using Next.js 14 and WPGraphQL.","og_url":"https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/","og_site_name":"Builders","article_published_time":"2024-01-22T17:03:21+00:00","article_modified_time":"2024-03-18T18:11:56+00:00","og_image":[{"width":1152,"height":671,"url":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2024\/01\/YouTube-Video-Thumbnail-5.jpg","type":"image\/jpeg"}],"author":"Francis Agulto","twitter_card":"summary_large_image","twitter_creator":"@wpebuilders","twitter_site":"@wpebuilders","twitter_misc":{"Written by":"Francis Agulto","Est. reading time":"31 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/#article","isPartOf":{"@id":"https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/"},"author":{"name":"Francis Agulto","@id":"https:\/\/wpengine.com\/builders\/#\/schema\/person\/bcdcb4ac0b215c34b6b30e440a24dc54"},"headline":"Cookie Policy Popups in headless WordPress with Next.js 14 and WPGraphQL \ud83c\udf6a","datePublished":"2024-01-22T17:03:21+00:00","dateModified":"2024-03-18T18:11:56+00:00","mainEntityOfPage":{"@id":"https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/"},"wordCount":2059,"commentCount":0,"publisher":{"@id":"https:\/\/wpengine.com\/builders\/#organization"},"image":{"@id":"https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/#primaryimage"},"thumbnailUrl":"https:\/\/lh7-us.googleusercontent.com\/2KHEafO5L0T448Pt-Kde0OVNBfFHMVZ_f6i7Yc_AywGJZ_GagQ5f_gTdjtHp5IN62Cx2Ss8sc0JkeQJAuN2noSc2NVRvUDJxmh-Emhqr4hD9LYkIAroTLz6K6WdDHKU1TEYiWW4p3LJl7AL9DS9C2t8","articleSection":["Headless"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/","url":"https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/","name":"Cookie Policy Popups in headless WordPress with Next.js 14 and WPGraphQL \ud83c\udf6a - Builders","isPartOf":{"@id":"https:\/\/wpengine.com\/builders\/#website"},"primaryImageOfPage":{"@id":"https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/#primaryimage"},"image":{"@id":"https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/#primaryimage"},"thumbnailUrl":"https:\/\/lh7-us.googleusercontent.com\/2KHEafO5L0T448Pt-Kde0OVNBfFHMVZ_f6i7Yc_AywGJZ_GagQ5f_gTdjtHp5IN62Cx2Ss8sc0JkeQJAuN2noSc2NVRvUDJxmh-Emhqr4hD9LYkIAroTLz6K6WdDHKU1TEYiWW4p3LJl7AL9DS9C2t8","datePublished":"2024-01-22T17:03:21+00:00","dateModified":"2024-03-18T18:11:56+00:00","description":"Learn 2 methods on how to implement GDPR-compliant cookie policy popups in a headless WordPress environment using Next.js 14.","breadcrumb":{"@id":"https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/#primaryimage","url":"https:\/\/lh7-us.googleusercontent.com\/2KHEafO5L0T448Pt-Kde0OVNBfFHMVZ_f6i7Yc_AywGJZ_GagQ5f_gTdjtHp5IN62Cx2Ss8sc0JkeQJAuN2noSc2NVRvUDJxmh-Emhqr4hD9LYkIAroTLz6K6WdDHKU1TEYiWW4p3LJl7AL9DS9C2t8","contentUrl":"https:\/\/lh7-us.googleusercontent.com\/2KHEafO5L0T448Pt-Kde0OVNBfFHMVZ_f6i7Yc_AywGJZ_GagQ5f_gTdjtHp5IN62Cx2Ss8sc0JkeQJAuN2noSc2NVRvUDJxmh-Emhqr4hD9LYkIAroTLz6K6WdDHKU1TEYiWW4p3LJl7AL9DS9C2t8"},{"@type":"BreadcrumbList","@id":"https:\/\/wpengine.com\/builders\/cookie-policy-popups-in-headless-wp\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/wpengine.com\/builders\/"},{"@type":"ListItem","position":2,"name":"Cookie Policy Popups in headless WordPress with Next.js 14 and WPGraphQL \ud83c\udf6a"}]},{"@type":"WebSite","@id":"https:\/\/wpengine.com\/builders\/#website","url":"https:\/\/wpengine.com\/builders\/","name":"Builders","description":"Reimagining the way we build with WordPress.","publisher":{"@id":"https:\/\/wpengine.com\/builders\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wpengine.com\/builders\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/wpengine.com\/builders\/#organization","name":"WP Engine","url":"https:\/\/wpengine.com\/builders\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wpengine.com\/builders\/#\/schema\/logo\/image\/","url":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2024\/05\/WP-Engine-Horizontal@2x.png","contentUrl":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2024\/05\/WP-Engine-Horizontal@2x.png","width":348,"height":68,"caption":"WP Engine"},"image":{"@id":"https:\/\/wpengine.com\/builders\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/wpebuilders","https:\/\/www.youtube.com\/channel\/UCh1WuL54XFb9ZI6m6goFv1g"]},{"@type":"Person","@id":"https:\/\/wpengine.com\/builders\/#\/schema\/person\/bcdcb4ac0b215c34b6b30e440a24dc54","name":"Francis Agulto","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/0c8a05c76944fc987d57296c96dc368055844527088c0aa44297edbfa8b82546?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/0c8a05c76944fc987d57296c96dc368055844527088c0aa44297edbfa8b82546?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/0c8a05c76944fc987d57296c96dc368055844527088c0aa44297edbfa8b82546?s=96&d=mm&r=g","caption":"Francis Agulto"},"description":"Fran Agulto is a Developer Advocate at WP Engine. He is a lover of all things headless WordPress, Rock Climbing, and overall being stoked for people that love what they do and share that stoke with others! Follow me on Twitter for cool stoked headless WP!","url":"https:\/\/wpengine.com\/builders\/author\/francis-agultowpengine-com-2-2-2-2-2-2-2-2-2-2-2-3\/"}]}},"_links":{"self":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/posts\/31457","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/users\/20"}],"replies":[{"embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/comments?post=31457"}],"version-history":[{"count":0,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/posts\/31457\/revisions"}],"wp:attachment":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/media?parent=31457"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/categories?post=31457"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/tags?post=31457"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}