@studio-fes/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
cookiePolicyIdbased on@nuxtjs/i18nlocale (falls back toen) - 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 allonIubenda*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: falseoption is set internally by the module to prevent iubenda's own CDN stylesheet from loading. This stays in effect regardless ofinjectCss.
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
Base Nuxt layer with shared utilities, components, and configurations for buildi...
Nuxt layer for Craft CMS integration with GraphQL and advanced caching capabilit...
Interactive wizard to scaffold a new project from the studio fes Nuxt layers sta...
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 | |
| 0.1.4 | ^3.0 | MIT |