Guide
Rendering tags on the server
Google Consent Mode, the right way round
Consent Mode defaults must run before any Google tag, so put them in the <head> — they are the same
for everyone, so they do not break page caching:
<head>
<script type="module">
import { consentModeDefaults } from '{{ config('cookie-consent.assets.js') }}';
consentModeDefaults();
</script>
{{-- your GTM snippet --}}
</head>
The widget sends the update when a decision is made. With 'consentMode' => true in the widget config
(the default), tags inside your container then fire or not by themselves.
Caching
A page whose HTML depends on consent must not be cached as one page for everyone. Two arrangements work:
Cache the page, block in the browser. Print the tags with data-cc and let the widget release
them:
<script type="text/plain" data-cc="analytics" src="…"></script>
Vary the page. Include the decision in your cache key:
$key = 'page:'.$slug.':'.(Consent::allows('analytics') ? 'a' : '-').(Consent::allows('marketing') ? 'm' : '-');
Full-page cache and @consent together, without one of these, will serve someone else's decision.
Inertia and Livewire
Share the decision once:
// AppServiceProvider
Inertia::share('consent', fn () => [
'decided' => Consent::decided(),
'allows' => collect(Consent::categories())->pluck('id')->mapWithKeys(fn ($id) => [$id => Consent::allows($id)]),
]);
// A Livewire component
public function mount(): void
{
$this->showEmbed = Consent::allows('marketing');
}
The browser is still the source of truth — after someone changes their mind without a reload, listen for the widget's event:
document.addEventListener('dx:consentchange', () => Livewire.dispatch('consent-changed'));
Reading it anywhere else
The cookie is plain JSON on purpose, so anything that speaks HTTP can read it — a queue worker handling a webhook, an edge function, a reverse proxy:
$decision = Devix\CookieConsent\Decision::fromArray(
json_decode($request->cookie('dx_consent') ?? '[]', true) ?: []
);
$decision->allows('analytics');
Where the visitor is
regime => 'auto' needs a country. The component reads your CDN's header — Cloudflare's
CF-IPCountry by default:
'country_header' => 'CF-IPCountry', // or 'X-Vercel-IP-Country', 'CloudFront-Viewer-Country'
Or pass one yourself: <x-cookie-consent country="AE" />. For US states, send US-CA.