@lartisanenumerique/nuxt-cookie-consent
v0.1.1
Published
Bandeau de consentement aux cookies pour Nuxt.
Downloads
22
Readme
@lartisanenumerique/nuxt-cookie-consent
Module de consentement pour Nuxt 4. Il présente des catégories de finalités, enregistre le choix dans un cookie et permet au visiteur de modifier ou retirer son consentement.
Ce package est indépendant de @lartisanenumerique/nuxt-snackbar.
Installation
npm install @lartisanenumerique/nuxt-cookie-consentConfiguration Nuxt
Ajouter le module dans nuxt.config.ts :
export default defineNuxtConfig({
modules: ['@lartisanenumerique/nuxt-cookie-consent'],
cookieConsent: {
policyUrl: '/politique-de-confidentialite',
categories: [
{
key: 'necessary',
label: 'Services strictement nécessaires',
description: 'Indispensables au fonctionnement et à la sécurité du site.',
required: true,
},
{
key: 'analytics',
label: "Mesure d'audience",
description: 'Nous aide à comprendre quelles pages sont les plus utiles.',
},
{
key: 'diagnostics',
label: 'Diagnostic des erreurs',
description: 'Nous aide à détecter et corriger les problèmes techniques.',
},
{
key: 'external-media',
label: 'Contenus externes',
description: 'Autorise les vidéos, cartes et publications intégrées.',
},
],
},
})Puis rendre le composant une seule fois dans app/app.vue :
<template>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
<CookieConsent />
</template>Le composant et le composable sont auto-importés : aucun import manuel n'est
nécessaire dans l'application.
Fonctionnement
Lors de la première visite, la fenêtre compacte propose :
- « Tout refuser » ;
- « Personnaliser » ;
- « Tout accepter ».
La liste des catégories apparaît après un clic sur « Personnaliser ». Après le choix, une icône reste accessible en bas à gauche pour rouvrir directement les préférences.
La page est toujours rechargée après une acceptation, un refus ou une modification. Les plugins du projet peuvent ainsi relire le cookie au démarrage et ne charger que les services autorisés.
API de useCookieConsent
const consent = useCookieConsent()| Propriété ou méthode | Paramètres | Description |
| --- | --- | --- |
| categories | — | Catégories configurées dans nuxt.config.ts |
| consent | — | Choix enregistrés sous la forme { [key]: boolean } |
| hasAnswered | — | Indique si le consentement enregistré est complet et à la bonne version |
| isOpen | — | Indique si la fenêtre est ouverte |
| isCustomizing | — | Indique si la liste des catégories est affichée |
| open | customize? | Ouvre la fenêtre ; true affiche directement les catégories |
| close | — | Ferme la fenêtre sans modifier le choix |
| customize | — | Affiche les catégories dans la fenêtre ouverte |
| save | choices | Enregistre une sélection personnalisée puis recharge la page |
| acceptAll | — | Accepte toutes les catégories optionnelles puis recharge la page |
| refuseAll | — | Refuse toutes les catégories optionnelles puis recharge la page |
| hasConsent | key | Retourne true lorsque la catégorie est autorisée |
Vérifier une catégorie
const consent = useCookieConsent()
if (consent.hasConsent('analytics')) {
// La mesure d'audience est autorisée.
}Dans un template :
<template>
<YouTubePlayer v-if="consent.hasConsent('external-media')" />
<button v-else type="button" @click="consent.open(true)">
Autoriser les contenus externes
</button>
</template>
<script setup lang="ts">
const consent = useCookieConsent()
</script>Ouvrir la fenêtre
const consent = useCookieConsent()
consent.open() // ouvre directement les catégories
consent.open(true) // même comportement, explicite
consent.open(false) // ouvre la version compacteEnregistrer une sélection
consent.save({
necessary: true,
analytics: false,
diagnostics: true,
'external-media': false,
})Les catégories required: true restent toujours actives, même si la valeur fournie
à save est false.
Adapter les catégories à un client
Le consentement est enregistré par finalité, et non par prestataire.
| Service utilisé | Catégorie conseillée |
| --- | --- |
| Session, authentification, panier, mémorisation du consentement | necessary |
| Matomo, Google Analytics | analytics |
| Sentry | diagnostics |
| YouTube, Vimeo, Instagram, LightWidget, Google Maps | external-media |
Un outil technique n'est pas automatiquement strictement nécessaire. Par exemple,
Sentry reste normalement optionnel et appartient à diagnostics, pas à necessary.
Ne déclarer que les catégories réellement utilisées par le projet. Une application
qui n'intègre aucune vidéo, carte ou publication externe ne doit pas afficher
external-media.
Structure d'une catégorie
{
key: 'analytics',
label: "Mesure d'audience",
description: 'Description claire destinée au visiteur',
required: false,
}keyidentifie la catégorie dans le code ;labeletdescriptionsont affichés dans la fenêtre ;required: trueest réservé aux services strictement nécessaires.
Une catégorie optionnelle est toujours désactivée avant le consentement. L'option
defaultEnabled n'existe pas.
Si aucune catégorie n'est configurée, le module affiche uniquement une catégorie « Services strictement nécessaires » non désactivable.
Charger les services après consentement
Le module mémorise la décision, mais il ne charge ni ne bloque automatiquement Matomo, Sentry, LightWidget ou un autre prestataire. Le projet doit vérifier la catégorie avant d'insérer le script concerné.
Exemple LightWidget dans un plugin client :
export default defineNuxtPlugin(() => {
const consent = useCookieConsent()
if (!consent.hasConsent('external-media')) {
return
}
const script = document.createElement('script')
script.src = 'https://cdn.lightwidget.com/widgets/lightwidget.js'
script.async = true
document.head.appendChild(script)
})Ne pas déclarer directement ce script dans nuxt.config.ts : il serait téléchargé
avant la vérification du consentement.
Politique de confidentialité
La fenêtre présente les finalités. La page indiquée par policyUrl doit détailler la
liste exhaustive des services utilisés. Pour chacun, documenter au minimum :
- son nom et la société responsable ;
- sa finalité et sa catégorie ;
- les données ou traceurs concernés ;
- la durée de conservation lorsqu'elle est connue ;
- un lien vers la politique du prestataire ;
- la manière de retirer le consentement.
Options
| Option | Type | Valeur par défaut | Description |
| --- | --- | --- | --- |
| cookieName | string | cookie-consent | Nom du cookie enregistré |
| expiresInDays | number | 180 | Durée de conservation du choix |
| icon | string | icône intégrée | URL d'une icône personnalisée |
| policyUrl | string | /politique-de-confidentialite | Page contenant les informations détaillées |
| version | number | 1 | Version de la structure du consentement |
| showPreferencesButton | boolean | true | Affiche l'icône permanente de préférences |
| categories | CookieConsentCategory[] | catégorie nécessaire | Finalités proposées au visiteur |
| texts | CookieConsentTexts | textes français | Personnalisation des libellés |
Configuration complète :
cookieConsent: {
cookieName: 'cookie-consent',
expiresInDays: 180,
icon: '/img/cookie-personnalise.webp',
policyUrl: '/politique-de-confidentialite',
version: 1,
showPreferencesButton: true,
categories: [],
texts: {
title: 'Vos préférences de confidentialité',
description: 'Texte introductif adapté au projet.',
acceptAll: 'Tout accepter',
refuseAll: 'Tout refuser',
customize: 'Personnaliser',
save: 'Enregistrer mes choix',
close: 'Fermer sans modifier mes choix',
preferences: 'Gérer mes préférences de confidentialité',
policy: 'En savoir plus',
},
}Icône personnalisée
Placer l'image dans le dossier public du projet :
public/img/cookie-personnalise.webpPuis utiliser :
cookieConsent: {
icon: '/img/cookie-personnalise.webp',
}Sans icon, le module utilise son illustration originale librement distribuable.
Changer les catégories en production
Lorsque les catégories ou leur signification changent, augmenter version :
cookieConsent: {
version: 2,
categories: [
// nouvelle configuration
],
}Le consentement de l'ancienne version devient invalide et le visiteur est invité à choisir de nouveau.
Validation
Le démarrage de Nuxt échoue lorsque :
- deux catégories utilisent la même clé ;
- une clé contient autre chose que des lettres minuscules, chiffres ou tirets ;
- un label ou une description est vide ;
- aucune catégorie n'utilise
required: true; - l'ancienne option
defaultEnabledest encore présente.
Accessibilité
La fenêtre :
- reçoit le focus à son ouverture ;
- se ferme avec
Échap; - conserve la navigation au clavier à l'intérieur ;
- rend le focus à l'icône après fermeture ;
- respecte
prefers-reduced-motion.
Limite de responsabilité
Le module gère l'interface, les catégories et la sauvegarde. La conformité finale dépend également de la configuration du projet, du blocage effectif des services optionnels et du contenu de la politique de confidentialité.
