Consent Management
What the consent abstraction does
A storefront usually loads scripts from several vendors (analytics, ads, chat, retargeting). Each vendor needs the visitor's consent before it runs, and what consent is given for is a purpose — why the data is processed — not a vendor. Laioutr's consent layer separates the two: your code asks "does the visitor consent to analytics?" and the active CMP (Cookiebot, CCM19, OneTrust, custom) answers. Switching CMPs later is a config change, not a rewrite.
The abstraction gives you a consent store with five fixed purposes and a provider-agnostic useConsentStore() composable. A consent adapter maps a concrete CMP's own vocabulary onto them. Other Laioutr features (tracking, GTM) read the store too, so a single source of truth gates every consented behaviour in the frontend.
const consentStore = useConsentStore();
if (consentStore.hasPurposeConsent('analytics')) {
loadHeatmapScript();
}
The store lives in @laioutr-core/frontend-core. Your Nuxt app must include the module so useConsentStore() and the #frontend/consent types are available.
The five consent purposes
Every adapter translates its CMP's own vocabulary into this fixed shape, so the rest of the app only deals with one model:
| Purpose | Typical use |
|---|---|
necessary | Essential processing (session, security, CSRF). Always true, not user-toggleable. |
functional | Preferences and functionality (language, cart, recently viewed, embeds). |
analytics | Measurement and performance (GA, heatmaps, session replay). |
advertising | Advertising and its measurement (ad pixels, retargeting, conversion tracking). |
personalization | Tailoring content or ads to the individual. |
The store keeps a single state object with these five booleans. Whenever the visitor accepts or revokes something in the CMP, the active adapter pushes the change into the store, and state updates reactively.
A purpose describes processing; a cookie category classifies an artifact. The two are not the same question, and only the first one has an answer for every recipient — a server-side subscriber forwarding orders to a warehouse writes nothing to the browser, so it has no category, but it plainly has a purpose. Adapters therefore report purposes, and a CMP that models categories maps them across. Where a CMP's vocabulary is coarser than ours the mapping loses precision: Cookiebot has one marketing bucket, so it grants advertising and personalization together and a visitor cannot separate them. That is a property of the CMP, not of this API.
Using the consent store
useConsentStore() is scoped to the Nuxt app rather than shared as a process-wide global. On the server that means one store per request: consent is request data, and a process-global would hand one visitor's answers to the next. Auto-imported by frontend-core, you can call it from any component, composable, or plugin.
The methods you will use most:
| Method | What it does |
|---|---|
state | Readonly reactive ConsentState. Watch it to react to consent changes. |
adapterName | ComputedRef<string | null> — the installed adapter's name, or null when no adapter is installed. |
hasPurposeConsent(purpose) | Returns true if the purpose is granted. With no adapter active, only necessary returns true. |
getPurposeConsents() | The whole ConsentState as a plain object, for a consumer that needs the full allow/deny picture. |
hasDecision() | Whether the visitor has actually answered. Returns boolean | undefined — see below. |
openConsentUi(view?) | Opens the CMP's banner, or its granular preferences panel with 'preferences'. Wire this to a "Cookie preferences" link. |
onConsentChange(callback) | Registers a watcher on the store state. The callback receives the full ConsentState whenever it changes. |
hasDecision() can return undefined as well as true or false. undefined means no decision signal exists at all — either no CMP adapter is installed, or the installed one has no way to report whether the visitor answered. That is not the same as a visitor who was asked and declined; treat undefined as "unknown", not as "no".
showConsentOverlay() and renewConsent() no longer exist. Replace showConsentOverlay() with openConsentUi() and renewConsent() with openConsentUi('preferences').A typical "Cookie preferences" footer link:
<script setup lang="ts">
const consentStore = useConsentStore();
</script>
<template>
<button type="button" @click="consentStore.openConsentUi()">
Cookie preferences
</button>
</template>
Reacting to consent changes outside a template (for example, lazy-loading a chat widget once the visitor accepts advertising):
const consentStore = useConsentStore();
consentStore.onConsentChange((consent) => {
if (consent.advertising) {
loadChatWidget();
}
});
How other features read consent
The store is consumed across the platform, not just by your code:
- The analytics layer gates delivery per destination. A destination declares
consent: { purposes: ['analytics'] }, and the bus only hands it an event once that purpose is granted. A destination may also declareonDeniedto receive events under refusal in a degraded form rather than going silent. Read the state directly withhasPurposeConsent('analytics')orgetPurposeConsents(). - The GTM app sets Google Consent Mode v2 defaults to
deniedinline in the head, beforegtm.jsloads, then sends an update once the visitor has actually answered — not when the CMP merely reports its default.
This means once a CMP adapter is active and the user has accepted analytics, GA fires through GTM without any further wiring in your app.
Ready-to-use consent apps
There already are a few standalone Laioutr apps that register a ConsentAdapter for you: the Cookiebot app and the CCM19 app. Add the module, set the credentials, and the store and tracking/GTM consent are wired up.
Building your own consent adapter
If you need a CMP that is not on the list (OneTrust, CookieYes, an in-house solution), you can build a Laioutr app that registers a ConsentAdapter with the store. The full contract, plugin boilerplate, and worked examples drawn from the Cookiebot and CCM19 sources live in Consent Adapters under app development.
Summary
- One store, five purposes, one set of methods. Write your code against
useConsentStore()and stop caring about which CMP is behind it. - Use
hasPurposeConsent(purpose)to gate behaviour,onConsentChangeto react, andopenConsentUifor "Cookie preferences" UI. - Drop in Cookiebot or CCM19 for ready-to-use providers, or build your own following the Consent Adapters guide.
Features
What ships with the Laioutr frontend. Capabilities and building blocks that come with the platform — from PWA and consent management to tracking and how to use or extend them.
Content Preview
Let editors see unpublished content on the live storefront by opening any URL with a preview token. Server-verified, server-rendered, and never cached.