Free tool Cookie banner generator with a live preview
Pick a layout, colours, wording and the cookie categories you actually use. You get one block of plain HTML, CSS and JavaScript with no library behind it, a working preview next to it, and an optional Google Consent Mode v2 snippet that is wired to the banner.
- Live preview
- No dependencies
- Runs locally
Design the banner, then copy one block of code
The preview runs the exact code below. Try Reject, Customize and the “Cookie settings” button; the log under the fake page shows what the banner sends to Google Consent Mode.
A bar is the least intrusive. A centred dialog blocks the page until the visitor chooses, so it must offer Reject just as clearly.
Text colours are fixed for contrast; only the button colour follows your brand.
Used for both Accept and Reject. The text colour on it is picked automatically for the higher contrast.
Button labels, category names and the default message.
Plain text. Say what the optional cookies are for; the policy link is added after it.
A path such as /cookies or a full https:// address. Need one? Try the cookie policy generator.
Both are first-party and readable only by your site.
1–730. Changing the version below also asks everyone again.
Bump it when you add a new purpose or vendor.
Live preview
A sandboxed frame with no access to storage, so choices live in memory and reset whenever you change a setting. Nothing is written on tapcub.com.
What this banner does
- DoneButton text contrast is 5.17:1, above the WCAG 4.5:1 minimum for normal text.
- DoneReject all and Accept all share one style and sit side by side on the first layer.
- DoneOptional categories start unticked. Saved choices are shown as they were saved.
- Donerole="dialog" with a labelled heading and message; every control is a real button or checkbox, works by keyboard and shows a focus ring; Escape closes the settings view.
- DoneA floating “Cookie settings” button appears after a choice, and any element with data-cc-open reopens the settings.
- NoteThe choice is saved in localStorage under “cookie_consent” and the banner asks again after 180 days or when the version changes.
- NoteVisitors whose browser sends Global Privacy Control get marketing off by default, with a visible note. California’s regulations (§7025) require businesses that sell or share personal information to treat that signal as an opt-out.
- NoteConsent Mode: paste the head snippet above the Google tag. Defaults are denied; the banner sends an update after every choice and on every later page view.
- NoteTo block a script until consent, change its type to text/plain and add data-cc-category="analytics" (or marketing / preferences).
- NoteIn the preview, links do nothing and choices are kept in memory only.
<!-- Google Consent Mode v2: paste this at the very top of <head>, before the Google tag or the Tag Manager container. -->
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
// Defaults: everything optional is denied until the visitor chooses.
gtag('consent', 'default', {
'ad_storage': 'denied',
'ad_user_data': 'denied',
'ad_personalization': 'denied',
'analytics_storage': 'denied',
'functionality_storage': 'denied',
'personalization_storage': 'denied',
'security_storage': 'granted',
'wait_for_update': 500
});
// Returning visitors: re-apply the saved choice before any Google tag runs.
(function () {
var raw = null, r = null;
try { raw = localStorage.getItem('cookie_consent'); } catch (e) {}
if (!raw) try { var m = document.cookie.match(/(?:^|; )cookie_consent=([^;]*)/); if (m) raw = decodeURIComponent(m[1]); } catch (e) {}
try { r = JSON.parse(raw); } catch (e) {}
if (!r || !r.c || !(r.e > Date.now()) || r.v !== '1') return;
var c = r.c;
gtag('consent', 'update', {
'ad_storage': c.marketing ? 'granted' : 'denied',
'ad_user_data': c.marketing ? 'granted' : 'denied',
'ad_personalization': c.marketing ? 'granted' : 'denied',
'analytics_storage': c.analytics ? 'granted' : 'denied',
'functionality_storage': c.preferences ? 'granted' : 'denied',
'personalization_storage': c.preferences ? 'granted' : 'denied'
});
})();
</script>Paste it before the Google tag or Tag Manager container. For region-specific defaults, url_passthrough or GTM, use the Consent Mode generator; it reads the same saved choice.
<!-- Cookie banner · generated with tapcub.com/tools/cookie-banner-generator · no dependencies. A template, not legal advice: review it before use. -->
<!-- Paste this block just before </body> on every page. -->
<!-- Optional scripts: write them as <script type="text/plain" data-cc-category="analytics" src="…"></script>; they run only after consent. -->
<!-- API: CookieConsent.get() · CookieConsent.open() · CookieConsent.reset() · CookieConsent.on(fn); any element with data-cc-open reopens the settings. -->
<style>
#cc-banner{--cc-bg:#ffffff;--cc-fg:#111827;--cc-muted:#4b5563;--cc-border:#d1d5db;--cc-panel:#f9fafb;--cc-accent:#2563eb;--cc-on-accent:#ffffff;--cc-link:#2563eb;
position:fixed;z-index:2147483000;left:0;right:0;bottom:0;border-width:1px 0 0;box-sizing:border-box;padding:20px;background:var(--cc-bg);color:var(--cc-fg);border:1px solid var(--cc-border);
box-shadow:0 8px 32px rgba(0,0,0,.18);font:15px/1.5 system-ui,-apple-system,"Segoe UI",Roboto,"PingFang SC","Microsoft YaHei",sans-serif}
#cc-banner[hidden],#cc-reopen[hidden],#cc-backdrop[hidden],#cc-banner [hidden]{display:none!important}
#cc-banner *{box-sizing:border-box}
#cc-banner:focus{outline:none}
#cc-banner .cc-inner{max-width:1080px;margin:0 auto;display:grid;gap:14px}
#cc-banner .cc-title{margin:0;font-size:17px;font-weight:700;line-height:1.3;color:var(--cc-fg)}
#cc-banner .cc-text{margin:0;color:var(--cc-muted)}
#cc-banner a{color:var(--cc-link);text-decoration:underline;text-underline-offset:2px}
#cc-banner .cc-cats{display:grid;gap:8px;margin:0;padding:0;border:0}
#cc-banner .cc-cat{display:flex;gap:10px;align-items:flex-start;padding:10px 12px;border:1px solid var(--cc-border);border-radius:8px;background:var(--cc-panel)}
#cc-banner .cc-cat input{width:20px;height:20px;margin:2px 0 0;flex:none;accent-color:var(--cc-accent)}
#cc-banner .cc-cat b{display:block;color:var(--cc-fg)}
#cc-banner .cc-cat span{display:block;font-size:13px;color:var(--cc-muted)}
#cc-banner .cc-note{margin:0;font-size:13px;color:var(--cc-muted)}
#cc-banner .cc-actions{display:flex;flex-wrap:wrap;gap:8px}
#cc-banner .cc-btn{flex:1 1 auto;min-height:44px;padding:10px 18px;border:2px solid var(--cc-accent);border-radius:8px;background:var(--cc-accent);color:var(--cc-on-accent);font:inherit;font-weight:600;cursor:pointer}
#cc-banner .cc-btn-alt{background:transparent;color:var(--cc-fg);border-color:var(--cc-border)}
#cc-banner .cc-btn:focus-visible,#cc-reopen:focus-visible,#cc-banner a:focus-visible,#cc-banner input:focus-visible{outline:3px solid var(--cc-link);outline-offset:2px}
#cc-backdrop{position:fixed;inset:0;z-index:2147482999;background:rgba(17,24,39,.55)}
#cc-reopen{position:fixed;z-index:2147482998;left:16px;bottom:16px;min-height:40px;padding:8px 14px;border:1px solid #d1d5db;border-radius:999px;background:#ffffff;color:#111827;font:600 13px/1.2 system-ui,sans-serif;cursor:pointer;box-shadow:0 2px 10px rgba(0,0,0,.15)}
#cc-reopen:focus-visible{outline:3px solid #2563eb;outline-offset:2px}
@media (min-width:720px){#cc-banner.cc-bar .cc-inner{grid-template-columns:1fr auto;align-items:center}#cc-banner.cc-bar .cc-prefs,#cc-banner.cc-bar .cc-actions-wide{grid-column:1/-1}#cc-banner .cc-btn{flex:0 1 auto}}
</style>
<div id="cc-banner" class="cc-bar" role="dialog" aria-modal="false" aria-labelledby="cc-title" aria-describedby="cc-desc" tabindex="-1" lang="en" hidden>
<div class="cc-inner">
<div>
<h2 class="cc-title" id="cc-title">We use cookies</h2>
<p class="cc-text" id="cc-desc">We use strictly necessary cookies to run this site. With your consent we also use cookies for analytics and marketing. You can change your choice at any time in “Cookie settings”. <a href="/cookies">Cookie policy</a></p>
</div>
<div class="cc-prefs" id="cc-prefs" hidden>
<fieldset class="cc-cats">
<legend class="cc-note">Cookie categories</legend>
<div class="cc-cat"><input type="checkbox" id="cc-cat-necessary" checked disabled><label for="cc-cat-necessary"><b>Strictly necessary</b><span>Always on. Needed for the site to work, for example security and remembering this choice.</span></label></div>
<div class="cc-cat"><input type="checkbox" id="cc-cat-analytics" data-cc-cat="analytics"><label for="cc-cat-analytics"><b>Analytics</b><span>Helps us understand how the site is used, for example which pages are visited.</span></label></div>
<div class="cc-cat"><input type="checkbox" id="cc-cat-marketing" data-cc-cat="marketing"><label for="cc-cat-marketing"><b>Marketing</b><span>Used to measure ad campaigns and show more relevant ads.</span></label></div>
</fieldset>
<p class="cc-note" data-cc-gpc hidden>Opt-out preference signal honored: your browser sent Global Privacy Control, so marketing stays off unless you switch it on here.</p>
</div>
<div class="cc-actions">
<button type="button" class="cc-btn" data-cc="reject">Reject all</button>
<button type="button" class="cc-btn" data-cc="accept">Accept all</button>
<button type="button" class="cc-btn cc-btn-alt" data-cc="customize" aria-expanded="false" aria-controls="cc-prefs">Customize</button>
<button type="button" class="cc-btn cc-btn-alt" data-cc="save" hidden>Save choices</button>
</div>
</div>
</div>
<button type="button" id="cc-reopen" data-cc-open hidden>Cookie settings</button>
<script>
(function () {
'use strict';
// Settings: change them here, not further down.
var KEY = "cookie_consent"; // localStorage key / cookie name
var VERSION = "1"; // change it when your purposes change: everyone is asked again
var DAYS = 180; // ask again after this many days
var STORAGE = "local"; // 'local' = localStorage, 'cookie' = first-party cookie
var CATEGORIES = ["analytics","marketing"];
var CONSENT_MODE = true; // send gtag('consent', 'update', …)
var TAPCUB = false; // tell the TapCub script (identification mode only)
var HONOR_GPC = true; // Global Privacy Control keeps marketing off
var MODAL = false;
var root = document.getElementById('cc-banner');
if (!root) return;
var backdrop = document.getElementById('cc-backdrop');
var reopenBtn = document.getElementById('cc-reopen');
var prefs = document.getElementById('cc-prefs');
var memory = null, lastFocus = null, firstRun = false;
var gpc = HONOR_GPC && navigator.globalPrivacyControl === true && CATEGORIES.indexOf('marketing') > -1;
// keep the banner first in the tab order
document.body.insertBefore(root, document.body.firstChild);
if (backdrop) document.body.insertBefore(backdrop, root);
// ---- storage: falls back to memory when the browser blocks it
function read() {
var raw = null;
try {
if (STORAGE === 'local') raw = localStorage.getItem(KEY);
else { var m = document.cookie.match(new RegExp('(?:^|; )' + KEY + '=([^;]*)')); if (m) raw = decodeURIComponent(m[1]); }
} catch (e) {}
if (!raw) return memory;
try { return JSON.parse(raw); } catch (e) { return null; }
}
function write(rec) {
memory = rec;
var s = rec ? JSON.stringify(rec) : null;
try {
if (STORAGE === 'local') { if (s) localStorage.setItem(KEY, s); else localStorage.removeItem(KEY); }
else document.cookie = KEY + '=' + (s ? encodeURIComponent(s) : '') + '; Max-Age=' + (s ? DAYS * 86400 : 0) + '; Path=/; SameSite=Lax' + (location.protocol === 'https:' ? '; Secure' : '');
} catch (e) {}
}
function valid(r) { return !!(r && r.c && r.v === VERSION && r.e > Date.now()); }
// ---- what happens after a choice
function apply(c, userAction) {
if (CONSENT_MODE) {
window.dataLayer = window.dataLayer || [];
if (typeof window.gtag !== 'function') window.gtag = function () { window.dataLayer.push(arguments); };
window.gtag('consent', 'update', {
'ad_storage': c.marketing ? 'granted' : 'denied',
'ad_user_data': c.marketing ? 'granted' : 'denied',
'ad_personalization': c.marketing ? 'granted' : 'denied',
'analytics_storage': c.analytics ? 'granted' : 'denied',
'functionality_storage': c.preferences ? 'granted' : 'denied',
'personalization_storage': c.preferences ? 'granted' : 'denied'
});
window.dataLayer.push({ event: 'cookie_consent_update' });
}
// run <script type="text/plain" data-cc-category="…"> blocks that are now allowed
var blocked = document.querySelectorAll('script[type="text/plain"][data-cc-category]');
for (var i = 0; i < blocked.length; i++) {
var old = blocked[i];
if (!c[old.getAttribute('data-cc-category')]) continue;
var s = document.createElement('script');
for (var k = 0; k < old.attributes.length; k++) {
var a = old.attributes[k];
if (a.name !== 'type' && a.name !== 'data-cc-category') s.setAttribute(a.name, a.value);
}
s.text = old.text;
old.parentNode.replaceChild(s, old);
}
var ev;
try { ev = new CustomEvent('cookieconsent', { detail: c }); } catch (e) { ev = document.createEvent('CustomEvent'); ev.initCustomEvent('cookieconsent', false, false, c); }
document.dispatchEvent(ev);
}
function choice(all) {
var c = {};
for (var i = 0; i < CATEGORIES.length; i++) {
var k = CATEGORIES[i];
if (all === null) { var box = document.getElementById('cc-cat-' + k); c[k] = !!(box && box.checked); }
else c[k] = all && !(gpc && k === 'marketing');
}
return c;
}
function save(c) {
var now = Date.now();
write({ v: VERSION, t: now, e: now + DAYS * 864e5, c: c });
apply(c, true);
close();
}
// ---- open / close and focus handling
function focusables() { return root.querySelectorAll('button:not([hidden]):not([disabled]), a[href], input:not([disabled])'); }
function showPrefs(on) {
if (!prefs) return;
prefs.hidden = !on;
var cus = root.querySelector('[data-cc="customize"]');
var sav = root.querySelector('[data-cc="save"]');
if (cus) { cus.hidden = on; cus.setAttribute('aria-expanded', String(on)); }
if (sav) sav.hidden = !on;
if (on) { var first = prefs.querySelector('input:not([disabled])'); if (first) first.focus(); }
}
function open(withPrefs, byUser) {
var r = read(), saved = valid(r) ? r.c : {};
for (var i = 0; i < CATEGORIES.length; i++) {
var box = document.getElementById('cc-cat-' + CATEGORIES[i]);
if (box) box.checked = saved[CATEGORIES[i]] === true; // nothing is pre-ticked
}
var g = root.querySelector('[data-cc-gpc]'); if (g) g.hidden = !gpc;
lastFocus = byUser ? document.activeElement : null;
root.hidden = false;
if (backdrop) backdrop.hidden = false;
if (reopenBtn) reopenBtn.hidden = true;
showPrefs(!!withPrefs);
if (!MODAL) document.documentElement.style.scrollPaddingBottom = root.offsetHeight + 'px';
if ((MODAL || byUser) && !withPrefs) root.focus();
}
function close() {
root.hidden = true;
firstRun = false;
if (backdrop) backdrop.hidden = true;
document.documentElement.style.scrollPaddingBottom = '';
if (reopenBtn) reopenBtn.hidden = false;
var to = lastFocus && document.contains(lastFocus) ? lastFocus : reopenBtn;
if (to && to.focus) to.focus();
}
root.addEventListener('click', function (e) {
var b = e.target.closest ? e.target.closest('[data-cc]') : null;
if (!b) return;
var act = b.getAttribute('data-cc');
if (act === 'accept') save(choice(true));
else if (act === 'reject') save(choice(false));
else if (act === 'save') save(choice(null));
else if (act === 'customize') showPrefs(true);
});
root.addEventListener('keydown', function (e) {
if (e.key === 'Escape') {
if (prefs && !prefs.hidden) { showPrefs(false); var cus = root.querySelector('[data-cc="customize"]'); if (cus) cus.focus(); }
else if (!firstRun) close();
return;
}
if (e.key !== 'Tab' || !MODAL) return;
var f = focusables(); if (!f.length) return;
var first = f[0], last = f[f.length - 1];
if (e.shiftKey && (document.activeElement === first || document.activeElement === root)) { e.preventDefault(); last.focus(); }
else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }
});
document.addEventListener('click', function (e) {
var t = e.target.closest ? e.target.closest('[data-cc-open]') : null;
if (t) { e.preventDefault(); open(true, true); }
});
window.CookieConsent = {
get: function () { var r = read(); return valid(r) ? r.c : null; },
open: function () { open(true, true); },
reset: function () { write(null); firstRun = true; open(false, false); },
on: function (fn) { document.addEventListener('cookieconsent', function (e) { fn(e.detail); }); }
};
var rec = read();
if (valid(rec)) { apply(rec.c, false); if (reopenBtn) reopenBtn.hidden = false; }
else { if (rec) write(null); firstRun = true; open(false, false); }
})();
</script>One block on every page. Settings are at the top of the script.
Share these inputs: the values go after the # in the link, so they never reach a server.
https://tapcub.com/tools/cookie-banner-generator
Version v1.0Updated Update history
What the generated code is made of
One block for the banner, plus an optional snippet for Google tags. Nothing loads from a third-party server.
Banner code
A <style> block scoped to #cc-banner, the banner markup and one script. The settings (storage key, version, days, categories) sit at the top of the script so you can change them without touching the logic.
The first layer
Heading, message, policy link, then Reject all, Accept all and Customize. Reject and Accept use the same colour, size and position weight. Customize opens a list of categories with the strictly necessary one locked on.
Consent Mode snippet
Goes at the very top of <head>. It sets every optional consent type to denied with wait_for_update: 500, then re-applies a saved choice so Google tags see it before they run.
The checks
Contrast of the button text, a missing policy link, a long re-ask period and what each option changes. They describe this code; whether your site needs a banner, and which categories, depends on what it actually loads.
The banner only records a choice. It cannot stop a script it does not control: tags that are hard-coded in your page still run unless you gate them with type="text/plain" or load them through Google Consent Mode or Tag Manager.
Four steps
About ten minutes, most of it spent on step one.
-
1
List what your site stores
Open your site in a private window, then the browser’s developer tools (Application or Storage tab). Note every cookie and localStorage item and which tool set it. Only tick the categories you found.
-
2
Design and word the banner
Choose a layout and colour, check the contrast note, and write a message that says what each optional category is for. Link your cookie policy.
-
3
Paste the code
Banner block before
</body>on every page; Consent Mode snippet first thing in<head>. Change optional scripts totype="text/plain"withdata-cc-category. -
4
Test the three paths
In a private window: Reject, then check the storage tab is still clean; Accept; then reopen and withdraw. With Consent Mode, Google Tag Assistant shows the default and update states.
Why the banner works the way it does
Each default maps to a published rule or guidance. Where the rules come from:
- Storing or reading anything on a device needs consent unless it is strictly necessary for a service the user asked for: ePrivacy Directive Article 5(3). It covers localStorage as well as cookies
- Consent must be a clear affirmative act; pre-ticked boxes do not count: CJEU judgment C-673/17 Planet49 (1 October 2019) and GDPR Recital 32
- Withdrawing consent must be as easy as giving it: GDPR Article 7(3), hence the reopen button and data-cc-open
- Refusing should be as easy as accepting: CNIL guidelines and recommendation 2020-091 / 2020-092 (September 2020); the EDPB cookie banner taskforce report (January 2023) lists missing reject buttons, pre-ticked boxes and deceptive button colours or contrast among the practices it examined
- In California, a business that sells or shares personal information must treat a Global Privacy Control signal as a valid opt-out: Cal. Code Regs. tit. 11, §7025(b)
| Behaviour | In the generated code | Source |
|---|---|---|
| Reject as easy as Accept | Same button style, same layer, side by side | CNIL 2020-092; EDPB taskforce report |
| No pre-ticked categories | Optional checkboxes start unticked | CJEU C-673/17 Planet49 |
| Nothing optional before consent | Gated scripts stay text/plain; Consent Mode defaults are denied | ePrivacy Art. 5(3) |
| Easy withdrawal | Floating button, data-cc-open, CookieConsent.open() | GDPR Art. 7(3) |
| Readable and operable | 4.5:1 button text, keyboard focus, labelled dialog | WCAG 2.2 SC 1.4.3, 2.1.1, 2.4.7 |
| Opt-out signal | GPC keeps marketing off, with a note | Cal. Code Regs. tit. 11, §7025 |
Three sites, three banners
What to tick depends on what each site loads. All three use the same generator.
| Site | What it loads | Settings | Result |
|---|---|---|---|
| Blog with Google Analytics | GA4 only | Analytics ticked; Consent Mode on | Reject / Accept / Customize; GA4 runs in denied mode until Accept |
| Shop with ad pixels | GA4, Google Ads, Meta Pixel | Analytics + Marketing; Consent Mode on; pixel gated with data-cc-category="marketing" | Pixel loads only after consent; Google tags get the update |
| SaaS site on TapCub only | TapCub default mode + chat | No optional category | A short notice with one OK button, or no banner at all after legal review: neither script stores anything before the visitor acts |
The third row reflects TapCub’s own set-up: the analytics script writes no cookies or storage in its default mode, and the chat widget writes one session token only after a visitor starts a conversation (see our cookie page).
Where cookie banners go wrong
Most problems are not in the banner itself but in what runs around it.
Tags fire before the choice
A banner on top of a page whose GA or pixel code already ran records consent too late. Gate those scripts or use Consent Mode defaults.
Reject hidden on a second layer
An “Accept” button next to a small “Settings” link is the pattern regulators examined first. Put Reject on the first layer with the same weight.
No way back
If the banner never reappears, visitors cannot withdraw consent. Keep the floating button or a footer link with data-cc-open.
Categories that do not match reality
Listing “Marketing” on a site with no ad tags, or calling an analytics cookie “necessary”, makes the banner misleading. Audit first.
Analytics that does not need a slot in your banner
TapCub’s analytics script writes nothing to the visitor’s device in its default mode, so it does not depend on the banner to count visits. Consent is still handled where it matters.
No analytics cookies
Visitors are told apart by a keyed hash computed on the server; the browser stores no analytics identifier.
Learn moreConsent rules by region
The compliance centre sets whether consent is required per region and honours Global Privacy Control.
Learn moreEvery item listed
Our cookie page lists every cookie and storage item the website, console, script and chat widget use.
Learn moreCookie banner questions
Still have a question?
Chat with the team behind TapCub — we usually reply within a few hours on business days.
Do I need a cookie banner?
In the EU and UK you need consent before storing or reading anything on a visitor’s device that is not strictly necessary for a service they asked for (ePrivacy Article 5(3) and national laws). If your site only uses strictly necessary storage, such as a login session or a shopping cart, a banner is not required for those items. Analytics and ad cookies usually do need consent. This page is a template, not legal advice; ask a lawyer about your site.
Is a cookie banner enough to be GDPR compliant?
No. The banner records a choice; you also need scripts that respect it, a policy that explains each purpose, records of consent where you rely on it, and a way to withdraw. The generated code covers the banner part and can wire the choice to Google Consent Mode and gated scripts.
Does the Reject button have to look the same as Accept?
The CNIL’s 2020 recommendation proposes a “Reject all” button with the same look as “Accept all”, and the EDPB’s cookie banner taskforce examined missing reject buttons and deceptive colours or contrast. The safe design, used here, gives both buttons the same style on the first layer.
How long should a cookie consent choice be stored?
There is no single number in the GDPR. Pick a period you can justify in your cookie policy, ask again when it ends, and say how long the choice is kept. Set the days field, and bump the version whenever you add a purpose so everyone is asked again.
How do I block Google Analytics until consent?
Two ways. With Consent Mode on, paste the head snippet above your Google tag: GA4 then starts with analytics_storage denied and updates when the visitor accepts. Or gate the tag entirely: change <script> to <script type="text/plain" data-cc-category="analytics"> and the banner runs it only after consent.
Can visitors change their mind later?
Yes. After a choice, a small “Cookie settings” button stays in the corner, and any element with data-cc-open, or a call to CookieConsent.open(), reopens the categories with the saved choice shown.
Does it work with WordPress, Shopify or a single-page app?
Yes, it is plain HTML and JavaScript. On WordPress or Shopify, paste the banner block into the theme footer and the Consent Mode snippet into the theme head. In a single-page app, load it once in the page shell: the banner stays in the document across route changes. It is not meant for native mobile apps, which use their platform’s own consent screens.
Does the preview set cookies on tapcub.com?
No. The preview runs in a sandboxed frame that has no access to cookies or localStorage, so the generated code falls back to memory. Your choices disappear when you change a setting or leave the page.
Update history
New features, fixes and data refreshes for this tool, newest first.
-
· v1.0
LaunchedFirst release.
Data this tool relies on
- Google Consent Mode documentation — checked 2026-11-10, reviewed every 6 months (next review by 2027-05-10)
Missing something or found an error? Tell us — requests that come up often go into the next update. All tool updates
Finish the consent set-up
A banner, a policy and tags that listen to it belong together. These tools cover the rest.