Documentation

Everything you need to add a lightweight consent banner to your site.

Installation

Script Tag (Recommended)

Add this script tag to your HTML, just before the closing </body> tag:

<script src="https://www.safebanner.com/safebanner.js"></script>

Self-Hosted

Download the script and host it yourself:

curl -o safebanner.js https://www.safebanner.com/safebanner.js

Quick Start

Get compliant in under 2 minutes:

  1. Add the script
    <script src="https://www.safebanner.com/safebanner.js"></script>
  2. That's it

    The banner appears automatically for new visitors. Consent is stored locally. Load analytics and ad scripts only after checking consent if your setup requires opt-in behavior.

Default behavior: SafeBanner stores consent choices locally and exposes them through the JavaScript API. For the safest setup, only load non-essential scripts after checking consent.

Configuration

Configure via data attributes on the script tag:

<script
  src="https://www.safebanner.com/safebanner.js"
  data-position="bottom-right"
  data-theme="dark"
  data-color="#8b5cf6"
  data-company="Acme Inc"
  data-privacy="https://acme.com/privacy"
  data-project-key="your-pro-key"
></script>

Options Reference

AttributeValuesDefaultDescription
data-positionbottom, top, bottom-left, bottom-rightbottomBanner position on screen
data-themelight, darklightColor scheme
data-colorAny hex color#2563ebPrimary button color
data-companyStringWeYour company name in banner text
data-privacyURLLink to your privacy policy
data-langen, fr, de, plus additional Pro languagesenBanner language. Free includes en/fr/de. Additional built-in languages require a Pro key
data-google-consentadvanced, basic, offadvancedGoogle Consent Mode v2 behavior. advanced sends redacted pings, basic blocks all tags when denied
data-project-keyStringPro license key — removes branding and unlocks additional languages

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_)

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')) {
  // Safe to load Google Analytics
  loadGoogleAnalytics();
}

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://www.safebanner.com/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>
  );
}

Conditional Analytics Loading

// Only load Google Analytics if user consented
function loadAnalytics() {
  if (window.safeBanner?.hasConsentFor('analytics')) {
    const script = document.createElement('script');
    script.src = 'https://www.googletagmanager.com/gtag/js?id=GA_ID';
    document.head.appendChild(script);

    window.dataLayer = window.dataLayer || [];
    function gtag() { dataLayer.push(arguments); }
    gtag('js', new Date());
    gtag('config', 'GA_ID');
  }
}

// Run on page load
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', loadAnalytics);
} else {
  loadAnalytics();
}

WordPress

// Add to your theme's functions.php
function add_consent_manager() {
  echo '<script src="https://www.safebanner.com/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://www.safebanner.com/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://www.safebanner.com/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.js

Requirements

  • 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.)

License: MIT. Use it however you want, including in commercial projects.

FAQ

Is this really GDPR compliant?

SafeBanner helps you collect and store consent choices in the browser. You are still responsible for configuring your site to load analytics and advertising scripts only after consent when required.

What about CCPA?

CCPA and GDPR have different requirements. SafeBanner provides the banner and consent state management, but it does not provide hosted audit logs, region routing, or legal advice.

How do you detect cookies?

We scan 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?

No. SafeBanner stores consent state and exposes it via the JavaScript API. For opt-in behavior, load non-essential scripts only after checking consent.

What does Pro unlock?

Pro removes the Powered by SafeBanner footer, unlocks additional built-in languages, and enables custom banner copy and button labels. Those translations load on demand, so the core banner stays small.

Can I customize the banner text?

Yes. Pro supports custom banner title, description, and button labels via data attributes. The free tier still supports company name and privacy policy URL.

How do I add a 'Manage Cookies' link?

Call 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.)
  • SafeBanner exposes consent state but does not block scripts or cookies — ensure you only load non-essential scripts after checking 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 our CDN (www.safebanner.com) 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.