Skip to content

v2.2 – Google Consent Mode v2, server-side consent checks & consent versioning

Latest

Choose a tag to compare

@devrabiul devrabiul released this 17 Oct 11:42

Highlights

📈 Google Consent Mode v2

Works with gtag.js, Google Tag Manager, GA4 and Google Ads. Consent defaults are set in <head> before Google tags load, returning visitors' choices are applied immediately, and every decision sends a gtag('consent', 'update', …) plus a cookie_consent_update dataLayer event for GTM triggers.

'google_consent_mode' => [
    'enabled' => env('COOKIE_CONSENT_GOOGLE_CONSENT_MODE', false),
    // consent type => cookie category mapping, wait_for_update, ads_data_redaction, url_passthrough
],

Place {!! CookieConsent::styles() !!} above your Google tag / GTM snippet in <head>.

🔐 Server-side consent checks

CookieConsent::hasConsent('analytics');
CookieConsent::hasValidConsent();
CookieConsent::googleConsentState();
@cookieConsent('analytics')
    <script async src="..."></script>
@endcookieConsent

The cookie data is validated before it's used: missing, malformed, tampered, outdated or expired consent counts as "no consent".

🔄 Consent versioning

'consent_version' => env('COOKIE_CONSENT_VERSION', '1.0'),

Change it when your cookie use materially changes, and every visitor is asked again. This replaces the old behaviour of asking everyone again each January 1st.

🍪 Floating cookie settings button

An optional button that reopens the preferences after the visitor has chosen, so consent can be changed or withdrawn at any time (GDPR Art. 7(3), UK ICO).

'floating_button' => ['enabled' => true, 'position' => 'bottom-left', 'label' => 'Cookie settings'],

🔁 SPA support

Works with Livewire wire:navigate, Turbo / Hotwire and Inertia. Each js_action runs at most once per page load, so analytics isn't loaded again on every navigation. For other routers, call window.initCookieConsent() after a page change.

🎨 Card colors

card_bg_color and card_text_color set the banner, modal and floating button colors, overriding the theme preset.

Fixes

  • No more cache access during boot (#14, #11). package:discover no longer crashes on fresh installs or in CI with CACHE_STORE=database before migrations run, and there's no cache I/O or cache-key growth per request.
  • Policy links: the URL fallback now works (env(...) ?: 'privacy-policy') and is safe with config:cache.
  • Cookie lifetime: the preferences cookie now uses cookie_lifetime / reject_lifetime instead of a fixed 365 days.
  • Removed the /laravel-cookie-consent/script-utils route. It cost an extra request per page and could overwrite your window.onload.
  • Category keys containing - now work in the service loader.
  • Accessibility: focus moves into the preferences modal and is restored on close, and the buttons now set aria-expanded.

Requirements

PHP 8.0+ and Laravel 8.x – 13.x, now declared in composer.json.

Upgrading

composer update devrabiul/laravel-cookie-consent
  • Existing consent is kept. Consent from earlier versions counts as consent version 1.0, and it's converted to the new cookies on the visitor's next page view. The new cookie names ({prefix}_consent, {prefix}_consent_preferences) no longer contain the year.
  • If you published the config file: add the new keys (consent_version, card_bg_color, card_text_color, floating_button, google_consent_mode). Also replace the policy links' env(..., '') ?? url(...) with env(...) ?: 'privacy-policy', otherwise those links are hidden. Missing new keys fall back to safe defaults: version 1.0, and both new features off.
  • JavaScript: getCookiePreferences() now returns null when consent is missing, outdated or expired.
  • Consent Mode and the floating button are disabled by default.

See the README for full documentation.

Full changelog: v2.1...v2.2