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 the gdpr:consent browser event fired on window when the visitor makes a choice.
  • Only load analytics when analytics is true.

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 marketing consent 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+
Note: This add-on is fully standalone: it has no dependencies on other add-ons. It works out of the box once activated.

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.

Cannot upload from the browser? Unzip the archive on your computer and copy the add-on folder to 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
Check your spam folder. For both bedigit.com Store and Gumroad purchases, the purchase code is delivered by email. Automated license emails are very often filtered, so if the message is not in your inbox, look in your spam / junk folder before contacting support, and add our sender address to your contacts or allow list.

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?
Lost your purchase code? Search your mailbox (spam folder included) for “license” or “purchase code”, then check My Account → My Licenses on bedigit.com for Store and Gumroad purchases, or Downloads → License certificate on Envato. If it is still missing, open a ticket on our Help Center with your order number (Store), Gumroad sale ID or buyer email (Gumroad), or Envato username and item name (Envato).

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 (default gdpr_consent): name of the consent cookie.
  • archive_disk (default local) and archive_path (default gdpr): where monthly archive files are stored.
  • admin_per_page (default 25): 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.

Note: Disabling a category in admin removes it from the banner entirely: visitors won’t see the toggle for that category in the preferences panel.

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-logs task. 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 0 to 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 0 to 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). Requires admin.gdpr.export.
  • Purge Now: queues the PurgeConsentLogsJob to immediately delete database rows and archive files beyond the retention period (asks for confirmation). The job runs on your queue connection. Requires admin.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 a whereDate(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:

  1. Streams every log of that month into a CSV buffer (1000 rows at a time).
  2. Gzips the CSV and writes it to the private disk at the path above.
  3. Deletes the archived rows from gdpr_consent_logs in chunks of 1000, inside a single database transaction.
  4. 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).

Path safety: the download endpoint validates the 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)

  1. Download the latest .zip file of the add-on.
  2. Go to Admin panel → Extensions → Add-ons and click Upload add-on.
  3. Drop the .zip file into the upload area.
  4. 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

  1. 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.
  2. Open Admin panel → Extensions → Add-ons: the page re-reads addon.json and 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:

  1. Deactivate GDPR & Cookie Consent (see Uninstallation).
  2. 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 migrations table, so a later reinstall migrates from scratch;
  • deletes its published assets: public/addons/gdpr/, public/vendor/gdpr/ and storage/app/public/addons/gdpr/;
  • deletes the add-on directory extensions/addons/gdpr/;
  • deletes its row in the addons table (the recorded purchase code goes with it) and clears the application cache.
This cannot be undone. Back up your database before removing an add-on whose data you may still need: installing it again later creates empty tables, not your old content, and asks for the purchase code again.

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_consent cookie 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_PATH value in .env, admin by 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 GdprServiceProvider is 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_logs table 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_consent cookie (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 InjectCookieBanner middleware 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, both gdpr:purge-logs (daily) and gdpr: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 --force to php artisan gdpr:archive-monthly to bypass this check.
  • Confirm that Laravel’s scheduler is wired up (* * * * * cd /path && php artisan schedule:run in your crontab). Without it, no scheduled task ever fires.
  • Check that the local disk is writable and that storage/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.view permission.

Dashboard statistics look stale

  • Stats are cached for gdpr_stats_cache_ttl seconds (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_ttl to 0 to 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 web middleware group (which includes VerifyCsrfToken) is applied to the consent routes.
  • If using a custom banner view, make sure it passes the CSRF token in the X-CSRF-TOKEN header of fetch requests.

GDPR & Cookie Consent v1.0.4: A LaraClassifier / JobClass add-on.

© BeDigit. All rights reserved.

Was this article helpful?

Thank you for your feedback!

Still need help? Create a support ticket

Create a Ticket