@meui-creative/cookies
v4.0.0
Published
GDPR-compliant cookie consent management for React with centralized Payload CMS configuration
Downloads
101
Maintainers
Readme
@meui-creative/cookies
GDPR-compliant cookie consent management for React and Next.js with 5 unique preset layouts, remote configuration, and full Google Consent Mode V2 support.
Features
- ✅ 5 Unique Layouts - From minimal bars to full sidebars, find the perfect design
- 🎨 Fully Customizable - Override colors, position, and styles for each preset
- 🌍 Multi-language - Built-in translations (EN, CS, DE) with auto-detection
- 📡 Remote Config - Centralized content management via Payload CMS
- 🎯 Google Consent Mode V2 - Full automatic support with all required parameters
- 🔌 Service Integrations - Optional auto-init for Google Analytics, Facebook Pixel, GTM, and more
- 🚫 Script Blocking - Automatically blocks scripts until consent
- 💪 Robust Positioning - React Portal ensures banner always displays correctly
- ♿ Accessible - Full keyboard navigation and ARIA support
- 📱 Responsive - Mobile-first design
- 🎯 TypeScript - Full type safety
- ⚡ GDPR Compliant - Strict mode blocks all non-essential cookies
Installation
npm install @meui-creative/cookies framer-motion lucide-react⚠️ Important for Google Analytics/GTM users
If you have existing Google tags in your <head>, remove them and use the plugin integration instead:
// ❌ Wrong - custom tag without Consent Mode
<script async src="https://www.googletagmanager.com/gtag/js?id=GA-XXX"></script>
// ✅ Correct - use plugin integration
<CookieConsent
integrations={{
googleAnalytics: 'GA-XXX'
}}
/>The plugin ensures proper order: consent default → load tag → config → update.
Quick Start
1. Add to your layout
import { CookieConsent } from '@meui-creative/cookies'
export default function App() {
return (
<>
<CookieConsent />
{/* Your app */}
</>
)
}2. Choose your integration method
You have two options for integrating analytics and tracking services:
✅ Method A: Integrated (Recommended)
Best for: Google Analytics, GTM, Facebook Pixel, Hotjar, Clarity
Simply pass your IDs via the integrations prop. The library handles everything automatically, including Google Consent Mode V2.
<CookieConsent
integrations={{
googleAnalytics: process.env.NEXT_PUBLIC_GA_ID,
googleTagManager: process.env.NEXT_PUBLIC_GTM_ID,
facebookPixel: process.env.NEXT_PUBLIC_FB_PIXEL_ID,
hotjar: process.env.NEXT_PUBLIC_HOTJAR_ID,
clarity: process.env.NEXT_PUBLIC_CLARITY_ID,
}}
/>How it works:
- Plugin automatically sets
gtag('consent', 'default', ...)withdeniedfor all parameters - Creates tracking scripts dynamically after user consents
- Calls
gtag('consent', 'update', ...)when user accepts/declines - Scripts load only when user accepts the relevant category
- Works automatically on every page load (consent is saved)
Category mapping:
googleAnalytics→ analyticsgoogleTagManager→ analyticsfacebookPixel→ marketinghotjar→ analyticsclarity→ analytics
📝 Method B: Manual blocking
Best for: Custom scripts, third-party widgets, or services not supported by integrations
Add these two attributes to your existing script tags:
type="text/plain"- Prevents script from executingdata-cookie-category="..."- Specifies which category
Examples:
<!-- Google Analytics → analytics -->
<script type="text/plain" data-cookie-category="analytics">
gtag('config', 'GA-XXXXXXXXX');
</script>
<!-- Facebook Pixel → marketing -->
<script type="text/plain" data-cookie-category="marketing">
fbq('init', 'YOUR_PIXEL_ID');
fbq('track', 'PageView');
</script>
<!-- Custom tracking → analytics -->
<script type="text/plain" data-cookie-category="analytics">
// Your custom tracking code
</script>
<!-- YouTube embed → marketing -->
<iframe data-cookie-category="marketing" src="https://www.youtube.com/embed/VIDEO_ID"> </iframe>Available categories:
strictly-necessary- Always allowed (use rarely)functional- Site functionalityanalytics- Google Analytics, Hotjar, Clarity, GTMmarketing- Facebook Pixel, ads, YouTube embeds
Google Consent Mode V2
Plugin automatically supports Google Consent Mode V2 according to official documentation.
What it does automatically
✅ Sets gtag('consent', 'default', ...) with denied for all parameters before loading Google tags
✅ Calls gtag('consent', 'update', ...) after user clicks Accept/Decline
✅ Supports all V2 parameters: ad_storage, analytics_storage, ad_user_data, ad_personalization
✅ Enables URL passthrough for ad click tracking without cookies
✅ Enables ads data redaction for GDPR compliance
Basic usage
<CookieConsent
integrations={{
googleAnalytics: 'GA-XXXXXXXXX',
googleTagManager: 'GTM-XXXXXX',
}}
/>That's it! Consent Mode V2 works automatically.
Category mapping to Consent Mode
| Plugin category | Consent Mode parameters |
| -------------------- | -------------------------------------------------- |
| marketing | ad_storage, ad_user_data, ad_personalization |
| analytics | analytics_storage |
| functional | functionality_storage, personalization_storage |
| strictly-necessary | security_storage (always granted) |
Testing in GTM
- Open GTM → Preview Mode
- Load your website
- Click "Consent" tab in Preview window
Before Accept:
- On-page default: Denied ✅
- Current state: Denied ✅
After Accept:
- On-page update: Granted ✅
- Current state: Granted ✅
Debug in console
// Show all consent events
window.dataLayer.filter(e => e[0] === 'consent')
// Expected output:
[
['consent', 'default', { ad_storage: 'denied', ... }],
['consent', 'update', { ad_storage: 'granted', ... }]
]Advanced usage
import { CookieConsent, initConsentMode, updateConsentMode } from '@meui-creative/cookies'
// Region-specific consent
initConsentMode({
region: ['ES', 'DE', 'FR'], // EU only
urlPassthrough: true,
adsDataRedaction: true,
})
// Manual consent update
updateConsentMode({
analytics: true,
marketing: false,
})Full documentation
For detailed guide, see the Consent Mode V2 documentation:
- How it works under the hood
- Migration guide from v1.x
- Troubleshooting common issues
- API reference
- Testing examples
Design Presets
Choose from 5 professionally designed layouts, each with unique UX:
default - Classic Card
Color: Blue (#3b82f6) | Position: Bottom-left
Clean, professional design with large cookie icon. Perfect for corporate websites.
<CookieConsent />meui - Compact with Inline Settings
Color: Green (#4A6953) | Position: Bottom-left
Original Meui design with expandable settings directly in banner. Saves modal interactions.
<CookieConsent preset="meui" />minimal - Bottom Bar
Color: Black (#000) | Position: Full-width bottom
Horizontal bar spanning full width. Non-intrusive, great for blogs and content sites.
<CookieConsent preset="minimal" />card - Accent Header
Color: Violet (#8b5cf6) | Position: Bottom-right
Modern card with colored header stripe and shield icon. Bold and eye-catching.
<CookieConsent preset="card" />sidebar - Full-Height Panel
Color: Emerald (#10b981) | Position: Right sidebar
Full-height sidebar with detailed information and trust indicators. Best for complex consent needs.
<CookieConsent preset="sidebar" />Customization
Every preset can be customized. Override color, position, language, or any style property:
Change Color
<CookieConsent
preset="default"
accentColor="#ec4899" // Pink
/>Change Position
<CookieConsent
preset="card"
style={{
position: 'top-center', // Move to top
}}
/>Change Language
<CookieConsent
preset="meui"
language="cs" // Czech
/>Multiple Overrides
<CookieConsent
preset="minimal"
accentColor="#f97316"
language="de"
style={{
position: 'top-center',
animation: {
direction: 'down',
duration: 0.5,
},
}}
/>Configuration
Basic Setup (GDPR Compliant)
<CookieConsent
preset="default"
language="cs"
links={{
privacyPolicy: '/privacy',
cookiePolicy: '/cookies',
}}
/>With Analytics
<CookieConsent
preset="card"
language="en"
links={{
privacyPolicy: '/privacy',
cookiePolicy: '/cookies',
}}
integrations={{
googleAnalytics: 'GA-XXXXXXXXX',
}}
/>Custom Position & Color
<CookieConsent
preset="sidebar"
accentColor="#10b981"
style={{
position: 'bottom-left', // Sidebar on left instead of right
}}
links={{
privacyPolicy: '/privacy',
cookiePolicy: '/cookies',
}}
/>All Configuration Options
<CookieConsent
// Design
preset="default" // 'default' | 'meui' | 'minimal' | 'card' | 'sidebar'
accentColor="#3b82f6" // Any hex color
borderRadius="rounded" // 'rounded' | 'sharp'
// Position & Layout
style={{
position: 'bottom-left', // 'bottom-left' | 'bottom-center' | 'bottom-right'
// 'top-left' | 'top-center' | 'top-right'
animation: {
direction: 'up', // 'up' | 'down' | 'left' | 'right' | 'fade'
duration: 0.3, // Animation duration in seconds
enabled: true, // Enable/disable animations
},
}}
// Content & Language
language="en" // 'en' | 'cs' | 'de'
descriptionMode="short" // 'short' | 'long'
// Behavior
mode="strict" // 'strict' (GDPR) | 'soft' (informational)
showSettingsButton={true} // Show settings button
closeButton={true} // Show close button
showRejectLink={true} // Show reject link
ttl={365} // Consent validity in days
// Legal (Required for GDPR)
links={{
privacyPolicy: '/privacy',
cookiePolicy: '/cookies',
}}
// Integrations (with automatic Consent Mode V2)
integrations={{
googleAnalytics: 'GA-XXXXXXXXX',
facebookPixel: '123456789',
googleTagManager: 'GTM-XXXXXX',
hotjar: 'XXXXXX',
clarity: 'XXXXXX',
}}
// Callbacks
onAccept={choices => console.log('Accepted:', choices)}
onDecline={() => console.log('Declined')}
onChange={choices => console.log('Changed:', choices)}
onReady={() => console.log('Ready')}
// Advanced
domain="example.com" // For subdomain consent
debug={false} // Enable debug logging
/>Position Options
All presets support 6 positions:
bottom-left- Bottom left cornerbottom-center- Bottom centerbottom-right- Bottom right cornertop-left- Top left cornertop-center- Top centertop-right- Top right corner
Note: minimal preset adapts to top/bottom (full-width bar)
Note: sidebar preset uses left/right from position (full-height panel)
Manual Control
Show Settings
import { showCookieSettings } from '@meui-creative/cookies'
export function Footer() {
return <button onClick={showCookieSettings}>Cookie Settings</button>
}Revoke Consent
import { revokeConsent } from '@meui-creative/cookies'
function clearConsent() {
revokeConsent()
}Export User Data (GDPR)
Export all stored consent data for GDPR data access requests:
import { exportConsent } from '@meui-creative/cookies'
function downloadUserData() {
const data = exportConsent()
if (!data) {
console.log('No consent data found')
return
}
// Returns ConsentRecord:
// {
// version: "1.0.0",
// timestamp: 1730000000000,
// choices: { analytics: true, marketing: false, ... },
// userAgent: "Mozilla/5.0...",
// language: "cs"
// }
// Download as JSON
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = `cookie-consent-${Date.now()}.json`
a.click()
URL.revokeObjectURL(url)
}What data is stored:
- localStorage (
meui_cookie_consent): Full consent record with all metadata - Cookie (
meui_cookie_consent): Simplified comma-separated list of accepted categories (for server-side access)
Data retention:
- Data expires after TTL (default 365 days)
- Automatically cleared on version change
- Can be manually revoked with
revokeConsent()
Headless Mode
Use the hook directly for custom UI:
import { useCookieConsent } from '@meui-creative/cookies'
export function CustomCookieBanner() {
const { consent, hasConsent, isReady, categories, acceptAll, declineAll } = useCookieConsent({
preset: 'default',
links: {
privacyPolicy: '/privacy',
cookiePolicy: '/cookies',
},
})
if (!isReady || hasConsent) return null
return (
<div className="my-custom-banner">
<h2>We use cookies</h2>
<button onClick={acceptAll}>Accept All</button>
<button onClick={declineAll}>Decline</button>
</div>
)
}Remote Configuration
1. Install Payload Plugin
// payload.config.ts
import { cookieConsentPlugin } from '@meui-creative/cookies/payload'
export default buildConfig({
plugins: [
cookieConsentPlugin({
enabled: true,
defaultVersion: '1.0.0',
}),
],
})2. Use in Frontend
<CookieConsent
preset="default"
apiUrl="https://your-cms.com/api/cookie-config"
links={{
privacyPolicy: '/privacy',
cookiePolicy: '/cookies',
}}
/>Remote config updates texts and categories. Style configuration remains local.
EU Legal Requirements
⚠️ Required for GDPR Compliance
1. Strict Mode
mode = 'strict' // Blocks cookies before consent2. Legal Links
links={{
privacyPolicy: '/privacy', // Required
cookiePolicy: '/cookies' // Required
}}3. Easy Reject
showSettingsButton={true} // Allow granular control
showRejectLink={true} // Easy rejection✅ Best Practices
- Use 6-12 month consent duration (max 24 months)
- Provide clear category descriptions
- Never pre-tick optional categories
- Only "strictly necessary" enabled by default
Browser Support
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- React 18+
- Next.js 13+
Latest: v2.1.0 - Google Consent Mode V2
- ✅ Full Google Consent Mode V2 support
- ✅ Automatic consent default and update
- ✅ All V2 parameters:
ad_user_data,ad_personalization - ✅ URL passthrough and ads data redaction
- ✅ Zero breaking changes
License
MIT © Meui Creative
