---
title: ConsentRoot
description: Mount the c15t banner, preference dialog and floating trigger in a
  Vue app with one ConsentRoot component from c15t/vue/vue-plugin.
group: frameworks
lastModified: "2026-10-10T16:01:45+01:00"
---
## Render `ConsentRoot` in your root component

Render `ConsentRoot` once in your root component, next to your page content.
Import it from `c15t/vue/vue-plugin`:

```vue title="src/App.vue"
<script setup lang="ts">
import { ConsentDialogLink, ConsentRoot } from 'c15t/vue/vue-plugin';
</script>

<template>
	<ConsentRoot />
	<main>
		<h1>c15t with Vue</h1>
		<p>PostHog loads after you allow measurement.</p>
	</main>
	<footer>
		<ConsentDialogLink>Privacy settings</ConsentDialogLink>
	</footer>
</template>
```

`ConsentRoot` reads the consent runtime that
[the c15tVue plugin](/docs/frameworks/vue/plugin) creates in `src/main.ts`.
Keep it in the root component so it stays mounted when the route changes.
It brings its own styles.

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

## What ConsentRoot renders

`ConsentRoot` picks the surfaces for the visitor's policy and the current
`activeUI`:

|Policy|`activeUI` is `'banner'`|`activeUI` is `'manager'`|
|--|--|--|
|Standard, opt-in or opt-out|[`ConsentBanner`](/docs/frameworks/vue/components/consent-banner)|[`ConsentManager`](/docs/frameworks/vue/components/consent-manager)|
|IAB TCF, with a vendor list|[`IABConsentBanner`](/docs/frameworks/vue/components/iab-consent-banner)|[`IABConsentDialog`](/docs/frameworks/vue/components/iab-consent-dialog)|

It also renders [`ConsentDialogTrigger`](/docs/frameworks/vue/components/consent-dialog-trigger)
when the `showTrigger` option is `true`.

Nothing renders until the visitor's policy has resolved. The dialog and the
IAB surfaces load as separate chunks. The IAB surfaces replace the standard
ones only when the `iab` option is set and the policy uses the `iab` model. After the page's `load` event,
`ConsentRoot` prefetches the dialog chunk in an idle moment, so the first
Customize click does not wait for the network. The dialog unmounts when it
closes.

## Theme tokens

`ConsentRoot` does not apply theme tokens. The c15tVue plugin adds every
token from the `tokens` option, including the defaults you did not set, to
`document.head` in a `<style id="c15t-css-vars">` element when you install
it, before the first render. Set token values through the `tokens` option
rather than a `:root` rule in your stylesheet. See
[customize](/docs/frameworks/vue/customize#set-theme-tokens).

## Props

|Prop|Type|Default|Behavior|
|--|--|--|--|
|`country`|`string`|The location the backend detects|Overrides the visitor's country and resolves the policy again.|
|`region`|`string`|The location the backend detects|Overrides the visitor's region, such as `CA`, and resolves the policy again.|
|`language`|`string`|The browser language|Overrides the language and resolves again, which fetches the banner and dialog text in that language.|

Setting any prop sends it to the backend with the next policy request. Use
`country` and `region` to preview another region's policy while you build.
Bind `language` to your site's language switcher:

```vue
<ConsentRoot :language="locale" />
```

## Compose the surfaces yourself

`ConsentRoot` is the same as rendering `ConsentBanner`, `ConsentManager` and
the IAB components with the right conditions. To place or configure them
yourself, render them in place of `ConsentRoot`, as in
[ConsentBanner](/docs/frameworks/vue/components/consent-banner#import-the-banner-into-your-root-component). Do not
render `ConsentRoot` next to them, or the visitor sees two banners.

## Verify

Load the app in a private window under a policy that asks for consent. The
banner appears after the policy request to your backend completes. In the
Elements panel, the `<style id="c15t-css-vars">` element in `<head>` holds
the `--c15t-*` tokens. Click Customize and the preference dialog opens. Reject,
reload, and confirm the banner stays closed.

## Next steps

* [c15tVue plugin](/docs/frameworks/vue/plugin) lists the options
  `ConsentRoot` reads.
* [Customize](/docs/frameworks/vue/customize) changes tokens, layout and
  slots.
* [Headless](/docs/frameworks/vue/headless) replaces `ConsentRoot` with your
  own markup.
