selli / laravel-gdpr-consent-database
A simple consent database for laravel applications to manage GDPR consents
Fund package maintenance!
selli
Requires
- php: ^8.2
- illuminate/contracts: ^11.0||^12.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.1.1||^7.10.0
- orchestra/testbench: ^10.0.0||^9.0.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-arch: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
- dev-main
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.1
- v1.0.0
- dev-devin/1749925296-fix-session-id-column-type
- dev-devin/1749924331-fix-migration-issues
- dev-devin/1749923776-update-readme-documentation
- dev-devin/1749916690-fix-cookie-consent-technical-cookie
- dev-devin/1749910875-cookie-consent-categorization
- dev-devin/1749902265-cookie-banner-customization
- dev-devin/1749889382-fix-cookie-banner-disappearing
- dev-expiring-consents
This package is auto-updated.
Last update: 2025-06-15 07:34:15 UTC
README
A comprehensive Laravel package for managing GDPR consent in your applications. This package provides a complete solution for tracking user consents, managing consent types, and ensuring GDPR compliance.
Installation
You can install the package via composer:
composer require selli/laravel-gdpr-consent-database
Consent Categories
The package supports categorizing consent types to handle different types of consents appropriately:
cookie
- For cookie-related consents (technical, profiling, tracking, etc.)other
- For non-cookie consents (marketing, newsletters, etc.)
Cookie Banner Integration
The cookie banner automatically filters and displays only consent types with category 'cookie'
. Other consent types should be managed through your application's registration/preference flows.
You can publish and run the migrations with:
php artisan vendor:publish --tag="gdpr-consent-database-migrations"
php artisan migrate
You can publish the config file with:
php artisan vendor:publish --tag="gdpr-consent-database-config"
This is the contents of the published config file:
return [ 'text' => [ 'title' => 'Cookie Consent', 'message' => 'We use cookies to enhance your browsing experience and analyze our traffic. By clicking "Accept All", you consent to our use of cookies.', 'accept_text' => 'Accept All', 'reject_text' => 'Reject All', 'details_text' => 'Cookie Details', 'back_text' => 'Back', 'save_text' => 'Save Preferences', 'icon_text' => 'Cookie Settings', 'details_header' => 'Cookie Categories', 'required_text' => '(Required)', ], 'colors' => [ 'banner_background' => '#fff', 'banner_border' => '#ddd', 'banner_shadow' => 'rgba(0,0,0,0.1)', 'text_primary' => '#333', 'text_secondary' => '#666', 'button_primary_bg' => '#007cba', 'button_primary_hover' => '#005a87', 'button_secondary_bg' => '#f1f1f1', 'button_secondary_hover' => '#e1e1e1', 'details_border' => '#eee', ], 'icon' => [ 'position' => 'right', 'display' => 'icon-with-text', 'background' => '#007cba', 'background_hover' => '#005a87', ], ];
Optionally, you can publish the views using
php artisan vendor:publish --tag="laravel-gdpr-consent-database-views"
Usage
Setup
After installing the package and running the migrations, you need to add the HasGdprConsents
trait to your User model or any other model that needs to manage GDPR consents:
use Selli\LaravelGdprConsentDatabase\Traits\HasGdprConsents; class User extends Authenticatable { use HasGdprConsents; // ... rest of your model }
Creating Consent Types
First, you need to create consent types that users can agree to:
use Selli\LaravelGdprConsentDatabase\Models\ConsentType; // Create a required consent type (e.g., Terms and Conditions) ConsentType::create([ 'name' => 'Terms and Conditions', 'slug' => 'terms', 'description' => 'Agreement to the website terms and conditions', 'required' => true, 'active' => true, 'category' => 'other', ]); // Create cookie-related consent ConsentType::create([ 'name' => 'Technical Cookies', 'slug' => 'technical-cookies', 'description' => 'Essential cookies required for website functionality', 'required' => true, 'active' => true, 'category' => 'cookie', ]); // Create non-cookie consent ConsentType::create([ 'name' => 'Marketing Emails', 'slug' => 'marketing-emails', 'description' => 'Consent to receive marketing communications', 'required' => false, 'active' => true, 'category' => 'other', ]);
Managing User Consents
Once you have set up consent types, you can manage user consents:
// Get the authenticated user $user = auth()->user(); // Check if the user has given a specific consent if ($user->hasConsent('marketing-emails')) { // User has consented to marketing emails } // Give consent (can use slug or consent type ID) $user->giveConsent('marketing-emails'); // Give consent with additional metadata $user->giveConsent('marketing-emails', [ 'source' => 'registration_form', 'version' => '1.0', ]); // Revoke consent $user->revokeConsent('marketing-emails'); // Get all active consents for the user $activeConsents = $user->activeConsents(); // Check if the user has all required consents if ($user->hasAllRequiredConsents()) { // User has all required consents } else { // Get missing required consents $missingConsents = $user->getMissingRequiredConsents(); } ### Consent Versioning #### Overview The package supports versioning of consent types, which is essential for GDPR compliance when terms or policies change. #### Usage ```php // Create a consent type with version $consentType = ConsentType::create([ 'name' => 'Privacy Policy', 'slug' => 'privacy-policy', 'description' => 'Privacy Policy consent', 'required' => true, 'active' => true, 'version' => '1.0', ]); // Create a new version when terms change $newVersion = $consentType->createNewVersion([ 'description' => 'Updated Privacy Policy consent', ]); // Check if a user's consent is for the current version if ($user->hasConsent('privacy-policy', true)) { // User has consented to the current version } else { // User needs to renew consent for the new version } // Get all consents that need renewal (expired or outdated version) $consentsNeedingRenewal = $user->consentsNeedingRenewal(); // Renew a consent with the latest version $user->renewConsent('privacy-policy');
Consent Expiration
Overview
The package also supports consent expiration, allowing you to set validity periods for consents.
Usage
// Create a consent type with a validity period (in months) ConsentType::create([ 'name' => 'Marketing Emails', 'slug' => 'marketing-emails', 'description' => 'Consent to receive marketing emails', 'required' => false, 'active' => true, 'category' => 'other', 'version' => '1.0', 'validity_months' => 12, // Consent valid for 12 months ]); // Give consent with a custom validity period $user->giveConsent('marketing-emails', [], 6); // Valid for 6 months // Check if a consent is expired $consent = $user->consents()->where('consent_type_id', $consentTypeId)->first(); if ($consent->isExpired()) { // Consent is expired } // Get all expired consents $expiredConsents = $user->expiredConsents(); // Get consents that are about to expire within the next 30 days $soonExpiringConsents = $user->getConsentsExpiringWithinDays(30);
Guest Consent Management
For non-logged-in users, the package provides session-based consent management using technical cookie codes:
use Selli\LaravelGdprConsentDatabase\Services\GuestConsentManager; $guestManager = new GuestConsentManager(); // Give consent for a guest user (uses current session) $guestManager->giveConsent('marketing-emails', [ 'source' => 'cookie_banner', ]); // Check if guest has given consent if ($guestManager->hasConsent('marketing-emails')) { // Guest has consented to marketing emails } // Get all active consents for guest $activeConsents = $guestManager->getActiveConsents(); // Check if guest has all required consents if ($guestManager->hasAllRequiredConsents()) { // Guest has all required consents } // Work with specific technical cookie code (session ID) $technicalCookieCode = 'gdpr_abc123_1234567890'; $guestManager->giveConsent('terms', [], null, $technicalCookieCode); // Revoke guest consent $guestManager->revokeConsent('marketing-emails', $technicalCookieCode);
The guest consent system uses the guest_consents
table to track session information and links to user_consents
using the technical cookie code as the session identifier.
Using the Cookie Consent Seeder
Run the seeder to populate default cookie consent types:
php artisan db:seed --class="Selli\LaravelGdprConsentDatabase\Database\Seeders\CookieConsentSeeder"
Cookie Banner Integration
The package provides a blade directive for displaying cookie consent banners:
{{-- Basic usage --}} @gdprCookieBanner {{-- With custom options --}} @gdprCookieBanner([ 'title' => 'Cookie Preferences', 'message' => 'We use cookies to improve your experience.', 'acceptText' => 'Accept All Cookies', 'rejectText' => 'Reject Optional', 'consentTypes' => $consentTypes ])
Publishing Views
You can publish and customize the cookie banner view:
php artisan vendor:publish --tag="laravel-gdpr-consent-database-views"
This will publish the view to resources/views/vendor/gdpr-consent-database/cookie-banner.blade.php
.
Customization Options
The cookie banner supports extensive customization through the config file:
- Text customization: All button labels, messages, and UI text can be customized
- Color theming: Complete color scheme customization including backgrounds, borders, and button colors
- Icon positioning: Configure the consent settings icon position (right, left, top, bottom)
- Icon display: Choose between icon-only or icon-with-text display modes
- Responsive design: Automatic mobile-friendly adaptations
JavaScript Integration
The cookie banner includes built-in JavaScript for handling user interactions. It automatically:
- Shows the banner for users who haven't given consent
- Handles accept/reject actions via AJAX
- Stores consent state using cookies (
gdpr_consent_given
,gdpr_session_id
) - Provides detailed consent management with expandable categories
- Shows a consent settings icon after initial consent is given
- Manages technical cookie codes for session-based guest consent tracking
- Automatically checks consent status on page load and shows appropriate UI
Routes
The package automatically registers these routes for consent management:
POST /gdpr/consent/accept-all
- Accept all consent typesPOST /gdpr/consent/reject-all
- Accept only required consentsPOST /gdpr/consent/save-preferences
- Save specific consent preferencesPOST /gdpr/consent/status
- Get current consent status for the session
Make sure to include the CSRF token in your layout:
<meta name="csrf-token" content="{{ csrf_token() }}">
Database Structure
This package creates three main tables:
consent_types
Stores the different types of consent that can be requested from users:
id
: Primary keyname
: Name of the consent typeslug
: Unique slug for easy referencedescription
: Detailed description of what the user is consenting torequired
: Boolean indicating if this consent is requiredactive
: Boolean indicating if this consent type is currently activeversion
: Version string for consent type versioning (default: '1.0')validity_months
: Number of months the consent remains valid (nullable)effective_from
: Timestamp when this version becomes effective (nullable)effective_until
: Timestamp when this version expires (nullable)category
: Category of consent ('cookie' or 'other', default: 'other')metadata
: JSON field for additional data (e.g., legal references)timestamps
: Created and updated timestamps
user_consents
Stores the actual user consents:
id
: Primary keyconsentable_id
andconsentable_type
: Polymorphic relationship to the user modelconsent_type_id
: Foreign key to the consent typeconsent_version
: Version of the consent type when consent was given (nullable)granted
: Boolean indicating if consent is currently grantedgranted_at
: Timestamp when consent was grantedrevoked_at
: Timestamp when consent was revoked (if applicable)expires_at
: Timestamp when consent expires (nullable)ip_address
: IP address from which consent was givenuser_agent
: User agent from which consent was givenmetadata
: JSON field for additional datatimestamps
: Created and updated timestamps
guest_consents
Stores guest user information for session-based consent tracking:
session_id
: Primary key (technical cookie code/session ID)ip_address
: IP address of the guest useruser_agent
: User agent of the guest usermetadata
: JSON field for additional datatimestamps
: Created and updated timestamps
This table works in conjunction with user_consents
where guest consents are stored using the technical cookie code as the consentable_id
with consentable_type
set to the guest consent model.
Extending the Package
Custom Consent Types
You can extend the ConsentType
model to add custom functionality:
use Selli\LaravelGdprConsentDatabase\Models\ConsentType; class MyConsentType extends ConsentType { // Add custom methods or override existing ones public function isLegallyRequired() { return $this->required && isset($this->metadata['legal_basis']); } }
Custom Consent Workflows
You can create custom consent workflows by extending the HasGdprConsents
trait or by creating service classes that use the provided models:
use Selli\LaravelGdprConsentDatabase\Models\ConsentType; class ConsentService { public function processRegistrationConsents(User $user, array $consentData) { // Process multiple consents at once foreach ($consentData as $slug => $isGranted) { if ($isGranted) { $user->giveConsent($slug, ['source' => 'registration']); } } // Check if all required consents are given return $user->hasAllRequiredConsents(); } }
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.