Skip to main content

Nuxt Components

ConsentRoot

Render ConsentRoot in app.vue

The Nuxt module registers ConsentRoot globally, so you render it without an import. Put it in app.vue, next to <NuxtPage />:

app/app.vue
<template>
	<ConsentRoot />
	<NuxtPage />
	<footer>
		<ConsentDialogLink>Privacy settings</ConsentDialogLink>
	</footer>
</template>

ConsentRoot reads the consent runtime the module creates. Keep it in app.vue so it stays mounted when the route changes. It brings its own styles.

ConsentRoot is not a provider. The module's plugin already gives every component the consent runtime, so nothing needs to sit inside it. Render <ConsentRoot /> next to <NuxtPage /> as shown above. If you wrap the app in it instead, the page still renders after the banner, dialog and trigger, but wrapping adds nothing.

Always mount the Nuxt ConsentRoot, not the Vue one from c15t/vue/vue-plugin. The Nuxt component renders the banner on the server.

What ConsentRoot renders

ConsentRoot picks the surfaces for the visitor's policy:

PolicyBannerPreferences
Standard, opt-in or opt-outConsentBannerConsentManager
IAB TCF, with a vendor listIABConsentBannerIABConsentDialog

It also renders ConsentDialogTrigger when the showTrigger option is true.

The banner is part of the server render. When the server resolves the policy, in the default manifest() mode or hosted(), a visitor whose policy asks for consent gets the banner in the first HTML, with no layout shift after hydration. On prerendered and cached routes the banner appears after the browser resolves the policy. See rendering.

The IAB surfaces replace the standard ones only when the module's iab option is set and the policy uses the iab model. The dialog and the IAB surfaces load as separate chunks. ConsentRoot prefetches the dialog chunk after the page's load event, mounts the dialog the first time preferences open, and keeps it mounted after that so its close animation runs.

The banner and the trigger are separate chunks too, so their CSS is not part of your app's entry stylesheets. Every page preloads the banner chunk. With Nuxt's features.inlineStyles, on by default, it also preloads the banner's CSS instead of linking it: a server-rendered banner paints with the styles Nuxt writes into the page head, so no c15t stylesheet blocks the first paint. The browser applies the CSS with the chunk, before it shows a banner it renders itself. The trigger chunk loads after the page mounts, and only when showTrigger is true.

Theme tokens

The Nuxt module's plugin, not ConsentRoot, writes the tokens option into a <style id="c15t-css-vars"> tag in the page head, on every page and with the module's nonce. During server rendering and prerendering the tag is in the first HTML. See customize.

Props

PropTypeDefaultBehavior
countrystringThe location from the request headersOverrides the visitor's country and resolves the policy again.
regionstringThe location from the request headersOverrides the visitor's region, such as CA, and resolves the policy again.
languagestringThe browser languageOverrides the language and resolves the policy again, which fetches the banner and dialog text in that language.

Use country and region to preview another region's policy while you build, such as <ConsentRoot country="DE" />. Bind language to your site's current language. See translations.

Compose the surfaces yourself

ConsentRoot is the same as rendering the banner, dialog and trigger with the right conditions. To place them yourself, render them in place of ConsentRoot, as in ConsentBanner. Do not render ConsentRoot next to them, or the visitor sees two banners.

Verify

Build and start the app, then view the source of a page under a policy that asks for consent. The HTML holds data-testid="consent-banner-root" and the c15t-css-vars style tag. Click Customize and the preference dialog opens. Reject, reload, and confirm the banner stays closed.

Next steps

  • Nuxt module lists the options ConsentRoot reads.
  • Customize changes tokens, layout and slots.
  • Headless replaces ConsentRoot with your own markup.