Gating
Put consent in front of a script, an embed or an effect.
<ConsentScript>
For vendor snippets, without writing a wrapper component:
<ConsentScript
id="hotjar"
src="https://static.hotjar.com/c/hotjar-123.js?sv=6"
/><ConsentScript id="meta-pixel">{`
!function(f,b,e,v,n,t,s){…}(window, document,'script', 'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '000000000000000');
`}</ConsentScript>The tag is added when consent is granted and removed when it is withdrawn.
Removing a tag is not the same as undoing it
A script that already ran has already done whatever it does. If withdrawal has
to actually stop something, reload: local({ reloadOnRevoke: true }).
<CookieService>
Wrap anything that should only run with consent. It also puts the service in the preferences dialog, so the list there stays in step with what your app loads.
<CookieService id="hotjar">
<HotjarSnippet />
</CookieService>The id is usually all it takes — see the service catalog for what's built in and how to add your own.
Show something else instead
<CookieService
id="youtube"
fallback={<p>Allow marketing cookies to watch this.</p>}
>
<iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ" />
</CookieService>Google Consent Mode
Some Google scripts, like Google Analytics, can run in a limited mode without consent. Simply set consentMode on the <CookieService> and the adapter will handle it for you:
<CookieService id="google-analytics" consentMode>
<GoogleAnalytics gaId="G-XXXXXXX" />
</CookieService>See the Google Consent Mode page for details on what it does.
Render both cases
Pass a function when the placeholder needs the answer too:
<CookieService id="google-maps">
{(granted) => (granted ? <Map /> : <StaticMapImage onClick={openSettings} />)}
</CookieService>Categories
Every service belongs to one of four categories, and that is what gates it when the consent platform has no answer for the service itself:
| Category | |
|---|---|
essential | Needed to run the site. Always granted. |
functional | Preferences, embedded maps, chat widgets. |
analytics | Measurement and product analytics. |
marketing | Advertising, remarketing, conversion tracking. |
Platforms use their own names for these; the adapter translates, so your components only ever see the four above.
useHasConsent
When you only need the answer:
const canTrack = useHasConsent("analytics");
const canHotjar = useHasConsent("hotjar");Pass a category or a service id — whichever fits.
useCookieService
Same as <CookieService>, for work that happens in an effect rather than in the
tree:
const granted = useCookieService("posthog");
useEffect(() => {
if (!granted) return;
posthog.init(KEY);
return () => posthog.reset();
}, [granted]);Listing services before they render
Services appear in the preferences dialog once they mount. If your banner shows on the first paint and you want the full list there right away, name them on the provider:
<ConsentProvider
services={[
{ id: "google-analytics" },
{ id: "meta-pixel" },
{ id: "acme-chat", name: "Acme Chat", category: "functional" },
]}
>Listing a service here and rendering it later is fine — it won't show up twice.