Skip to content
Devix Open Source

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.

Updated 12 Sep 2026