Consent in the Theme
The consent state lives in two places: Google Consent Mode, which the GTM tags read, and the evolve_consent cookie, which the server and the theme scripts read. This page is the developer's view of the browser side. Policies, settings and the cookie table are on Tracking and Consent.
What the head partial defines
theme::consentMode (included by theme::head) runs before any tag and defines:
| Global | What it is |
|---|---|
window.EVOLVE_CONSENT | { policy, cookieName, cookieLifetimeDays, banner, managedBy, state }. state is { analytics, marketing } from the cookie, or the policy default. managedBy is cmp when a consent platform is declared (TRACKING_CONSENT_VIA_CMP or TRACKING_CMP), otherwise evolve. |
window.evolveConsentAllows(category) | true when analytics or marketing is granted right now. |
window.evolveConsentUpdate({ analytics, marketing }) | The one entry point for consent decided outside the Evolve banner. Since 2.19. |
Listen to the evolve:consent-updated window event to react to a change. Its detail is { analytics, marketing }. Hotjar and the tracking config do this already.
window.evolveConsentUpdate 2.19
window.evolveConsentUpdate({ analytics: true, marketing: false })It does what the Evolve banner does when the visitor saves a choice:
- writes the
evolve_consentcookie in the banner's format: JSON{ v: 1, analytics, marketing, ts },max-agefromcookieLifetimeDays,path=/,SameSite=Lax. The server reads it on the next request. - sets
EVOLVE_CONSENT.state. - calls
gtag('consent', 'update', ...), but only whenmanagedByisevolve. With a consent platform the platform updates Consent Mode itself, and a second update from Evolve could contradict it. - pushes
consent_updatedwithconsent_analyticsandconsent_marketingto thedataLayer. - dispatches
evolve:consent-updated.
A choice equal to the stored cookie changes nothing and returns false, otherwise the call returns true. Consent platforms report the stored consent on every page load, so the guard keeps the cookie and the events quiet when nothing changed. Values are cast to booleans; a missing category counts as denied.
Wiring a consent platform
Cookiebot needs no code: set the driver and the ID in the panel and Evolve renders uc.js and the listener (see External consent platforms). Remove a project partial that loads Cookiebot itself once the driver is set, otherwise it loads twice.
Any other platform maps its categories to analytics and marketing and calls the bridge from its consent callback. Render the script after theme::head, so the bridge exists when the platform reports. A sketch for a platform with a JavaScript event:
@push('head')
<script data-cookieconsent="ignore">
window.addEventListener('consent-platform:changed', function (event) {
window.evolveConsentUpdate({
analytics: event.detail.statistics === true,
marketing: event.detail.marketing === true,
});
});
</script>
@endpushWithout such a call, TRACKING_CONSENT_VIA_CMP on an opt-in site only grants the GTM tags. Server-side conversions, Hotjar, the client tracking config and the footprints cookie stay denied, and the tracking health check warns.
Project copies of the views
A project that copied theme::head or theme::consentMode (into resources/views/vendor/theme/) or renders its own consent snippet does not get the bridge. php artisan evolve:view-overrides --since=2.18.0 lists the copies of the theme views and what they have to add. A project consent snippet that is not a copy of theme::consentMode is not detected; compare it with the package view by hand.