@superbiche/nuxt-umami-cnil

Nuxt module for self-hosted Umami under the CNIL audience-measurement exemption: no query strings, origin-only referrers, no ids, visitor opt-out, correct page titles.
455
Install
npm install @superbiche/nuxt-umami-cnil
Latest Version:0.1.1
Vue:3
License:MIT
Last Updated:Oct 8, 2026
Links: GitHub  ·  npm
Maintainer: superbiche

@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

nuxt-foresite

Foresite for Nuxt: privacy-first website analytics with no cookies.

288 0
@databuddy/nuxt

Official Databuddy Nuxt module

2,572 1,204
@ciphera-net/pulse-nuxt

Add Pulse Analytics — privacy-first web analytics — to a Nuxt site with one modu...

505 0
nuxt-measuremysite

Nuxt module for measuremy.site: cookieless web analytics your AI agent can read.

0 0
@ascencia/sarutobi-vue

Plugin et composable Vue pour Sarutobi.

0

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