leobsst / laravel-cookie-consent
A cookie consent package for Laravel applications, providing an easy way to manage user consent for cookies in compliance with privacy regulations.
Fund package maintenance!
Requires
- php: ^8.2
- illuminate/contracts: ^11.9|^12.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- fakerphp/faker: ^1.23
- larastan/larastan: ^3.0
- laravel/pail: ^1.1
- laravel/pint: ^1.14
- mockery/mockery: ^1.6
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^9.0|^10.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-arch: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
README
Laravel Cookie Consent
A lightweight Laravel package for handling cookie consent with Google Tag Manager integration. No Livewire required — the banner is a pure Blade component with vanilla JavaScript, making it usable in any Laravel project.
Features
- Zero Livewire dependency — pure Blade component + vanilla JS
- Simple binary consent system (Accept/Refuse)
- Automatic Google Tag Manager integration with Consent Mode v2
- Cookie set client-side (non-HttpOnly, readable by JS)
- Persistent user preferences stored in cookies (1 year by default)
- Tailwind CSS styling with customizable accent color
- Dark mode support
- Multi-language support (EN, FR, IT, ES, DE)
Requirements
- PHP 8.2 or higher
- Laravel 11.9 or higher
- Tailwind CSS
Installation
Step 1: Install the Package
composer require leobsst/laravel-cookie-consent
Step 2: Publish Assets (Required)
php artisan vendor:publish --tag=cookie-consent-assets
This publishes public/vendor/cookie-consent/cookie-consent.js, the JavaScript file that handles cookie writing and Google Tag Manager consent updates.
Step 3: Publish Config File (Recommended)
php artisan vendor:publish --tag=cookie-consent-config
This creates config/cookie-consent.php where you can customize:
- GOOGLE_TAG_MANAGER_ID: Your GTM container ID (e.g.
GTM-XXXXXXX) - LEARN_MORE_LINK: URL or route name for the "Learn more" link (default:
/privacy-policy) - CONSENT_BANNER_VIEW: Override the banner view
- ACCENT_COLOR: Button and link color (default:
#3490dc) - duration: Cookie lifetime in minutes (default: 1 year)
- same_site: SameSite cookie attribute (default:
Lax)
Alternative: Use the Install Command
php artisan cookie-consent:install
This will publish the config file and assets, then ask you to star the repository on GitHub.
Configuration
Tailwind CSS Integration
Important
Add the following to your app.css so Tailwind processes the banner's utility classes:
@source '../../../../vendor/leobsst/laravel-cookie-consent/resources/views/**/*.blade.php';
Usage
Basic Usage
- Add your Google Tag Manager ID to
.env:
GOOGLE_TAG_MANAGER_ID=GTM-XXXXXXX
- Add the scripts directive and the banner component to your layout:
<!DOCTYPE html> <html> <head> <!-- Google Tag Manager with Consent Mode v2 --> @cookieConsentScripts </head> <body> <!-- Your content --> <!-- Cookie Consent Banner --> <x-cookie-consent::cookie-banner /> </body> </html>
The banner automatically appears for users who have not yet set their cookie preferences.
Complete Example
<!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>{{ config('app.name') }}</title> @vite(['resources/css/app.css', 'resources/js/app.js']) {{-- Google Tag Manager with Consent Mode --}} @cookieConsentScripts </head> <body> <div id="app"> {{ $slot }} </div> {{-- Cookie Consent Banner --}} <x-cookie-consent::cookie-banner /> </body> </html>
How It Works
-
@cookieConsentScripts(or<x-cookie-consent::scripts />) injects the GTM snippet withgtag('consent', 'default', ...). The initial state depends on thecookie_consentcookie already being set (e.g. returning visitors). -
<x-cookie-consent::cookie-banner />renders the banner only when GTM is configured and the user has not yet made a choice. It also injects a smallwindow.CookieConsentconfig object (cookie name, duration, SameSite, secure flag) and the banner's JavaScript inline. -
When the user clicks Accept or Refuse, the bundled
cookie-consent.jsscript:- Writes the
cookie_consentcookie directly in the browser (non-HttpOnly so it remains readable by JS on subsequent page loads) - Calls
gtag('consent', 'update', ...)to update consent in the current GTM session - Hides the banner instantly without a page reload
- Writes the
Checking User Consent
The HandleCookieConsent middleware shares $cookieConsentStatus with all views:
// In a Blade view @if($cookieConsentStatus === 'full') {{-- User has accepted all cookies --}} @endif
You can also read the cookie directly via the $_COOKIE superglobal:
$consent = $_COOKIE['cookie_consent'] ?? null; // 'full' — accepted // 'none' — refused // null — not yet set
Note
Do not use request()->cookie('cookie_consent') — Laravel's EncryptCookies middleware will try to decrypt the value and return null, because the cookie is written as plain text by the browser-side JavaScript. Reading it via $_COOKIE bypasses decryption and returns the raw value correctly.
Customizing the Banner
Publish the views to modify them:
php artisan vendor:publish --tag=cookie-consent-views
This copies the views to resources/views/vendor/cookie-consent/. You can also point to a completely custom view via the config:
// config/cookie-consent.php 'CONSENT_BANNER_VIEW' => 'my-theme.cookie-banner',
Your custom view receives these variables from CookieBanner:
| Variable | Type | Description |
|---|---|---|
$loadScript |
bool |
Whether GTM is configured |
$learnMoreLink |
?string |
Resolved URL for the "Learn more" link |
$accentColor |
?string |
CSS color value |
$cookieDuration |
int |
Cookie lifetime in seconds |
$sameSite |
string |
SameSite attribute value |
Translations
The banner uses the locale set in config('app.locale'). Available languages: English (en), French (fr), Italian (it), Spanish (es), German (de).
To publish and customize translation files:
php artisan vendor:publish --tag=cookie-consent-lang
Files are published to resources/lang/vendor/cookie-consent/.
Translation keys:
| Key | Default (EN) |
|---|---|
cookie-consent::translations.description |
Our website uses cookies... |
cookie-consent::translations.question |
Do you accept the use of these cookies? |
cookie-consent::translations.learn_more |
Learn more |
cookie-consent::translations.accept |
Accept |
cookie-consent::translations.refuse |
Deny |
Google Tag Manager Consent Mode
The package implements Google Consent Mode v2.
Default state (user has not yet decided):
{ 'functional_storage': 'granted', 'security_storage': 'granted', 'analytics_storage': 'denied', 'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied' }
When user accepts:
{ 'functional_storage': 'granted', 'security_storage': 'granted', 'analytics_storage': 'granted', 'ad_storage': 'granted', 'ad_user_data': 'granted', 'ad_personalization': 'granted' }
When user refuses:
{ 'functional_storage': 'granted', 'security_storage': 'granted', 'analytics_storage': 'denied', 'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied' }
Note: On a first-time accept, if
gtagis not yet loaded (GTM script hasn't initialized), the page will reload once so that GTM boots with the correct consent state.
Advanced Configuration
Environment Variables
# Required for Google Tag Manager integration GOOGLE_TAG_MANAGER_ID=GTM-XXXXXXX # Optional COOKIE_LEARN_MORE_LINK=/privacy-policy COOKIE_CONSENT_BANNER_VIEW=cookie-consent::components.cookie-banner COOKIE_CONSENT_ACCENT_COLOR=#3490dc
Resetting a User's Consent
use Illuminate\Support\Facades\Cookie; Cookie::queue(Cookie::forget('cookie_consent'));
FAQ
Does this package require Livewire?
No. As of v2, Livewire is not required. The banner is a Blade component and all consent logic runs in vanilla JavaScript.
Can I use this without Google Tag Manager?
Yes. Simply don't set GOOGLE_TAG_MANAGER_ID. The banner will not appear (it only renders when GTM is configured), but the cookie_consent cookie will still be available for you to use in your own scripts.
How do I style the banner to match my design?
- Use
ACCENT_COLORin the config to change the button/link color. - Publish the views and edit the Tailwind classes.
- Create a completely custom view and point
CONSENT_BANNER_VIEWto it.
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Security
If you find a security vulnerability, please email contact@leobsst.fr instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.