A complete GDPR compliance toolkit for your LaraClassifier / JobClass site. Display a customizable cookie consent banner, log visitor consent decisions for audit compliance, and manage cookie categories from the admin panel.
Cookie Consent Banner
A polished, responsive banner with Accept All, Reject All, and Customize options. Seven position variants including modal mode.
Granular Categories
Four cookie categories (Essential, Analytics, Marketing, Preferences) with per-category toggle controls for visitors.
Consent Logging
Full audit trail of every consent decision: IP address, user agent, action taken, and categories selected. GDPR Article 7 compliant.
Auto-injection
The banner is automatically injected into all front-end pages via middleware. No template changes needed. Skips admin panel and AJAX requests.
Use Cases
EU/EEA Website Compliance
Your site serves visitors in the European Union and must comply with the GDPR and ePrivacy Directive.
- Enable the cookie consent banner to inform visitors about cookie usage.
- Enable consent logging to maintain an auditable record of all consent decisions.
- Link your privacy policy page so visitors can review your data practices.
- Configure category toggles so visitors can opt in/out of analytics and marketing cookies.
Analytics-Heavy Site
You use Google Analytics, Hotjar, or similar tools and need user consent before loading tracking scripts.
- Enable the Analytics category toggle.
- Read the consent cookie (
gdpr_consent, a URL-encoded JSON object such as{"necessary":true,"analytics":true,...}) in your JavaScript before loading analytics scripts, or listen for thegdpr:consentbrowser event fired onwindowwhen the visitor makes a choice. - Only load analytics when
analyticsistrue.
Marketing & Ad Retargeting
You run Facebook Pixel, Google Ads, or email marketing tools that set cookies.
- Enable the Marketing category toggle.
- Gate all marketing/advertising scripts behind the
marketingconsent flag. - Visitors can revoke consent at any time via the withdraw endpoint.
Requirements
- LaraClassifier / JobClass v19.0.0 or later
- PHP 8.3+
- MySQL 8.0+
Installation
Step 1: Upload the add-on
Go to Admin panel → Extensions → Add-ons, click Upload add-on and drop the add-on's .zip file into the upload area (50 MB maximum).
The archive is extracted into extensions/addons/gdpr/ and GDPR & Cookie Consent appears in the list, deactivated.
extensions/addons/gdpr/ over FTP or SSH: its addon.json file must sit directly inside that folder.
Then open Admin panel → Extensions → Add-ons. The page scans extensions/addons/ every time it loads, so the add-on is listed straight away (the Sync button runs the same scan on demand).
Step 2: Activate the add-on
Click Activate on the GDPR & Cookie Consent card. It is a paid add-on, so a dialog asks for its purchase code, which is verified before anything else happens: an invalid code is rejected in the dialog and nothing is changed.
Once the code is accepted, activation runs in one pass: it creates the add-on's database tables (its migrations), registers its permissions, runs its seeders and publishes its public assets. Reload the page to see its new entry in the Add-ons section of the admin sidebar.
Step 3: Configure
Open Admin panel → GDPR from the Add-ons section of the sidebar and set the add-on up: see Configuration.
Purchase Code (License Key)
GDPR & Cookie Consent is sold as a separate product, so it has its own purchase code (license key), distinct from the purchase code of the main application and from the one of every other add-on. You are asked for it when you activate GDPR & Cookie Consent in Admin panel → Extensions → Add-ons.
Our products are sold on three platforms. The way you receive a purchase code depends on where you bought the product.
| Platform / Marketplace | How you get the purchase code | Where to find it again |
|---|---|---|
| bedigit.com Store In-site purchase (Shop) |
Generated automatically when the order is paid, then sent by email, either in its own license email, or inside the order confirmation email. | My Account → My Licenses on bedigit.com |
| Gumroad | Created as soon as Gumroad notifies us of the sale, then sent in a separate email, in addition to the Gumroad receipt. | The license email, your Gumroad Library, and My Account → My Licenses on bedigit.com |
| Envato Market CodeCanyon |
Issued by Envato, not by us, and never sent by email: you download it yourself from your Envato account. | Envato account → Downloads → License certificate & purchase code |
1. bedigit.com Store (in-site purchase)
- As soon as the order’s payment status becomes Paid, a license key is generated automatically for every licensed item in the order (one key per purchased unit: buying 3 units gives 3 distinct keys).
- It is emailed to the address used on the order, either in a dedicated license email or inside the order confirmation email. Check your inbox and your spam / junk folder.
- The key stays available in your account under My Account → My Licenses. Keys are masked in the list; open the license detail page to reveal and copy the full key, see the domains it is activated on, and deactivate a domain to free an activation slot.
- The matching invoice is under My Account → My Orders.
2. Gumroad
- A Gumroad purchase produces two separate emails: the Gumroad receipt (sent by Gumroad, giving access to the files) and a license key email (sent by bedigit.com) that contains your purchase code.
- The license key email is generated as soon as Gumroad notifies us of the sale, so it normally arrives within seconds of the payment. Here too, check your inbox and your spam / junk folder.
- When the Gumroad product uses Gumroad’s own license-key feature, the same key also appears in your Gumroad receipt and under Library → your purchase on gumroad.com.
- Use the same email address on bedigit.com as on Gumroad: your keys are then linked to your account automatically and listed under My Account → My Licenses, even if you register after the purchase. You can also add a Gumroad key manually from My Account → My Gumroad Licenses.
3. Envato Market (CodeCanyon)
- Envato purchase codes are issued and delivered by Envato Market, never emailed by us, so there is nothing to look for in your spam folder: you retrieve the code from your Envato account.
- Log in to your Envato / CodeCanyon account, open the Downloads page, find the item, and choose License certificate & purchase code from the Download dropdown. The code is written in that certificate.
- An Envato purchase code looks like
12345678-90ab-cdef-1234-567890abcdef(8-4-4-4-12 characters). It never changes, and renewing item support does not issue a new one. - Official Envato article: Where Is My Purchase Code?
Configuration
All settings are managed in Admin panel → Add-ons → GDPR → Settings
(stored in the core settings table, group gdpr).
Default values come from the add-on’s config/gdpr.php file.
| Setting | Description | Default |
|---|---|---|
gdpr_enabled |
Enable or disable the cookie consent banner globally. | true |
gdpr_cookie_lifetime |
How many days the consent preference cookie is remembered (1–3650). | 365 |
gdpr_log_consents |
Record each visitor’s consent decision to the database for compliance auditing. | true |
gdpr_capture_country |
Resolve the visitor’s country code from their IP address (using the GeoIP driver configured in LaraClassifier / JobClass) when a consent is logged. The lookup runs as a queued job, and a Country column is added to the Consent Logs table. | false |
gdpr_banner_position |
Where the banner appears on the page (7 positions available). | bottom-center |
gdpr_privacy_policy_url |
URL to your privacy policy page, displayed as a link in the banner. When empty, the banner links to your site’s active page of type Privacy Policy (Admin panel → Pages); no link is shown if there is none. | (empty) |
gdpr_category_analytics |
Show the Analytics cookie category toggle in the preferences panel. | true |
gdpr_category_marketing |
Show the Marketing cookie category toggle in the preferences panel. | true |
gdpr_category_preferences |
Show the Preferences cookie category toggle in the preferences panel. | true |
gdpr_log_retention_days |
Number of days before consent logs and archive files are permanently deleted (1–7300). | 730 (2 years) |
gdpr_archive_enabled |
When enabled, previous-month logs are gzipped and moved to private storage; only the current month remains in the database. | false |
gdpr_dedup_window_minutes |
Skip writing a new consent log if an identical one (same user/IP, action, categories) was recorded within this window. Set to 0 to disable. |
5 |
gdpr_stats_cache_ttl |
How long (in seconds) cached dashboard statistics stay fresh. Set to 0 to disable the cache entirely. |
900 (15 minutes) |
Config File Defaults
The add-on’s config/gdpr.php file (in extensions/addons/gdpr/config/) provides the default values used
until the settings page is saved for the first time. It also holds a few options that have no field on the settings page:
cookie_name(defaultgdpr_consent): name of the consent cookie.archive_disk(defaultlocal) andarchive_path(defaultgdpr): where monthly archive files are stored.admin_per_page(default25): number of rows per page on the Consent Logs page.
Admin: Settings
The settings page (Admin panel → Add-ons → GDPR → Settings) requires the admin.setting.view
permission to open and admin.setting.edit to save. It is organized into four main areas:
General Settings
The left column (7/12 width) contains the core configuration options:
- Enable Cookie Banner: toggle switch to enable/disable the banner globally. When disabled, no banner is shown and no middleware injection occurs.
- Cookie Lifetime (Days): numeric input (1–3650 days) controlling how long the consent cookie persists in the visitor’s browser.
- Banner Position: visual position picker with 7 positions displayed on a browser mockup. Click a position to select it; the label updates in real time.
- Log Consent Actions: toggle to enable/disable consent logging to the database. When enabled, every Accept/Reject/Customize/Withdraw action is recorded.
- Privacy Policy URL: text input for the URL to your privacy policy page. If provided, a “Privacy Policy” link to it appears in the banner. When left empty, the banner links to your site’s active page of type Privacy Policy (Admin panel → Pages), whose address is shown as the field’s placeholder; if no such page exists, no link is shown.
- Capture Country via IP: toggle to store the visitor’s country code with each consent log. The country is resolved in a queued job using the GeoIP driver configured in LaraClassifier / JobClass, so it requires a working GeoIP setup.
Banner Position Picker
The position picker is an interactive visual element showing a miniature browser window. Seven clickable dots represent the available positions:
| Position | Layout | Description |
|---|---|---|
top-left |
Compact card | Floating card in the top-left corner (max 420px wide) |
top-center |
Full-width bar | Horizontal bar across the top of the page |
top-right |
Compact card | Floating card in the top-right corner (max 420px wide) |
middle-center |
Modal dialog | Centered modal with a semi-transparent backdrop overlay |
bottom-left |
Compact card | Floating card in the bottom-left corner (max 420px wide) |
bottom-center |
Full-width bar | Horizontal bar across the bottom of the page (default) |
bottom-right |
Compact card | Floating card in the bottom-right corner (max 420px wide) |
Cookie Categories
The right column (5/12 width) displays the four cookie categories with toggle switches:
- Essential: always on, cannot be disabled (displayed with an “Always On” badge). These are cookies required for the website to function (sessions, CSRF tokens, etc.).
- Analytics: toggleable. When enabled, visitors can opt in/out of analytics cookies (Google Analytics, Hotjar, etc.).
- Marketing: toggleable. When enabled, visitors can opt in/out of marketing cookies (Facebook Pixel, ad retargeting, etc.).
- Preferences: toggleable. When enabled, visitors can opt in/out of preference cookies (language, theme, personalization, etc.).
The three optional categories are switched on by default: until you turn one off and save the settings, it is offered to visitors in the banner and shown as on in this card.
Logs & Retention
A third full-width card below the two existing columns controls data retention and performance:
- Monthly Log Archive: toggle switch. When enabled, only the current month’s logs stay in the database; previous months are gzip-compressed and moved to private storage (see Admin: Archives). A shortcut to the Archives page appears next to the toggle.
- Log Retention (Days): integer (1–7300). Both database rows and archive files older than this
are permanently deleted by the daily
gdpr:purge-logstask. The GDPR typically recommends 2–6 years for consent evidence. - Deduplication Window: integer minutes (0–1440). If an identical consent entry exists for the
same user/IP within this window, the new write is skipped and the existing record is reused. Set to
0to disable. - Stats Cache TTL: integer seconds (0–86400). How long cached dashboard statistics stay fresh.
The cache is automatically invalidated whenever a consent log is created or deleted. Set to
0to disable caching. - Clear Stats Cache Now: button that purges the cached statistics on demand (useful after bulk deletes or imports).
Consent Overview Stats
At the top of the settings page, five stat cards show consent metrics for the last 30 days:
- Total Consents: total number of consent actions recorded
- Accepted All: visitors who clicked “Accept All”
- Rejected All: visitors who clicked “Reject All”
- Customized: visitors who saved custom preferences
- Acceptance Rate: percentage of “Accepted All” vs total consents
These stats are cached for gdpr_stats_cache_ttl seconds (default 15 minutes) to keep the page fast on
databases with millions of rows.
Admin: Consent Logs
The Consent Logs page (Admin panel → Add-ons → GDPR → Consent Logs, permission admin.gdpr.view) provides a full audit trail
of every visitor consent decision, as required by GDPR Article 7. The page is fully AJAX-driven: filtering,
pagination, inline delete and bulk actions all refresh the table in place without a full reload.
Statistics Card
A dedicated card at the top of the page shows four mini stat cards for the last 30 days (independent of the table filters below):
- Total Consents (neutral color)
- Accepted All (success/green color)
- Rejected All (danger/red color)
- Acceptance Rate (accent color, shown as percentage)
These figures are cached for gdpr_stats_cache_ttl seconds and automatically refresh when any log is
created or deleted.
Page Actions
The page header exposes three permission-gated action buttons:
- Archives (shown only when archive mode is enabled): opens the monthly archive browser
(see below). Requires
admin.gdpr-archive.view. - Export CSV: downloads a CSV file of the currently filtered rows, with a UTF-8 BOM for Excel
compatibility. Columns:
id,created_at,user_id,user_name,user_email,ip_address,user_agent,action,categories(JSON). Requiresadmin.gdpr.export. - Purge Now: queues the
PurgeConsentLogsJobto immediately delete database rows and archive files beyond the retention period (asks for confirmation). The job runs on your queue connection. Requiresadmin.gdpr.delete.
Filters
All filters sit inline on a single row in the card header and trigger an AJAX refresh:
- Search (debounced 300 ms): filter by IP address, user name, or user email.
- Action: dropdown with
accepted_all,rejected_all,customized,withdrew. - From date and To date: native
<input type="date">pickers that apply awhereDate(created_at, …)range.
The Export CSV button respects the currently applied filters.
Log Table
A paginated table (25 records per page by default) with the following columns:
| Column | Description |
|---|---|
| Select | Row checkbox + header “select all”. Shown only when the user has admin.gdpr.delete. |
| Visitor | User avatar + name/email (if authenticated) or “Guest” label (if anonymous). |
| IP Address | Visitor’s IP address, displayed in monospace/code formatting. |
| Country | Flag and country code (full name in a tooltip). Shown only when Capture Country via IP is enabled. |
| Action | Color-coded badge: Accepted All (green), Rejected All (red), Customized (yellow), Withdrew (gray). |
| Categories | Inline badges for each category showing enabled (filled) or disabled (outline) state. |
| Date | Human-readable relative time (e.g. “2 hours ago”) with full date in a tooltip. |
| Actions | Per-row trash icon that deletes the entry via AJAX after a confirmation prompt. |
Bulk Delete
Ticking one or more row checkboxes surfaces a floating bulk-action bar at the top of the list. Click Delete selected and confirm the SweetAlert prompt to remove all selected rows in a single AJAX request. The selection is reset and the table refreshes on success.
Deduplication
Before inserting a new row, GdprService::logConsent() looks for an identical recent log (same
user_id or IP, same action, same categories) created within the
gdpr_dedup_window_minutes window. If one is found, the existing record is returned and no new row is
written. This prevents the table from filling up when a visitor reloads a page or quickly toggles their consent.
Empty State
When no logs match the current filters, a friendly empty state is displayed with a large icon and a message explaining that records will appear once visitors interact with the banner.
Admin: Archives
The Archives page (Admin panel → Add-ons → GDPR → Archives) is always listed in the sidebar.
New archives are only created while Monthly Log Archive (gdpr_archive_enabled) is on: while it is
off, the page shows a notice saying so, with a shortcut to the settings page, and any archives created earlier stay listed and
downloadable. It lists all gzipped monthly archive files found under
storage/app/gdpr/{year}/{month}/consent-logs-{year}-{month}.csv.gz (default local disk).
How Archives Are Created
Every 1st of the month at 00:05, the scheduled gdpr:archive-monthly command runs (if the archive
setting is enabled). It performs the following for each month older than the current one that does not yet have
an archive file:
- Streams every log of that month into a CSV buffer (1000 rows at a time).
- Gzips the CSV and writes it to the private disk at the path above.
- Deletes the archived rows from
gdpr_consent_logsin chunks of 1000, inside a single database transaction. - Finally prunes any archive files older than
gdpr_log_retention_days.
Browsing Archives
The admin page groups files by year in a collapsible list. Each row shows the month, filename, file size and
archive timestamp, plus a Download button that streams the gzip file back to the browser. Access
to both browsing and downloading is permission-gated (admin.gdpr-archive.view and
admin.gdpr-archive.download).
year / month /
filename URL parameters against strict regex patterns and aborts with 404 for anything outside the
gdpr/ storage directory.
CLI & Scheduling
The add-on registers two Artisan commands and their matching scheduled entries. Both are wired up automatically
inside GdprServiceProvider::boot(), no changes to
routes/console.php are required.
| Command | Schedule | Purpose |
|---|---|---|
gdpr:purge-logs |
Daily at 00:00 | Dispatches PurgeConsentLogsJob: deletes DB rows older than gdpr_log_retention_days,
prunes expired archive files, and clears the stats cache. |
gdpr:archive-monthly [--force] |
1st of each month at 00:05 | Dispatches ArchiveMonthlyConsentLogsJob: archives every completed past month, then prunes
expired archives. Skips entirely when gdpr_archive_enabled is off unless
--force is passed. |
Both commands run their job synchronously, inside the command itself, so no queue worker is needed for the scheduled runs
(only the Purge Now button on the Consent Logs page pushes the purge job onto your queue connection). The schedule
only fires if the LaraClassifier / JobClass cron job (* * * * * cd /path-to-your-site && php artisan schedule:run >> /dev/null 2>&1)
is set up on your server. Confirm the tasks are registered with php artisan schedule:list.
Front-end: Cookie Banner
The cookie consent banner is a self-contained HTML/CSS/JS component that is automatically injected
into every front-end page via the InjectCookieBanner middleware.
Main Banner View
The main view displays:
- Cookie icon: an inline SVG cookie illustration
- Title: “Cookie Preferences”
- Message: a brief explanation of cookie usage
- Privacy Policy link: points to the URL configured in settings or, when that field is empty, to your site’s active Privacy Policy page; hidden when neither exists
- Three action buttons:
- Accept All (primary dark button): accepts all cookie categories
- Reject All (secondary gray button): rejects all non-essential cookies
- Customize (ghost/text button): opens the preferences panel
Banner Positions
The banner adapts its layout based on the configured position:
- Full-width positions (
top-center,bottom-center) use a horizontal flex layout with content and buttons side by side. Max width 860px, centered. - Corner positions (
top-left,top-right,bottom-left,bottom-right) use a compact card layout (max 420px) with stacked content. - Modal position (
middle-center) centers the banner with a semi-transparent backdrop overlay, functioning as a modal dialog (max 520px).
Preferences Panel
Clicking “Customize” transitions from the main view to the preferences panel (no page reload). The panel shows:
- Back button with chevron icon: returns to the main banner view
- Category list (scrollable, max height 280px) with one row per enabled category:
- Category name and description
- Required categories: display an “Always On” badge (no toggle)
- Optional categories: display a custom CSS toggle switch
- Save Preferences button: saves the selected categories and dismisses the banner
Animations
The banner uses smooth CSS animations:
- Slide in from bottom for bottom positions
- Slide in from top for top positions
- Fade + scale for the center modal position
- Reverse animations when the banner is dismissed
Responsive Design
On screens below 768px:
- Full-width bars switch to vertical (stacked) layout
- Corner cards expand to full width
- Action buttons stack vertically and fill the width
Translations
Translation files are provided for 18 languages (ar, bn, de, en, es, fr, he, hi, it, ja, ka, pt, ro, ru, th, tr, uk, zh).
All strings use the gdpr:: namespace prefix.
Translation Keys
| Section | Key Pattern | Description |
|---|---|---|
| Categories | gdpr::messages.categories.* |
Category names and descriptions (necessary, analytics, marketing, preferences) |
| Actions | gdpr::messages.actions.* |
Consent action labels (accepted_all, rejected_all, customized, withdrew) |
| Positions | gdpr::messages.positions.* |
Banner position labels for the admin picker |
| Front-end | gdpr::messages.front.* |
Banner UI strings (title, message, button labels, privacy link) |
| Admin Settings | gdpr::messages.admin.settings.* |
Settings page labels, hints, and section headings |
| Admin Consent Logs | gdpr::messages.admin.consent_logs.* |
Consent logs page labels, column headers, empty state |
| Admin Stats | gdpr::messages.admin.stats.* |
Stat card labels (total_consents, accepted_all, etc.) |
| Admin Archives | gdpr::messages.admin.archives.* |
Archive browser labels (title, subtitle, month, filename, size, archived_at, download, empty state) |
| Messages | gdpr::messages.admin.messages.* |
Flash messages (settings_updated, stats_cache_cleared) |
Updating
An update only replaces the add-on's files. Its database tables and data, its settings, its activation state and its recorded purchase code are all kept, so do not deactivate or remove the add-on before updating it. Back up your database first all the same.
Method 1: Upload the new version (recommended)
- Download the latest
.zipfile of the add-on. - Go to Admin panel → Extensions → Add-ons and click Upload add-on.
- Drop the
.zipfile into the upload area. - Because GDPR & Cookie Consent is already installed, a prompt shows the installed version and the new one. Click Replace: the
extensions/addons/gdpr/folder is swapped for the new files. Cancelling the prompt discards the upload.
Method 2: Replace the files by hand
- Over FTP or SSH, delete the
extensions/addons/gdpr/folder and upload the new one in its place. Replace the whole folder rather than copying over it, so files dropped by the new version do not linger. - Open Admin panel → Extensions → Add-ons: the page re-reads
addon.jsonand the card shows the new version number.
After the files are replaced
New database tables or columns. When a new version adds some, create them by running php artisan migrate --force over SSH, or without SSH by clicking Deactivate then Activate on the add-on's card: activation runs every pending migration (and asks for the purchase code again). Your data is not touched either way.
If your installation caches its configuration or routes (php artisan config:cache, route:cache), run php artisan optimize:clear after the update.
Uninstallation
Switching an add-on off without losing anything is a deactivation: go to Admin panel → Extensions → Add-ons, click Deactivate on the GDPR & Cookie Consent card and confirm.
- The add-on is no longer loaded: its routes, views, admin sidebar entry and front-end pages stop answering.
- Its database tables and all the data they hold are kept, and its files stay under
extensions/addons/gdpr/. Nothing is deleted. - Its permissions and its recorded purchase code stay in the database. Only Remove deletes them.
- Deactivation is refused while another active add-on depends on this one: deactivate that add-on first.
Click Activate on the same card to switch it back on. As for a first activation, the purchase code is asked for and verified again; then any pending migrations run, the assets are republished, and the add-on picks up exactly where it left off.
Removing
Removing is permanent and destroys the add-on's data. The Remove button only appears on a deactivated add-on, so removal is always two steps:
- Deactivate GDPR & Cookie Consent (see Uninstallation).
- Click Remove on its card and confirm the prompt.
The admin panel then, in one pass:
- runs the add-on's uninstall hook, if it ships one, while its code is still on disk;
- revokes the permissions declared in its
addon.json; - rolls back its migrations (this drops its database tables and every row they hold) and purges its entries from the
migrationstable, so a later reinstall migrates from scratch; - deletes its published assets:
public/addons/gdpr/,public/vendor/gdpr/andstorage/app/public/addons/gdpr/; - deletes the add-on directory
extensions/addons/gdpr/; - deletes its row in the
addonstable (the recorded purchase code goes with it) and clears the application cache.
Removal is refused, with an explanatory message and before anything is destroyed, when the add-on is still active, when another active add-on depends on it, or when the web server (PHP) user cannot delete extensions/addons/gdpr/. In that last case, give that user write permission on the directory and on its parent, then try again.
Deleting the folder over FTP or SSH is not equivalent: the add-on is only switched off, and its tables, its entries in the migrations table and its addons row are all left behind. Use Remove in the admin panel instead.
Troubleshooting
Banner not appearing on the front-end
Check the following:
- The add-on is activated in Admin panel → Extensions → Add-ons.
- Enable Cookie Banner is switched on in GDPR → Settings.
- You don’t already have a
gdpr_consentcookie set. Clear cookies or use an incognito window to test. - The page is a standard HTML response with a
</body>tag (the middleware looks for this tag to inject the banner). - You are viewing a front-end page, not an admin page (admin routes are excluded).
Banner appears on admin pages
This should not happen: the middleware explicitly skips admin routes via isAdminPanelRoute().
If it does occur, check that:
- The
isAdminPanelRoute()helper function is defined and working in your LaraClassifier / JobClass core installation. - Your admin URL prefix matches the configured admin base path (the
ADMIN_BASE_PATHvalue in.env,adminby default).
Consent cookie is encrypted / unreadable by JavaScript
The add-on explicitly excludes the gdpr_consent cookie from Laravel’s EncryptCookies middleware.
If the cookie is still encrypted:
- Ensure the
GdprServiceProvideris properly registered (add-on is active). - Check that no custom middleware or package is re-encrypting the cookie.
- Clear your browser cookies and consent again: old encrypted cookies from a previous configuration may persist.
Consent logs not being recorded
- Check that Log Consent Actions is switched on in the admin settings.
- Verify the
gdpr_consent_logstable exists (it is created when the add-on is activated). - An identical choice made again by the same user/IP within the Deduplication Window is not logged twice.
- Check your server logs for database errors (e.g. permission issues).
Banner position not changing
- After changing the position in admin settings, make sure to clear the
gdpr_consentcookie (or use an incognito window): the banner only appears for visitors without a consent cookie. - The rendered banner is cached, but that cache is cleared automatically every time the GDPR settings are saved.
Categories not showing in preferences panel
Only categories that are enabled in the admin settings appear in the preferences panel. The “Essential” category always appears. For optional categories:
- Check that Analytics Cookies, Marketing Cookies and/or Preference Cookies are switched on in the Cookie Categories card of the settings page.
- Disabled categories are filtered out by the
InjectCookieBannermiddleware before rendering the view.
Log retention / purging
Retention is fully automated. The gdpr:purge-logs scheduled command runs every day at 00:00 and
deletes both database rows and archive files older than gdpr_log_retention_days
(default: 730 days / 2 years, configurable from the Settings page). You can also:
- Trigger it on demand from the Consent Logs page via the Purge Now button
(requires
admin.gdpr.delete). - Run it manually:
php artisan gdpr:purge-logs. - Verify scheduling with
php artisan schedule:list, bothgdpr:purge-logs(daily) andgdpr:archive-monthly(monthly on the 1st, 00:05) should appear.
Monthly archive job does not run
- Make sure Monthly Log Archive is switched on in Settings; otherwise the command exits early. Pass
--forcetophp artisan gdpr:archive-monthlyto bypass this check. - Confirm that Laravel’s scheduler is wired up (
* * * * * cd /path && php artisan schedule:runin your crontab). Without it, no scheduled task ever fires. - Check that the
localdisk is writable and thatstorage/app/gdpr/is writable (the folder is created on the fly by the job).
Archives page shows “Monthly archiving is off” or is missing from the sidebar
- The notice means Monthly Log Archive is off, so no new archive is created: switch it on in the settings page.
- The Archives menu item is only listed for admin users who have the
admin.gdpr-archive.viewpermission.
Dashboard statistics look stale
- Stats are cached for
gdpr_stats_cache_ttlseconds (default 15 minutes). The cache is automatically cleared on any log create/delete. - After a bulk import or a manual database cleanup, click Clear Stats Cache Now on the Settings page to force a recompute.
- Set
gdpr_stats_cache_ttlto0to disable caching entirely (not recommended on large datasets).
CSRF token mismatch on consent endpoints
All consent endpoints (/gdpr/accept-all, etc.) require a valid CSRF token.
The banner JavaScript reads the token from the page’s <meta name="csrf-token"> tag. If you see 419 errors:
- Ensure your Laravel session is configured correctly.
- Check that the
webmiddleware group (which includesVerifyCsrfToken) is applied to the consent routes. - If using a custom banner view, make sure it passes the CSRF token in the
X-CSRF-TOKENheader of fetch requests.
GDPR & Cookie Consent v1.0.4: A LaraClassifier / JobClass add-on.
© BeDigit. All rights reserved.