Microsoft Clarity
Clarity records sessions and builds heatmaps — squarely analytics-purpose tracking, and squarely something you shouldn't start before consent. Consenti gives you a Clarity-shaped consent object plus the primitives to gate the tracking script itself and keep Clarity's own runtime consent flag in sync.
Reading consent in Clarity's shape
const clarityConsent = widget.getConsent('microsoft-clarity')
// {
// session: 'granted', // session recordings
// heatmaps: 'granted', // click/scroll heatmaps
// performance: 'granted', // performance/rage-click metrics
// }analyticspurpose — Clarity doesn't offer a way to separately opt out of, say, heatmaps but not session recording. See API Methods for the full getConsent(type) reference.Step 1 — Gate the tracking script
Clarity has no build-time way to defer its own start, so the reliable approach is to not load clarity.js at all until consent exists. Wrap the standard snippet in a CategoryScript, keyed to your own authored category ID (see Category type) — 'analytics' below is the common convention:
import { CategoryScript } from '@consenti/ui'
new CategoryScript({
categoryId: 'analytics',
widget,
unsafeInnerHTML: `
(function(c,l,a,r,i,t,y){
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
})(window, document, "clarity", "script", "YOUR_PROJECT_ID");
`,
onLoad: () => console.log('Clarity loaded'),
onRevoke: () => console.log('Clarity script removed'),
})<script> tag on revoke (which CategoryScript does automatically) stops newClarity activity, but doesn't retroactively delete anything already captured in that session before revocation — same caveat as any script-gated analytics tool. Load it only after consent in the first place if that matters for your compliance posture, rather than relying on gate-then-revoke.Step 2 — Sync Clarity's own consent API
If your Clarity project has “require consent” behaviour configured, or you want an explicit signal independent of script presence, call clarity('consent', …) directly from a CategoryAction:
import { CategoryAction } from '@consenti/ui'
new CategoryAction({
id: 'analytics',
widget,
onGrant: () => window.clarity?.('consent', true),
onDeny: () => window.clarity?.('consent', false),
})Run this alongside the CategoryScript above — the script gate controls whether Clarity is present at all, and the consent call controls its behaviour once it is.
Verifying
- Before consenting, open Network tab and confirm no request to
clarity.ms/tag/…orclarity.ms/collectfires. - Accept the analytics category on the Consenti banner.
- Confirm the Clarity script now loads, and check the Clarity dashboard — new sessions should appear within a couple of minutes (Clarity batches uploads, so it isn't instant).