@superbiche/nuxt-umami-cnil
| Install | |
|---|---|
npm install @superbiche/nuxt-umami-cnil |
|
| Latest Version: | 0.1.1 |
| Vue: | 3 |
| License: | MIT |
| Last Updated: | Oct 8, 2026 |
| Links: | GitHub · npm |
@superbiche/nuxt-umami-cnil
Nuxt 3/4 module for a self-hosted Umami that follows the CNIL audience-measurement exemption profile:
- page URLs are sent without query string or hash (no UTM parameters, no ad click IDs);
- an external referrer is reduced to its origin and only the landing view carries it; internal referrers are dropped;
- no distinct id is ever sent;
- the visitor can object: the choice is stored in
localStorage(umami.disabled, Umami's own flag) and enforced at the send boundary, including for calls queued while the script was still loading; - each page view carries its own title (sent once Nuxt has written the new page's head, not before).
It loads Umami's own script.js with automatic tracking off and drives it
from the router, with a data-before-send hook applied to every payload.
Install
npm install @superbiche/nuxt-umami-cnil@0.1.1 --save-exact
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@superbiche/nuxt-umami-cnil'],
umamiCnil: {
scriptUrl: 'https://analytics.example.com/script.js',
websiteId: '00000000-0000-0000-0000-000000000000',
// Optional: only send from these hostnames.
domains: ['example.com', 'www.example.com'],
},
})
Every option is also public runtime config, so it can be set per
environment: NUXT_PUBLIC_UMAMI_CNIL_SCRIPT_URL,
NUXT_PUBLIC_UMAMI_CNIL_WEBSITE_ID, NUXT_PUBLIC_UMAMI_CNIL_ENABLED=false
(e.g. for preview builds). Without a valid script URL and website id the
module does nothing.
| Option | Default | |
|---|---|---|
enabled |
true |
false: never measure. |
scriptUrl |
'' |
https://…/script.js (plain https host and path). |
websiteId |
'' |
Umami website id (UUID). |
domains |
[] |
data-domains; empty: any hostname. |
legacyOptOutKeys |
[] |
Older localStorage flags (value '1') that still count as an objection. |
beforeSendName |
'umamiCnil' |
Global name of the before-send hook. |
Use
const umami = useUmamiCnil()
umami.trackEvent('newsletter_signup', { source: 'footer' })
// Privacy page: let the visitor object (client-side, e.g. in onMounted).
const measured = ref(!umami.isOptedOut())
function toggle(on: boolean) {
const persisted = umami.setOptedOut(!on) // false: storage blocked, choice holds for this visit only
measured.value = on
}
Event data must not identify a person (no emails, names, order numbers, user ids, typed search terms).
A website chosen at runtime (e.g. from a CMS payload) takes precedence over the build config; set it before the first page finishes rendering, e.g. in a client plugin:
export default defineNuxtPlugin(() => {
useUmamiCnilSite().value = { scriptUrl, websiteId }
})
The framework-free core (before-send hook, opt-out store, controller) is
exported from @superbiche/nuxt-umami-cnil/core.
Privacy notice
The exemption also requires telling visitors. State at least: the tool and who hosts it, what is collected (pages, referrer domain, device and browser type, country, events), that no cookie is set and no IP is stored, the retention period, and how to object (link to the toggle).
License
MIT
Related Packages
Add Pulse Analytics — privacy-first web analytics — to a Nuxt site with one modu...
Nuxt module for measuremy.site: cookieless web analytics your AI agent can read.
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 0.1.1 | ^3.0 | MIT | |
| 0.1.0 | ^3.0 | MIT |
Pre-releases (1)
| Version | Released | License |
|---|---|---|
| 0.0.0-stage |