Skip to main content

Vue Components

ConsentGate

Import ConsentGate and wrap an embed

Import ConsentGate from c15t/vue/vue-plugin. Put the embed in the default slot and a placeholder in the placeholder slot:

src/VideoEmbed.vue
<script setup lang="ts">
import { ConsentDialogLink, ConsentGate } from 'c15t/vue/vue-plugin';
</script>

<template>
	<ConsentGate category="measurement">
		<iframe
			src="https://www.youtube-nocookie.com/embed/czTksCF6X8Y"
			title="YouTube video"
			loading="lazy"
			allowfullscreen
		/>
		<template #placeholder>
			<p>Allow measurement to load this YouTube video.</p>
			<ConsentDialogLink>Choose video permissions</ConsentDialogLink>
		</template>
	</ConsentGate>
</template>

The iframe is absent from the page until the visitor allows measurement. The placeholder uses ConsentDialogLink so the visitor can open preferences from it.

What ConsentGate renders

ConsentGate renders its default slot while the visitor's effective permission for category is granted, and its placeholder slot otherwise. It adds no wrapper element. While permission is denied, the default slot does not exist in the DOM, so an iframe or widget inside it sends no requests. When the visitor withdraws permission, Vue removes the slot content.

Permission is the same value useConsent() returns for the category. It can be granted under an opt-out policy before the visitor has recorded a choice, and a privacy signal such as Global Privacy Control can deny a category the visitor granted.

Without a placeholder slot, the gate renders the same placeholder as the React and Svelte gates. It shows the consentGate.title text with the category name, and a button labelled with consentGate.actionButton that opens the preference dialog. Under a strict policy that leaves the category out, no choice can allow the content, so the placeholder shows consentGate.policyBlocked and no button. The text is in the visitor's language once init has delivered copy, and in English until then. The placeholder is a card styled by your theme tokens and the --consent-gate-placeholder-* variables. A placeholder slot replaces it entirely.

To restyle the built-in placeholder instead, set its parts under components['consent-gate'] in the options. root is the card, and title and button are its text and button. Use Vue attribute names such as class and style. The consentGate, consentGateTitle and consentGateButton theme slots reach the same parts. The placeholder carries data-testid="consent-gate-placeholder", its title data-testid="consent-gate-title" and its button data-testid="consent-gate-button".

ConsentGate also adds its category to the categories the preference dialog lists, so the button opens a dialog where the visitor can allow it.

Props and slots

NameKindTypeBehavior
categoryProp, required'necessary' | 'functionality' | 'measurement' | 'experience' | 'marketing'The category whose permission gates the default slot.
defaultSlotThe gated content, such as an iframe.
placeholderSlotShown while the category is denied.

Accessibility

Give the iframe a descriptive title. Keep a way to reach the content without the embed, such as a link or a transcript, for visitors who decline the category. A policy can fix a category as denied, so opening preferences does not guarantee the visitor can allow it.

Verify

Load the page in a private window with the Network tab open. The placeholder shows and no request goes to the embed's host. Allow the category in preferences and save: the iframe appears and its requests start. Withdraw the category and save: the page reloads without the iframe.

Next steps