Documentation
Everything you need to add a lightweight consent banner to your site.
Installation
Script Tag (Recommended)
Add this script tag to your HTML:
<script src="https://cdn.jsdelivr.net/npm/safebanner/dist/safebanner.js"></script>Using Google Consent Mode v2?
SafeBanner must load before any Google tags. Place it in your <head> above your Google tag scripts. If SafeBanner loads after, Google will fire before consent is set.
Self-Hosted
Download the script and host it yourself:
curl -o safebanner.js https://cdn.jsdelivr.net/npm/safebanner/dist/safebanner.jsQuick Start
Get set up in under 2 minutes:
- Add the script
<script src="https://cdn.jsdelivr.net/npm/safebanner/dist/safebanner.js"></script> - That's it
The banner appears automatically for new visitors. Consent is stored locally. If your setup requires enforced opt-in behavior, use Pro script blocking for analytics and marketing tags.
Default behavior: SafeBanner stores consent choices locally and exposes them through the JavaScript API. Pro adds script blocking for sites that need it.
Configuration
Configure via data attributes on the script tag:
<script
src="https://cdn.jsdelivr.net/npm/safebanner/dist/safebanner.js"
data-position="bottom-right"
data-theme="dark"
data-color="#8b5cf6"
data-company="Acme Inc"
data-privacy="https://acme.com/privacy"
></script>Options Reference
| Attribute | Values | Default | Description |
|---|---|---|---|
data-position | bottom, top, bottom-left, bottom-right | bottom | Banner position on screen |
data-theme | light, dark, auto (Pro) | light | Color scheme. Pro adds automatic light/dark theme detection |
data-color | Any hex color | #2563eb | Primary button color |
data-company | String | We | Your company name in banner text |
data-privacy | URL | — | Link to your privacy policy |
data-lang | en, fr, de, plus additional Pro languages | en | Banner language. Free includes en/fr/de. Additional built-in languages require a Pro key |
data-google-consent | advanced, basic, off | advanced | Google Consent Mode v2 behavior. advanced sends redacted pings, basic blocks all tags when denied |
data-project-key | String | — | Pro license key — unlocks script blocking, consent expiry, branding removal, layouts, and languages |
data-layout | banner, bar, card (Pro) | banner | Banner layout style. Pro adds compact bar and floating card layouts |
data-logo | Image URL (Pro) | — | Logo shown inside the banner |
data-button-style | default, pill, square (Pro) | default | Button shape preset for the banner actions |
data-banner-title | String (Pro) | Localized default | Custom banner title text |
data-banner-description | String (Pro) | Localized default | Custom banner body copy |
data-accept-label | String (Pro) | Localized default | Custom Accept All button label |
data-reject-label | String (Pro) | Localized default | Custom Reject All button label |
data-customize-label | String (Pro) | Localized default | Custom Customize button label |
data-save-label | String (Pro) | Localized default | Custom Save Preferences button label |
data-radius | Number in px (Pro) | Contextual default | Border radius for the banner and buttons |
data-max-width | Number in px (Pro) | Layout default | Maximum width for bar/card style layouts |
data-offset | Number in px (Pro) | 16 | Distance from screen edges for corner and card layouts |
data-consent-expiry-days | Number in days (Pro) | — | Re-prompt visitors after stored consent expires |
Languages
Free includes English, French, and German in the core bundle. Pro unlocks additional built-in languages with a valid data-project-key. Those Pro translations load on demand, so the free core bundle stays small. If a Pro-only language is requested without a valid key, SafeBanner falls back to English.
Cookie Categories
We automatically categorize cookies into three groups:
Necessary
Essential cookies required for the site to function. Always enabled.
Examples: Session IDs, CSRF tokens, auth cookies
Analytics
Cookies used to understand how visitors interact with your site.
Examples: Google Analytics (_ga, _gid), Mixpanel, Amplitude
Marketing
Cookies used for advertising and retargeting.
Examples: Facebook Pixel (_fbp), Google Ads (_gcl), LinkedIn (li_)
Script Blocking
Pro can activate Analytics and Marketing scripts only after the matching consent category is granted. Mark blocked scripts with type="text/safebanner" and put the real source in data-src.
<script
src="https://cdn.jsdelivr.net/npm/safebanner/dist/safebanner.js"
data-project-key="your-pro-key"
></script>
<script
type="text/safebanner"
data-consent="analytics"
data-src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXX"
data-async
></script>Inline scripts work too. Omit data-src and place the code inside the marked script tag.
Use data-type="module" for module scripts. SafeBanner preserves common attributes such as id, nonce, integrity, crossorigin, and referrerpolicy when activating marked scripts.
<script type="text/safebanner" data-consent="marketing">
fbq('init', '123456789');
fbq('track', 'PageView');
</script>SafeBanner only activates scripts you explicitly mark. It does not scan, rewrite, or guess third-party scripts automatically.
JavaScript API
Access the consent manager programmatically via window.safeBanner.
getConsent()
Returns the current consent state, or null if not yet consented.
Returns: ConsentState | null
const consent = window.safeBanner.getConsent();
// { necessary: true, analytics: true, marketing: false, timestamp: 1704067200000 }hasConsented()
Check if the user has made a consent choice.
Returns: boolean
if (window.safeBanner.hasConsented()) {
// User has already chosen
}hasConsentFor(category)
Check if user has consented to a specific category.
Returns: boolean
if (window.safeBanner.hasConsentFor('analytics')) {
showAnalyticsEnabledState();
}updateConsent(updates)
Programmatically update consent preferences.
Returns: void
window.safeBanner.updateConsent({
analytics: true,
marketing: false
});reset()
Clear stored consent and show the banner again.
Returns: void
// Add a 'Manage Cookies' link in your footer
document.getElementById('manage-cookies').addEventListener('click', () => {
window.safeBanner.reset();
});show()
Manually show the consent banner.
Returns: void
window.safeBanner.show();hide()
Manually hide the consent banner.
Returns: void
window.safeBanner.hide();TypeScript Types
interface ConsentState {
necessary: boolean; // Always true
analytics: boolean;
marketing: boolean;
timestamp: number; // Unix timestamp of consent
}
type ConsentCategory = 'necessary' | 'analytics' | 'marketing';Examples
React / Next.js
// components/SafeBanner.tsx
'use client';
import Script from 'next/script';
export function SafeBanner() {
return (
<Script
src="https://cdn.jsdelivr.net/npm/safebanner/dist/safebanner.js"
data-position="bottom-right"
data-theme="light"
strategy="afterInteractive"
/>
);
}
// app/layout.tsx
import { SafeBanner } from '@/components/SafeBanner';
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<SafeBanner />
</body>
</html>
);
}Pro Script Blocking
For production sites, Pro can activate marked analytics and marketing scripts only after matching consent is granted.
<script
type="text/safebanner"
data-consent="analytics"
data-src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXX"
data-async
></script>WordPress
// Add to your theme's functions.php
function add_consent_manager() {
echo '<script src="https://cdn.jsdelivr.net/npm/safebanner/dist/safebanner.js" data-company="' . get_bloginfo('name') . '"></script>';
}
add_action('wp_footer', 'add_consent_manager');Vue.js
<!-- App.vue -->
<template>
<div id="app">
<router-view />
</div>
</template>
<script>
export default {
mounted() {
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/safebanner/dist/safebanner.js';
script.dataset.position = 'bottom-right';
document.body.appendChild(script);
}
}
</script>Footer "Manage Cookies" Link
<footer>
<a href="#" id="manage-cookies">Manage Cookie Preferences</a>
</footer>
<script>
document.getElementById('manage-cookies').addEventListener('click', (e) => {
e.preventDefault();
window.safeBanner.reset();
});
</script>Self-Hosting
Want full control? Self-host the script on your own infrastructure.
Option 1: Download the Script
# Download the latest version
curl -o safebanner.js https://cdn.jsdelivr.net/npm/safebanner/dist/safebanner.js
# Host it on your server
cp safebanner.js /var/www/html/js/Option 2: Build from Source
# Clone the repo
git clone https://github.com/hellokariburt/SafeBanner.git
cd safebanner
# Install dependencies
pnpm install
# Build the script
cd packages/consent-script && pnpm build
# Output is in apps/web/public/safebanner.jsRequirements
- No backend required for free tier (client-side only)
- Serve the JS file with proper CORS headers if cross-origin
- Recommended: serve via CDN for performance (Cloudflare, Vercel Edge, etc.)
- Pro features (license validation, 40+ languages) always contact
safebanner.comregardless of where the script is hosted
License: MIT. Use it however you want, including in commercial projects.
Paid Features
The free tier covers the core banner and consent state. Pro adds marked script blocking, consent expiry, accessible cookie cleanup, and production customization.
Shipping client work or a real SaaS?
Pro blocks marked analytics and marketing scripts until consent, re-prompts after consent expires, cleans up accessible cookies after rejection, removes SafeBanner branding, and adds production customization.
| Feature | Free | Pro |
|---|---|---|
| Consent banner | ✓ | ✓ |
| Local consent storage | ✓ | ✓ |
| Google Consent Mode support | ✓ | ✓ |
| Self-host or use CDN | ✓ | ✓ |
| English, French, German | ✓ | ✓ |
| Marked script blocking | — | ✓ |
| Consent expiry and re-prompt | — | ✓ |
| Spanish, Italian, Dutch, Portuguese | — | ✓ |
| Auto light/dark theme | — | ✓ |
| Bar and card layouts | — | ✓ |
| Logo support | — | ✓ |
| Button style presets | — | ✓ |
| Custom banner title and description | — | ✓ |
| Custom button labels | — | ✓ |
| Powered by SafeBanner branding | ✓ | — |
| Production/client license key | — | ✓ |
FAQ
Does SafeBanner make my site GDPR compliant?
What about CCPA?
How do you detect cookies?
document.cookie and match against known patterns (Google Analytics, Facebook Pixel, etc.). We categorize them as necessary, analytics, or marketing. You can also manually configure categories.Does this block cookies automatically?
What does Pro unlock?
Can I customize the banner text?
What happens before a visitor makes a choice?
type="text/safebanner" stay blocked until consent. The banner stays visible until the visitor makes a choice.How long does consent last?
window.safeBanner.reset(). In Pro, use data-consent-expiry-days to re-prompt visitors after a set number of days.How do I add a 'Manage Cookies' link?
window.safeBanner.reset() to clear consent and re-show the banner. See the Examples section above.Troubleshooting
Banner not appearing
- Check the browser console for errors
- Ensure the script is loaded (Network tab → filter by "consent")
- Clear localStorage (
localStorage.removeItem('safebanner_consent')) - You may have already consented — try
window.safeBanner.reset()
Cookies still being set before consent
- Ensure our script loads before other scripts (analytics, ads, etc.)
- Free does not block scripts. Use Pro to block marked scripts with
type="text/safebanner"for analytics and marketing tags that must wait for consent. - Check if the cookie is categorized as "necessary"
Script not loading (CORS error)
- If self-hosting, ensure your server sends proper CORS headers
- Use the jsdelivr CDN (
cdn.jsdelivr.net/npm/safebanner) which handles CORS automatically
Banner style conflicts
- Our styles are scoped with
.cm-prefix to avoid conflicts - Check for CSS resets or aggressive global styles in your app
- Use browser dev tools to inspect the banner element
Still stuck? Open an issue on GitHub and we'll help.