@studio-fes/iubenda

Nuxt module for iubenda Cookie Solution — locale-aware config, script loading via @nuxt/scripts, auto-imported listener composables.
1,180
Install
npm install @studio-fes/iubenda
Latest Version:0.1.9
Vue:3
License:MIT
Last Updated:Sep 17, 2026
Links: npm
Maintainer: plcdnl

iubenda

@studio-fes/iubenda

Locale-aware iubenda Cookie Solution module for Nuxt — script loading via @nuxt/scripts, auto-imported listener composables.


Features

  • Locale-aware — automatically picks the right cookiePolicyId based on @nuxtjs/i18n locale (falls back to en)
  • Script bundling — stub and CS scripts are bundled with @nuxt/scripts; autoblocking uses a plain <script> to avoid CDN CORS issues
  • Auto-imported composables — useIubenda() and all onIubenda* listeners are available without any imports
  • Late-subscriber safe — once-events (ready, consentRead, …) replay immediately to components that mount after the event fired
  • TypeScript — full types for all module options and composables

Setup

npm install @studio-fes/iubenda
# or
pnpm add @studio-fes/iubenda

Add the module to your nuxt.config.ts:

export default defineNuxtConfig({
  modules: ['@studio-fes/iubenda'],

  iubenda: {
    siteId: 123456,           // your iubenda Site ID
    cookiePolicyIds: {
      en: 78901234,           // cookie policy document ID per locale
      it: 87654321,
    },
  },
})

Then call useIubenda() once — typically in your root app.vue — to load and initialize the Cookie Solution:

<script setup>
useIubenda()
</script>

That's it. The banner appears automatically on the first visit.


Environment variables

siteId and cookiePolicyIds can be set (or overridden) via environment variables instead of hardcoding them in nuxt.config.ts. This is useful for multi-environment deployments or keeping credentials out of source control.

Variable Config equivalent
NUXT_PUBLIC_IUBENDA_SITE_ID iubenda.siteId
NUXT_PUBLIC_IUBENDA_COOKIE_POLICY_IDS_EN iubenda.cookiePolicyIds.en
NUXT_PUBLIC_IUBENDA_COOKIE_POLICY_IDS_IT iubenda.cookiePolicyIds.it

The locale suffix follows Nuxt's convention: uppercase the key name (en → _EN, pt-BR → _PT_BR).

Env vars and nuxt.config.ts can be mixed — env vars take precedence:

// nuxt.config.ts — safe to commit, no secrets
export default defineNuxtConfig({
  modules: ['@studio-fes/iubenda'],
  iubenda: {
    banner: {
      position: 'float-bottom-center',
    },
  },
})
# .env — gitignored
NUXT_PUBLIC_IUBENDA_SITE_ID=123456
NUXT_PUBLIC_IUBENDA_COOKIE_POLICY_IDS_EN=78901234
NUXT_PUBLIC_IUBENDA_COOKIE_POLICY_IDS_IT=87654321

Options

Required (config or env)

Both options are required at runtime but can come from nuxt.config.ts or environment variables (see Environment variables).

Option Type Description
siteId number Your iubenda Site ID (found in the iubenda dashboard under Sites & Apps)
cookiePolicyIds Record<string, number> Cookie policy document ID per locale code (e.g. { en: 123, it: 456 })

Module behaviour

Option Type Default Description
autoblocking boolean true Load the autoblocking script
injectCss boolean true Inject the module's default stylesheet
bundle boolean true Bundle the iubenda stub and CS scripts with @nuxt/scripts

Consent behaviour

Option Type Default Description
consentOnContinuedBrowsing boolean false Treat continued browsing as implicit consent
invalidateConsentWithoutLog boolean | string true Invalidate consent when no server log entry exists. Pass a 'YYYY-MM-DD' string to use a cutoff date
reloadOnConsent boolean false Reload the page after consent is collected
askConsentAtCookiePolicyUpdate boolean false Re-ask consent when the cookie policy is updated
enableRemoteConsent boolean false Enable cross-site consent recording
googleConsentMode boolean | 'template' | null null Google Consent Mode integration (null = auto-detect)
invalidateConsentBefore string | number — Revoke all consents collected before this date ('YYYY-MM-DD' or epoch ms)

Regulations

Option Type Default Description
enableGdpr boolean true Enable GDPR support
gdprAppliesGlobally boolean true Apply GDPR regardless of user location
countryDetection boolean false Auto-detect country to conditionally apply regulations
enableCcpa boolean false Enable CCPA support
enableLgpd boolean false Enable LGPD support
enableTcf boolean false Enable IAB TCF v2 support

Banner

Configure the banner appearance and text under the banner key:

iubenda: {
  siteId: 123456,
  cookiePolicyIds: { en: 78901234, it: 87654321 },

  banner: {
    position: 'float-bottom-center',
    backgroundColor: '#1a1a1a',
    acceptButtonColor: '#00dc82',
    rejectButtonColor: '#555',

    // per-locale button labels
    acceptButtonCaptions: { en: 'Allow all', it: 'Consenti tutto' },
    rejectButtonCaptions: { en: 'Only necessary', it: 'Solo necessari' },

    // per-locale banner HTML (%{cookie_policy_link} is replaced automatically)
    contents: {
      en: '<div class="iubenda-cs-title">Cookies</div><div class="iubenda-cs-paragraph">We use cookies. See our %{cookie_policy_link}.</div>',
      it: '<div class="iubenda-cs-title">Cookie</div><div class="iubenda-cs-paragraph">Utilizziamo cookie. Vedi la nostra %{cookie_policy_link}.</div>',
    },
  },
}
Banner options reference
Option Type Default Description
position string 'float-top-center' Banner position ('top', 'bottom', 'float-top-left', 'float-bottom-right', …)
backgroundOverlay boolean false Dim the page with an overlay
backgroundColor string '#000' Banner background color
textColor string '#fff' Banner text color
acceptButtonColor string '#0073ce' Accept button background
rejectButtonColor string '#0073ce' Reject button background
logo string — Logo URL or base64 image
perPurposeConsent boolean false Enable granular per-category consent
floatingPreferencesButtonDisplay boolean | string false Show a floating preferences widget
acceptButtonCaptions Record<string, string> — Accept button label per locale
rejectButtonCaptions Record<string, string> — Reject button label per locale
contents Record<string, string> — Full banner HTML per locale

Composables

useIubenda()

Loads and initializes the Cookie Solution. Call it once in app.vue (or a root layout).

<script setup>
useIubenda()
</script>

Listener composables

All listeners are auto-imported. They handle component lifecycle automatically — the callback is registered on mount and cleaned up on unmount.

Once-events (fire at most once per page load) also replay immediately to components that mount after the event has already fired, so you never miss them.

Lifecycle
// Fired when the CS is ready. `consent` is true if existing consent was found.
onIubendaReady((consent: boolean) => { ... })

onIubendaBeforePreload(() => { ... })
onIubendaBannerShown(() => { ... })
onIubendaBannerClosed(() => { ... })
onIubenda2ndLayerShown(() => { ... })
Consent
onIubendaConsentGiven(() => { ... })
onIubendaConsentFirstGiven((source: IubendaConsentFirstGivenSource) => { ... })
onIubendaConsentRejected(() => { ... })
onIubendaConsentFirstRejected(() => { ... })

// Fires on first consent AND on every page load where consent already exists
onIubendaConsentRead(() => { ... })

onIubendaPreferenceExpressed(() => { ... })
onIubendaPreferenceFirstExpressed(() => { ... })

// Fires when a preference is given OR when consent is not required (non-GDPR user)
onIubendaPreferenceExpressedOrNotNeeded(
  (preference: { purposes?: Record<number, boolean> } | false) => { ... }
)
onIubendaPreferenceNotNeeded(() => { ... })
onIubendaActivationDone(() => { ... })
Cookie policy
onIubendaCookiePolicyShown(() => { ... })
CCPA
onIubendaCcpaAcknowledged(() => { ... })
onIubendaCcpaFirstAcknowledged(() => { ... })
onIubendaCcpaOptOut(() => { ... })
onIubendaCcpaFirstOptOut(() => { ... })
Errors
onIubendaError((error: string) => { ... })
onIubendaFatalError((error: string) => { ... })
onIubendaStartupFailed((error: string) => { ... })

Example

<script setup>
useIubenda()

onIubendaPreferenceExpressedOrNotNeeded((preference) => {
  if (!preference) return // consent not required for this user
  const { purposes } = preference
  if (purposes?.[4]) {
    // measurement/analytics consent given — initialize analytics
  }
})
</script>

Customising the styles

The module ships a default stylesheet (injected automatically unless injectCss: false). There are three ways to customise it, from lightest to heaviest.


1. CSS custom properties (recommended for design tokens)

The default stylesheet exposes a set of --iubenda-* CSS custom properties. Override only what you need — everything else keeps its default:

Variable Role Default
--iubenda-spacing Base spacing unit 4px
--iubenda-font-sans Title / body font system-ui, sans-serif
--iubenda-font-mono Button font ui-monospace, monospace
--iubenda-color-backdrop Banner card background tint #64748b
--iubenda-color-text Banner text color #ffffff
--iubenda-color-btn-bg Reject / secondary button background #1a1a1a
--iubenda-color-btn-text Reject / secondary button text #ffffff
--iubenda-color-btn-hover Reject / secondary button hover #333333
--iubenda-color-btn-accept-bg Accept button background #ffffff
--iubenda-color-btn-accept-text Accept button text #000000
--iubenda-color-btn-accept-hover Accept button hover #e5e5e5

All variables are scoped to #iubenda-cs-banner — they don't leak into the rest of your project.

/* app.css — override only what you need */
#iubenda-cs-banner {
  --iubenda-color-backdrop: #1e293b;
  --iubenda-color-btn-accept-bg: #00dc82;
  --iubenda-color-btn-accept-text: #000;
  --iubenda-color-btn-accept-hover: #00c472;
  --iubenda-font-sans: 'Inter', system-ui, sans-serif;
}

To connect the banner tokens to your own design system:

#iubenda-cs-banner {
  --iubenda-spacing: var(--spacing);           /* Tailwind v4 */
  --iubenda-font-sans: var(--font-sans);
  --iubenda-color-backdrop: var(--color-slate-700);
}

2. Override specific selectors (for targeted tweaks)

All banner elements share the #iubenda-cs-banner root ID, so specificity is easy to beat with a class or :root selector in your global CSS:

/* Override the banner card background */
#iubenda-cs-banner .iubenda-banner-content {
  background: rgba(10, 10, 10, 0.85);
  border-radius: 12px;
}

/* Make buttons pill-shaped */
#iubenda-cs-banner button {
  border-radius: 999px;
  font-family: 'Inter', sans-serif;
  text-transform: none;
}

/* Swap accept/reject button colours individually */
#iubenda-cs-banner .iubenda-cs-btn-accept {
  background: #00dc82;
  color: #000;
}
#iubenda-cs-banner .iubenda-cs-btn-reject {
  background: transparent;
  color: #fff;
  border: 1px solid #fff;
}

These rules go in your project's global stylesheet (e.g. assets/main.css, imported in nuxt.config.ts via css: ['~/assets/main.css']).


3. Disable the module CSS and write your own (full control)

Set injectCss: false to skip the module stylesheet entirely, then write your own from scratch targeting the same selectors:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@studio-fes/iubenda'],
  css: ['~/assets/iubenda-custom.css'],
  iubenda: {
    injectCss: false,
    siteId: 123456,
    cookiePolicyIds: { en: 78901234 },
  },
})
/* assets/iubenda-custom.css — full banner structure */
#iubenda-cs-banner { /* banner wrapper */ }
#iubenda-cs-banner .iubenda-cs-container { /* inner card */ }
#iubenda-cs-banner .iubenda-banner-content { /* content area */ }
#iubenda-cs-banner .iubenda-cs-title { /* title */ }
#iubenda-cs-banner .iubenda-cs-paragraph { /* body text */ }
#iubenda-cs-banner .iubenda-cs-opt-group-consent { /* accept/reject button row */ }
#iubenda-cs-banner .iubenda-cs-btn-accept { /* accept button */ }
#iubenda-cs-banner .iubenda-cs-btn-reject { /* reject button */ }

Note: The banner.applyStyles: false option is set internally by the module to prevent iubenda's own CDN stylesheet from loading. This stays in effect regardless of injectCss.


Development

# Install dependencies
pnpm install

# Build the module stub and prepare the playground
pnpm dev:prepare

# Start the playground dev server
pnpm dev

# Run tests
pnpm test

# Build for release
pnpm prepack

License

MIT

Related Packages

@studio-fes/layer-strapi

Create Nuxt extendable layer with this GitHub template.

7,092
@studio-fes/layer-base

Base Nuxt layer with shared utilities, components, and configurations for buildi...

8,749
@studio-fes/layer-craft

Nuxt layer for Craft CMS integration with GraphQL and advanced caching capabilit...

7,897
@studio-fes/create-fes-app

Interactive wizard to scaffold a new project from the studio fes Nuxt layers sta...

2,277

Version History

Version Released Vue License
0.1.9 ^3.0 MIT
0.1.8 ^3.0 MIT
0.1.7 ^3.0 MIT
0.1.6 ^3.0 MIT
0.1.5 ^3.0 MIT