Library: smallest-cookie-banner | Size: ~2KB gzipped | License: MIT
The Problem with Cookie Consent
Every website that uses analytics, advertising, or tracking needs user consent in the EU under GDPR. Most cookie consent solutions are bloated - OneTrust clocks in at 100KB+, and even simpler solutions like cookieconsent hit 25KB. That's larger than many entire websites need to be.
When you're building a fast, performant site, adding a 100KB consent manager defeats the purpose. You need something that:
- Loads instantly (no impact on Core Web Vitals)
- Works without a build step (CDN-loadable)
- Handles GDPR compliance correctly
- Doesn't require a SaaS subscription
Enter smallest-cookie-banner
smallest-cookie-banner is a ~2KB gzipped library that handles cookie consent properly. It's MIT licensed, has zero dependencies, and loads from unpkg CDN.
Key features:
- Geo-aware: Auto-detects EU users via timezone for GDPR
- Implied consent: Auto-accepts in regions where it's legal (USA, Asia)
- WCAG 2.1 AA accessible: Keyboard navigation, screen readers, 44px touch targets
- Fully customizable: Every string, style, and behavior can be configured
Quick Installation (CDN)
The simplest setup - just two script tags:
<!-- Set config before loading -->
<script>
window.CookieBannerConfig = {
msg: 'We use cookies for analytics.',
acceptText: 'Accept',
rejectText: 'Decline',
onAccept: function() {
// Load your analytics here
console.log('User accepted cookies');
},
onReject: function() {
// Disable tracking
console.log('User rejected cookies');
}
};
</script>
<!-- Load the library -->
<script src="https://cdn.jsdelivr.net/npm/smallest-cookie-banner@2.1.2/dist/cookie-banner.min.js"></script>That's it. The banner appears for EU users with Accept/Decline buttons. Non-EU users get a simpler "OK" button with implied consent.
Configuration Options
window.CookieBannerConfig = {
// Text (fully customizable for i18n)
msg: 'We use cookies to enhance your experience.',
acceptText: 'Accept',
rejectText: 'Decline',
// Behavior
days: 365, // Cookie expiry
forceEU: true, // Force EU mode (show Accept/Decline everywhere)
autoAcceptDelay: 5000, // Auto-accept after 5s for non-EU (0 to disable)
cookieName: 'ck', // Custom cookie name
cookieDomain: '.example.com', // For subdomains
// Callbacks
onAccept: function() { /* Load analytics */ },
onReject: function() { /* Disable tracking */ },
// Styling
css: '#ckb { background: #333; }', // Additional CSS
style: 'border-radius: 8px;' // Inline styles
};Toast-Style Corner Banner
Want a modern toast notification instead of a full-width bar? Add custom CSS:
window.CookieBannerConfig = {
msg: 'We use cookies for analytics.',
acceptText: 'Accept',
rejectText: 'Decline',
forceEU: true,
css: `
#ckb {
bottom: 20px !important;
right: 20px !important;
left: auto !important;
width: 320px;
border-radius: 12px;
flex-direction: column;
text-align: center;
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
}
#ckb p { min-width: auto; }
`
};Integrating with Google Analytics
The key to GDPR compliance is only loading tracking scripts AFTER consent:
window.CookieBannerConfig = {
msg: 'We use cookies for analytics.',
acceptText: 'Accept',
rejectText: 'Decline',
forceEU: true,
onAccept: function() {
// Only load GA after user accepts
if (!document.querySelector('script[src*="googletagmanager.com/gtag/js"]')) {
var s = document.createElement('script');
s.async = true;
s.src = 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX';
document.head.appendChild(s);
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
window.gtag = gtag;
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
}
},
onReject: function() {
// Disable GA if user rejects
window['ga-disable-G-XXXXXXXXXX'] = true;
}
};Gatsby/React Integration
For Gatsby sites, add the banner via gatsby-ssr.js:
const React = require("react");
exports.onRenderBody = ({ setPostBodyComponents }) => {
setPostBodyComponents([
// Config must come before script
<script
key="cookie-banner-config"
dangerouslySetInnerHTML={{
__html: `
window.CookieBannerConfig = {
msg: 'We use cookies for analytics.',
acceptText: 'Accept',
rejectText: 'Decline',
forceEU: true,
onAccept: function() {
// Load GA
},
onReject: function() {
window['ga-disable-G-XXXXXXXXXX'] = true;
}
};
`,
}}
/>,
<script
key="cookie-banner-script"
src="https://cdn.jsdelivr.net/npm/smallest-cookie-banner@2.1.2/dist/cookie-banner.min.js"
/>,
]);
};Important: Set the config BEFORE loading the script. The library auto-initializes when it detects window.CookieBannerConfig.
Common Gotchas
Double Banner Issue
If you see two banners, you're likely:
- Setting config AND calling
createCookieBanner()manually - Loading the script twice
The library auto-initializes when config exists. Don't call createCookieBanner() unless you're not setting window.CookieBannerConfig.
Banner Not Showing
If the banner doesn't appear:
- Check if a
ckcookie already exists (user already consented) - Non-EU users get auto-accepted silently - use
forceEU: trueto test - Clear cookies:
document.cookie = "ck=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"
Checking Consent Status
// After banner loads, check consent:
CookieBanner.ok // true (accepted), false (rejected), null (no decision)
// Programmatic control:
CookieBanner.yes() // Accept
CookieBanner.no() // Reject
CookieBanner.reset() // Clear and reload pagenpm Installation (Alternative)
If you prefer npm over CDN:
npm install smallest-cookie-bannerimport 'smallest-cookie-banner';
// Set config in useEffect (React) or mounted (Vue)
window.CookieBannerConfig = {
msg: 'We use cookies.',
onAccept: () => loadAnalytics()
};Size Comparison
| Library | Size |
|---|---|
| smallest-cookie-banner | ~2KB |
| cookie-consent | ~15KB |
| cookieconsent | ~25KB |
| tarteaucitron | ~45KB |
| OneTrust | ~100KB+ |
Legal Compliance
The library handles these regulations:
| Region | Law | Behavior |
|---|---|---|
| EU | GDPR | Shows Accept + Reject buttons |
| UK | UK GDPR | Shows Accept + Reject buttons |
| California | CCPA | Shows OK button (implied consent) |
| Brazil | LGPD | Shows Accept + Reject buttons |
| Rest of World | Various | Shows OK button (implied consent) |
The geo-detection uses timezone offset, which is reliable for determining EU vs non-EU without any external API calls.
Conclusion
smallest-cookie-banner solves cookie consent without the bloat. At 2KB, it's smaller than most favicons. It loads from CDN, requires no build step, and handles GDPR compliance correctly.
For most sites, the CDN approach shown here is the simplest path to compliance. Set your config, load the script, and you're done.
Resources:
Fred
AUTHORFull-stack developer with 10+ years building production applications. This blog is built with Gatsby - I know the framework inside and out.
Need a developer who gets it?
POC builds, vibe-coded fixes, and real engineering. Let's talk.
Hire Me →
