Platforms

How to add a cookie consent banner to a Docusaurus site

In Docusaurus, add the snippet as the first entry of the scripts field in docusaurus.config.js: Docusaurus prints those tags in the head of every page, before the head tags that plugins inject. If the site uses the gtag option of the classic preset, either drop the snippet's defer so Consent Mode defaults run first, or replace the plugin with a marked script.
Published 21 October 2026 · By the Cookiequiet team · Markdown

Steps

Copy the snippetIn the Cookiequiet dashboard, add the website and copy the snippet with your site key, data-consent-mode="1" and data-auto-block="1".
Add it to the scripts fieldIn docusaurus.config.js (or .ts), add an object to scripts with src set to https://cookiequiet.com/cq.js, defer: true and the three data attributes as string values.
Decide what to do with gtagIf the classic preset has a gtag option, either remove defer from the Cookiequiet entry so the denied defaults run before the plugin's tags, or remove the gtag option and load Google Analytics from a marked script.
Load other tags as marked scriptsPut tracking code in a file under static/js and add it to scripts with type: "text/plain" and data-cq-category, below the Cookiequiet entry.
Add the Cookie preferences linkIn themeConfig.footer.links, add an item whose html field holds an anchor with href="#cq-preferences" and data-cq-show-preferences.
Build and testRun npm run build and npm run serve, open the site in a private window, click Reject all and check that no _ga cookie is set. Accept all, reload and check the consent log.

Where does the snippet go in Docusaurus?

The scripts field of docusaurus.config.js takes URLs or objects of attributes, and Docusaurus inserts the resulting <script> tags in the head of every page. The plugin documentation adds that the head tags plugins inject come after the scripts added by the config, so an entry here runs before analytics plugins:

js
// docusaurus.config.js
export default {
// ...
scripts: [
{
src: "https://cookiequiet.com/cq.js",
defer: true,
"data-site": "YOUR_SITE_KEY",
"data-consent-mode": "1",
"data-auto-block": "1",
},
],
};

Use scripts rather than headTags for this: both print to the head, but scripts is the field Docusaurus documents for script tags, and its object form accepts any attribute. Do not load the banner as a client module either: client modules are bundled into the app and run after it, while the banner reads its settings from its own tag.

What about the gtag option of the classic preset?

Many Docusaurus sites set gtag: { trackingID: "G-..." } in @docusaurus/preset-classic. The plugin is active only in production builds, and it injects the Google tag as head tags: the external gtag.js with async, then an inline script that calls gtag('config') straight away. That inline script runs while the page is parsed, before a deferred script. Two ways to put consent first:

Keep the plugin, use Consent Mode. Remove defer: true from the Cookiequiet entry. The banner then runs where it stands, before the plugin's tags, and sets every Google consent type to denied before gtag('config'). Google Analytics loads with analytics_storage denied and sets no _ga cookie until the visitor accepts; Cookiequiet sends the update after each choice. The Google Analytics 4 guide explains what Google receives in that state.

Drop the plugin, load GA only after consent. Remove the gtag option and add your own file as a marked script:

js
scripts: [
{ src: "https://cookiequiet.com/cq.js", defer: true, "data-site": "YOUR_SITE_KEY", "data-consent-mode": "1", "data-auto-block": "1" },
{ src: "/js/analytics.js", type: "text/plain", "data-cq-category": "analytics" },
],
js
// static/js/analytics.js
var s = document.createElement("script");
s.async = true;
s.src = "https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX";
document.head.appendChild(s);
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag("js", new Date());
gtag("config", "G-XXXXXXX");

Cookiequiet runs the file when analytics is granted, and at once on later visits where the stored choice includes it. Nothing from Google loads before that. Any other tracker can follow the same pattern; the guide on blocking scripts lists the markup for embeds.

What about client-side navigation?

A Docusaurus site is a single-page app after the first load. The snippet runs once per full load and the stored choice stays applied, so the banner does not come back on each page. If you send page views yourself, a client module's onRouteDidUpdate runs after each route renders, and on the first render too; check consent there with window.Cookiequiet.get(), whose c array lists the granted categories, or keep the categories from the cq:consent event that Cookiequiet dispatches on window each time it applies a choice. Docusaurus notes that hash changes also trigger these lifecycles, so compare the pathname before sending.

Footer items accept an html field that is rendered as given:

js
themeConfig: {
footer: {
links: [
{
title: "Legal",
items: [
{ html: '<a href="#cq-preferences" data-cq-show-preferences>Cookie preferences</a>' },
],
},
],
},
},

How do I test it?

  1. Run npm run build then npm run serve: the gtag plugin does nothing in development, so test the production build.
  2. View the page source: cq.js is the first script in the head.
  3. Open the site in a private window and click Reject all: no _ga cookie, only cq_consent.
  4. Clear the cookies, click Accept all, reload: _ga appears and the Realtime report shows the visit.
  5. Check the consent log in the dashboard.

Documentation sites often serve a global audience: geo-targeting can show the banner only in regulated countries, and it is included in the free plan, which covers one website. Starter is €3 per website per month with unlimited pageviews.

Questions

Use scripts. It is the field Docusaurus documents for script tags, its object form takes any attribute, and its tags come before the head tags plugins inject.
The gtag plugin adds an inline script that calls gtag config while the page is parsed. A deferred script runs later, so Google's consent defaults would arrive after the tag. Without defer, Cookiequiet sets them first.
Not an official one. The scripts field is enough: Cookiequiet is one script tag, configured from the dashboard.
The gtag plugin is only active in production builds. Run npm run build and npm run serve to test the banner and the Google tag together.

Put a quiet banner on your website today

Free for one website with every core feature, no card and no trial clock. Upgrade a website to Starter for $3 a month to match your brand with AI and drop the branding, or to Pro for $9 to design it with the AI agent.