DEV Community

Cover image for Nuxt 3: Flexible Cookie Consent Module
criting
criting

Posted on

Nuxt 3: Flexible Cookie Consent Module

A Simple, Flexible Cookie Consent Module for Nuxt 3 — Still in Development

Cookie banners have become a default requirement in modern websites — but most solutions I found for Nuxt were either too bloated, too opinionated, or overly complex just to get a consent banner working.

So I decided to build my own — headless, fully customizable, and Nuxt 3-native.

Introducing: nuxt-simple-cookie-consent

A lightweight module that gives you full control over cookie categories, script injection, consent logic, and expiration — while staying out of your way when it comes to styling and UI.


Why I Built This

Most cookie modules I tried:

  • Forced a UI I didn’t want
  • Didn’t let me control the UX
  • Were hard to integrate into my Nuxt/Vue composables
  • Didn’t handle script injection cleanly

I just wanted something simple: give me the logic, and let me build my own UI on top.


Features

Here’s what it currently supports out of the box:

  • Headless design – You build the banner, modals, toggles — I just give you the reactive state and logic
  • Categorized script control – Group scripts into analytics, ads, or anything you want
  • Support for multi-category scripts – e.g. a single script can belong to both analytics and ads
  • Required categories – Enforce required scripts that users can’t disable
  • Auto-injection and removal – Based on real-time preferences
  • Consent expiration – Re-prompt users after a configurable duration (e.g. 180 days)
  • Consent versioning – Force re-consent if your cookie policy changes
  • Event hooks – Listen to consent lifecycle events like:
    • onConsentAccepted
    • onConsentDenied
    • onCategoryAccepted(category)
    • onScriptsInjected(category)
    • onScriptsRemoved(category)
  • SSR-safe – All scripts only run on the client, avoiding hydration mismatch
  • Inline & pixel support – Use <script>, inline JS, custom HTML, <iframe>, etc.
  • Google Tag Manager Consent Mode support (gtag('consent', 'update', {...}))
  • Built-in dev helpers – resetPreferences(), isConsentExpired, debug-friendly structure

Example Nuxt Config

export default defineNuxtConfig({ modules: ['nuxt-simple-cookie-consent'], cookieConsent: { cookieName: 'cookie_consent', expiresInDays: 180, consentVersion: '1.0.0', gtmConsentMapping: { analytics: 'analytics_storage', ads: 'ad_storage', }, categories: { analytics: { label: 'Analytics', description: 'Used to improve performance.', }, ads: { label: 'Ads', description: 'Helps personalize advertising.', }, }, scripts: [ { id: 'gtag-main', src: 'https://www.googletagmanager.com/gtag/js?id=GA_ID', async: true, defer: true, categories: ['analytics'], }, { id: 'gtag-inline', customContent: ` window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'GA_ID'); `, categories: ['analytics'], }, { id: 'ads', src: 'https://ads.example.com/script.js', categories: ['ads'], }, { id: 'fb-pixel', customHTML: ` <iframe src="https://facebook.com/track.html" height="1" width="1" style="display:none"></iframe> `, categories: ['ads'], }, ], }, }) 
Enter fullscreen mode Exit fullscreen mode

Composable API

You can build your own UI using the built-in composable:

const { preferences, categoryMeta, acceptAll, denyAll, acceptCategories, resetPreferences, hasUserMadeChoice, isConsentExpired } = useCookieConsent() 
Enter fullscreen mode Exit fullscreen mode

Hook into lifecycle events:

onConsentAccepted(() => { console.log('Consent accepted') }) onConsentDenied(() => { console.log('Consent denied') }) onCategoryAccepted(({ category }) => { console.log('Category accepted:', category) }) onScriptsInjected(({ category }) => { console.log('Scripts injected for category:', category) }) onScriptsRemoved(({ category }) => { console.log('Scripts removed for category:', category) }) 
Enter fullscreen mode Exit fullscreen mode

Still Experimental

This module is actively being developed. While the core features work, it still needs more testing in various setups:

  • Do scripts load/unload correctly across multiple categories?
  • Is consent stored and respected properly?
  • How does it behave with third-party tag managers or inline scripts?

Contribute or Give Feedback

GitHub: https://github.com/criting/nuxt-simple-cookie-consent

  • Found a bug?
  • Have ideas for improvements?
  • Want to contribute?

Pull requests, discussions, and constructive critique are very welcome.

Top comments (0)