How to add a cookie consent banner to a Drupal site
Drupal has no admin field for head code, so the snippet goes in your theme's copy of html.html.twig, right after the opening head tag, or in a small module that attaches it with hook_page_attachments(). Clear the caches, uninstall any other consent module, and mark the tags you control with type="text/plain" and a data-cq-category; the rest of the setup is in the Cookiequiet dashboard.Steps
Where to paste the snippet in Drupal
Drupal prints every page through one template, html.html.twig, whose head holds three placeholders: one for head elements, one for CSS and one for JavaScript. The snippet should sit above all three, so it loads before any library or module script.
With a theme template (no module needed). Use a custom theme or a sub-theme of the theme you run. Copy the html.html.twig your theme inherits (Olivero ships its own in core/themes/olivero/templates/layout/; otherwise copy core/modules/system/templates/html.html.twig) into your theme's templates folder, and add the snippet on the line after <head>:
html<head><script src="https://cookiequiet.com/cq.js" data-site="YOUR_SITE_KEY" data-consent-mode="1" data-auto-block="1" defer></script><head-placeholder token="{{ placeholder_token }}"><title>{{ head_title|safe_join(' | ') }}</title>
Then clear the caches under Configuration, then Development, then Performance, or with drush cr. Drupal uses your copy of a template only after a cache rebuild. Do not edit Olivero or a contributed theme in place: the next update would remove the line.
With a custom module. If you would rather not touch templates, attach the tag from hook_page_attachments(). Elements added to html_head print in the head placeholder, before the CSS and JS:
phpfunction mymodule_page_attachments(array &$attachments) {$attachments['#attached']['html_head'][] = [['#tag' => 'script','#attributes' => ['src' => 'https://cookiequiet.com/cq.js','data-site' => 'YOUR_SITE_KEY','data-consent-mode' => '1','data-auto-block' => '1','defer' => TRUE,],], 'cookiequiet'];}
The hook also runs on admin pages. That is harmless, but you can skip them by checking the router's admin context first.
Which cookies does Drupal set itself?
Drupal core sets one cookie of its own: the session cookie, named SESS (or SSESS on HTTPS) followed by a 32-character hash of the host. It is created when someone logs in, or when a module stores data in the session for an anonymous visitor (a cart, a form in progress). It is strictly necessary and needs no consent. Everything else comes from modules and the tags you add, which is why a scan matters more on Drupal than on most platforms: run the free cookie scanner on a few page types (home, article, form, shop) to see what your modules actually print.
How to handle the tags modules add
- Google Tag module. It prints the Google tag for you, so you cannot mark it. In the tag container's advanced settings, tick Enforce Privacy Consent Policy: the module then sets Google's consent defaults to denied (ad_storage, analytics_storage, ad_user_data, ad_personalization) before it loads gtag.js. Cookiequiet sends the
consent updatecommand when the visitor chooses, which the tag applies whoever printed it. If you use Google Tag Manager instead, see the Google Tag Manager guide. - Tags you pasted. In a template or a block that uses the Full HTML text format, change the opening tag to
<script type="text/plain" data-cq-category="marketing">for the Meta Pixel,analyticsfor Hotjar or Clarity. The guide to blocking scripts until consent shows the pattern for inline and external scripts. - Scripts that modules inject with JavaScript. With
data-auto-block="1", Cookiequiet holds the scripts and iframes of about 80 known trackers created this way until their category is granted. - Remote video. Drupal's Media module prints YouTube and Vimeo players as iframes in the HTML, so they load at once. For a video that must wait for consent, use an iframe with
data-cq-srcinstead ofsrcin a Full HTML block.
Uninstall any other consent module (EU Cookie Compliance, Klaro, COOKiES) after the switch, so visitors see one banner and one consent is recorded.
How to add the Cookie preferences link
Go to Structure, then Menus, open the Footer menu and click Add link. Enter #cq-preferences as the link (Drupal accepts paths that start with a hash) and "Cookie preferences" as the title. Cookiequiet opens the preferences centre from any link with that address. If your footer is a custom block instead, add an anchor with the same href.
How to test
- Open the site in a private window, logged out. The banner shows with Accept all and Reject all of the same size.
- Click Reject all. In the developer tools (Application, then Cookies in Chrome) you should see
cq_consentand nothing from Google, Meta or Hotjar. - Clear the cookies, reload, click Accept all: the marked scripts run and their cookies appear.
- Check the consent log in the Cookiequiet dashboard.
If the banner does not show, view the page source and search for cq.js. A missing tag almost always means the cache was not rebuilt or the template sits in a theme that is not the default one.
What is specific to Drupal
- Two themes. The admin theme (Claro) does not use your front-end template, so the banner appears only on the public site, which is what you want.
- Page cache and reverse proxies. The snippet is the same for every visitor, so Drupal's page cache, Varnish or a CDN can cache pages that contain it. Purge them once after the change.
- Multisite. Give each site its own site key so consent logs and policies stay separate.
Cookiequiet is free for one website with geo-targeting included, and Starter costs €3 per website per month with no pageview limit, see pricing.