LW Cookie
GDPR-compliant cookie consent banner for WordPress - minimal footprint, full compliance.
Overview
| Requires WordPress | 6.0+ |
| Requires PHP | 8.1+ |
| Tested up to | 6.7 |
| License | GPL-2.0-or-later |
| GitHub | lwplugins/lw-cookie |
Installation
composer require lwplugins/lw-cookieOr upload the lw-cookie folder to /wp-content/plugins/ and activate through the Plugins menu.
Features
GDPR Compliance
- Opt-in by default - all optional categories are OFF until user consents
- Granular category selection (Necessary, Functional, Analytics, Marketing)
- Consent logging with timestamp for compliance proof
- Policy version tracking - automatic re-consent on policy changes
- Anonymized IP logging (GDPR-compliant)
Cookie Banner
- Customizable position (top, bottom, modal)
- Customizable layout (full-width bar, floating box)
- Customizable colors and border radius
- Accept All / Reject All / Customize buttons
- Floating button for easy access to change preferences
Script Blocking
- Automatic blocking of known tracking scripts until consent
- Supports Google Analytics, Facebook Pixel, Hotjar, and more
- Scripts unblock dynamically when consent is given
- Client-side blocking architecture - works with any page cache plugin
Google Consent Mode v2
- Built-in support for Google Consent Mode v2
- Required for Google Ads and Analytics in the EU
- Automatic consent signal updates
- Loads before any tracking scripts (
-PHP_INT_MAXpriority) - EEA region-specific defaults
Meta Pixel (Facebook) Support
- Automatic
fbq('consent', 'revoke/grant')API calls - Works with existing Facebook Pixel implementations
Third-Party Plugin Integration
dataLayer.pushevents for GTM triggers (lw_cookie_consent_update)- WordPress filters for other plugins to query consent state
- Script blocking override filter for plugin compatibility
Cookie Scanner
- Server-side cookie scanner detects all cookies including HttpOnly
- Integration with LW Plugins Cookie Database API (2000+ cookies)
- Automatic cookie enrichment with provider, purpose, and duration
- Multi-page scanning (home, WooCommerce cart/checkout, posts)
Cookie Categories
| Category | Description | Default |
|---|---|---|
| Necessary | Essential for website function | Always enabled |
| Functional | Enhanced functionality and personalization | Off until consent |
| Analytics | Visitor analytics and statistics | Off until consent |
| Marketing | Advertising and remarketing | Off until consent |
Settings
Configure under LW Plugins > Cookie. The settings page uses a tabbed interface:
| Tab | Description |
|---|---|
| General | Enable/disable, policy version, consent mode |
| Appearance | Colors, position, layout, border radius |
| Texts | Customize all labels and messages |
| Categories | Cookie category descriptions |
| Declaration | Manage declared cookies |
General Settings
Enable Cookie Banner
Option: enabled | Default: true
Enables or disables the cookie consent banner on the frontend. When disabled, no banner will be shown and no scripts will be blocked.
Privacy Policy Page
Option: privacy_policy_page | Default: 0 (none)
Select the page containing your privacy policy. This page will be linked in the cookie banner, allowing users to review your privacy practices before making a consent decision.
Policy Version
Option: policy_version | Default: 1.0
The current version of your cookie/privacy policy. When you update this version number, all existing consents become invalid and users will be prompted to consent again.
Best Practice: Increment this version whenever you:
- Add new cookie categories
- Change how cookies are used
- Update your privacy policy significantly
Appearance Settings
Banner Position
Option: banner_position | Default: bottom
| Value | Description |
|---|---|
bottom | Fixed bar at the bottom of the viewport |
top | Fixed bar at the top of the viewport |
modal | Centered modal overlay |
Banner Layout
Option: banner_layout | Default: bar
| Value | Description |
|---|---|
bar | Horizontal bar spanning the viewport width |
box | Compact box in the corner |
Primary Color
Option: primary_color | Default: #2271b1
The primary color used for buttons (Accept All, Save Preferences). Accepts any valid CSS color value.
Text Color
Option: text_color | Default: #1d2327
The color used for banner text content.
Background Color
Option: background_color | Default: #ffffff
The background color of the cookie banner and preferences modal.
Border Radius
Option: border_radius | Default: 4
Border radius in pixels for buttons and the banner container. Set to 0 for sharp corners.
Categories Settings
LW Cookie uses four cookie categories as recommended by GDPR guidelines:
Necessary (Required)
Always enabled and cannot be disabled by users. These cookies are essential for basic website functionality.
Examples: Session cookies, shopping cart cookies, security cookies (CSRF tokens), cookie consent preferences.
Functional
Options: cat_functional_name (default: “Functional”), cat_functional_desc
Cookies that enhance website functionality and personalization but are not strictly necessary.
Examples: Language preferences, region/timezone settings, user interface customization, recently viewed items.
Analytics
Options: cat_analytics_name (default: “Analytics”), cat_analytics_desc
Cookies used to collect information about how visitors use the website.
Examples: Google Analytics, Matomo/Piwik, Hotjar, Microsoft Clarity.
Marketing
Options: cat_marketing_name (default: “Marketing”), cat_marketing_desc
Cookies used for advertising and tracking across websites.
Examples: Google Ads, Facebook Pixel, LinkedIn Insight Tag, retargeting cookies.
Texts Settings
All text displayed in the cookie banner can be customized:
| Option | Default | Description |
|---|---|---|
banner_title | We value your privacy | Heading at the top of the cookie banner |
banner_message | We use cookies to enhance your browsing experience and analyze our traffic. | Main message explaining why cookies are used |
btn_accept_all | Accept All | Accepts all cookie categories |
btn_reject_all | Reject All | Rejects all optional categories |
btn_customize | Customize | Opens the preferences modal |
btn_save | Save Preferences | Saves custom category selections |
Advanced Settings
Consent Duration
Option: consent_duration | Default: 365 (days)
How long the consent cookie is stored. After this period, users will be prompted to consent again.
GDPR Recommendation: Maximum 12 months (365 days).
Script Blocking
Option: script_blocking | Default: true
When enabled, known tracking scripts are automatically blocked until the user provides consent for the relevant category.
Blocked Scripts Include:
- Google Analytics (analytics category)
- Google Tag Manager (analytics category)
- Facebook Pixel (marketing category)
- Hotjar (analytics category)
- LinkedIn Insight (marketing category)
- Twitter/X Pixel (marketing category)
- TikTok Pixel (marketing category)
- Pinterest Tag (marketing category)
- Snapchat Pixel (marketing category)
Google Consent Mode
Option: gcm_enabled | Default: false
Enables Google Consent Mode v2 integration. When enabled, consent signals are automatically sent to Google services.
Show Floating Button
Option: show_floating_button | Default: true
Shows a small floating button allowing users to re-open the cookie preferences modal after they’ve made their initial choice.
Floating Button Position
Option: floating_button_pos | Default: bottom-left
| Value | Description |
|---|---|
bottom-left | Bottom left corner |
bottom-right | Bottom right corner |
Cookie Declaration
Admin Management
Navigate to LW Plugins > Cookie > Cookies to declare all cookies used on your website.
For each cookie, you can specify:
- Cookie Name - The actual cookie name (e.g.,
_ga,_fbp) - Provider - Who sets this cookie (e.g., Google Analytics, Facebook)
- Purpose - What the cookie is used for
- Duration - How long the cookie is stored (e.g., 1 year, Session)
- Category - Which consent category it belongs to
- Type - Session (deleted when browser closes) or Persistent
Use the “Add Common Cookies” button to quickly add commonly used cookies (WordPress, Google Analytics, Facebook Pixel).
Shortcode
Display your cookie declaration on any page using the shortcode:
[lw_cookie_declaration]Attributes:
| Attribute | Default | Description |
|---|---|---|
class | (empty) | Additional CSS class for styling |
Example:
[lw_cookie_declaration class="my-custom-table"]The shortcode displays:
- Cookies grouped by category
- Category names and descriptions
- Full cookie details (name, provider, purpose, duration, type)
- “Manage Cookie Preferences” button
- Responsive table design (mobile-friendly)
Shortcodes
| Shortcode | Description |
|---|---|
[lw_cookie_declaration] | Display cookie declaration table on any page |
WP-CLI Commands
LW Cookie provides comprehensive WP-CLI support for managing settings and consent data from the command line.
Available Commands
| Command | Description |
|---|---|
wp lw-cookie settings list | List all settings with current values |
wp lw-cookie settings get <key> | Get a specific setting value |
wp lw-cookie settings set <key> <value> | Set a specific setting value |
wp lw-cookie settings reset | Reset all settings to defaults |
wp lw-cookie keys | Show all available setting keys |
wp lw-cookie stats | Display consent statistics |
wp lw-cookie export | Export consent logs |
wp lw-cookie clear-logs | Clear consent logs |
Settings Management
List All Settings
# Table format (default)
wp lw-cookie settings list
# JSON format
wp lw-cookie settings list --format=json
# YAML format
wp lw-cookie settings list --format=yamlGet a Setting
wp lw-cookie settings get enabled
# Output: true
wp lw-cookie settings get primary_color
# Output: #2271b1Set a Setting
# Enable/disable banner
wp lw-cookie settings set enabled true
wp lw-cookie settings set enabled false
# Change colors
wp lw-cookie settings set primary_color "#ff6600"
wp lw-cookie settings set background_color "#f5f5f5"
# Change texts
wp lw-cookie settings set banner_title "Cookie Settings"
wp lw-cookie settings set btn_accept_all "Accept Cookies"
# Change position
wp lw-cookie settings set banner_position top
wp lw-cookie settings set banner_position modal
# Enable Google Consent Mode
wp lw-cookie settings set gcm_enabled true
# Set consent duration (days)
wp lw-cookie settings set consent_duration 180Reset Settings
wp lw-cookie settings reset
# Resets all settings to default valuesView Available Keys
wp lw-cookie keys
# Output:
# +------------------------+-------------------------------------+---------+
# | key | description | default |
# +------------------------+-------------------------------------+---------+
# | enabled | Enable/disable cookie banner | true |
# | privacy_policy_page | Privacy policy page ID | 0 |
# | policy_version | Current policy version | 1.0 |
# | banner_position | Banner position (bottom, top, modal)| bottom |
# | ... | ... | ... |
# +------------------------+-------------------------------------+---------+Consent Statistics
# Default: last 30 days
wp lw-cookie stats
# Custom time period
wp lw-cookie stats --days=7
wp lw-cookie stats --days=90
# JSON output
wp lw-cookie stats --format=jsonExample output:
+--------------------------------+-------+
| metric | value |
+--------------------------------+-------+
| Total consents (all time) | 1543 |
| Consents (last 30 days) | 234 |
| Accept All (last 30 days) | 156 |
| Reject All (last 30 days) | 45 |
| Customize (last 30 days) | 33 |
| Accept All rate | 66.7% |
| Reject All rate | 19.2% |
+--------------------------------+-------+Export Consent Logs
# Export to table (default)
wp lw-cookie export
# Export to CSV file
wp lw-cookie export --format=csv > consents.csv
# Export to JSON
wp lw-cookie export --format=json --limit=1000
# Export last 30 days only
wp lw-cookie export --days=30 --format=csvClear Consent Logs
# Delete all logs (requires confirmation)
wp lw-cookie clear-logs
# Skip confirmation
wp lw-cookie clear-logs --yes
# Delete only old logs
wp lw-cookie clear-logs --older-than=365 --yesGDPR Data Requests (CLI)
Find Consent Records
# Search by consent ID
wp lw-cookie consent --consent-id=abc123-def456-xyz789
# Search by IP address (will be hashed internally)
wp lw-cookie consent --ip=192.168.1.100
# Export to JSON
wp lw-cookie consent --ip=192.168.1.100 --format=jsonDelete Consent Records (Right to Erasure)
# Find and delete records
wp lw-cookie consent --consent-id=abc123-def456 --delete
# With confirmation skip
wp lw-cookie consent --ip=192.168.1.100 --delete --yesAutomation Examples
Backup Settings Before Update
# Export current settings
wp lw-cookie settings list --format=json > lw-cookie-backup.jsonDeploy Settings Across Environments
# On staging/production
wp lw-cookie settings set enabled true
wp lw-cookie settings set gcm_enabled true
wp lw-cookie settings set policy_version "2.0"
wp lw-cookie settings set primary_color "#0066cc"Scheduled Log Cleanup (Cron)
# Add to crontab: delete logs older than 1 year
0 0 1 * * cd /var/www/html && wp lw-cookie clear-logs --older-than=365 --yesMonthly Statistics Report
#!/bin/bash
echo "=== LW Cookie Monthly Report ==="
echo "Date: $(date)"
wp lw-cookie stats --days=30 --format=tableJavaScript API
LW Cookie exposes a global LWCookie object for programmatic access:
Methods
// Accept all cookies
LWCookie.acceptAll();
// Reject all optional cookies
LWCookie.rejectAll();
// Open the preferences modal
LWCookie.openPreferences();
// Get current consent state
const consent = LWCookie.getConsent();
// Returns: { necessary: true, functional: false, analytics: false, marketing: false }
// Check if a specific category is allowed
if (LWCookie.isAllowed('analytics')) {
// Load analytics scripts
}Events
Listen for consent changes:
window.addEventListener('lwCookieConsent', function(e) {
console.log('Consent updated:', e.detail.categories);
console.log('Action:', e.detail.action); // 'accept_all', 'reject_all', or 'customize'
if (e.detail.categories.analytics) {
// User accepted analytics cookies
}
});Conditional Script Loading
You can use the API to conditionally load scripts:
document.addEventListener('DOMContentLoaded', function() {
if (LWCookie.isAllowed('analytics')) {
// Load Google Analytics
var script = document.createElement('script');
script.src = 'https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID';
document.head.appendChild(script);
}
});Google Consent Mode
When Google Consent Mode is enabled, LW Cookie automatically manages the following consent signals:
| Signal | Cookie Category |
|---|---|
analytics_storage | Analytics |
ad_storage | Marketing |
ad_user_data | Marketing |
ad_personalization | Marketing |
Default State
Before user consent, all signals default to denied:
gtag('consent', 'default', {
'analytics_storage': 'denied',
'ad_storage': 'denied',
'ad_user_data': 'denied',
'ad_personalization': 'denied'
});After Consent
When users provide consent, signals are updated accordingly:
gtag('consent', 'update', {
'analytics_storage': 'granted', // if analytics accepted
'ad_storage': 'granted', // if marketing accepted
'ad_user_data': 'granted', // if marketing accepted
'ad_personalization': 'granted' // if marketing accepted
});Script Blocking
How It Works
When script blocking is enabled, the plugin:
- Scans all
<script>tags during page load - Identifies known tracking scripts by their URL patterns
- Blocks scripts that require consent for categories the user hasn’t accepted
- Automatically unblocks and loads scripts when consent is granted
Blocked Script Patterns
| Pattern | Category |
|---|---|
google-analytics.com | Analytics |
googletagmanager.com | Analytics |
facebook.net | Marketing |
connect.facebook.net | Marketing |
hotjar.com | Analytics |
clarity.ms | Analytics |
linkedin.com/insight | Marketing |
ads.twitter.com | Marketing |
tiktok.com | Marketing |
pintrk | Marketing |
snap.licdn.com | Marketing |
Custom Script Blocking
For scripts not automatically detected, use the type attribute:
<!-- Block until analytics consent -->
<script type="text/plain" data-consent-category="analytics" data-src="https://example.com/analytics.js"></script>
<!-- Block until marketing consent -->
<script type="text/plain" data-consent-category="marketing" data-src="https://example.com/pixel.js"></script>Database & GDPR Compliance
Consent Logging
All consent actions are logged to the {prefix}lw_cookie_consents table:
| Column | Description |
|---|---|
id | Auto-increment ID |
consent_id | UUID v4 identifier |
ip_hash | SHA-256 hashed IP (anonymized) |
categories | JSON object of consent choices |
policy_version | Policy version at time of consent |
action_type | accept_all, reject_all, or customize |
user_agent | Browser user agent string |
created_at | Timestamp of consent |
Cookie Structure
Consent is stored in a cookie named lw_cookie_consent containing base64-encoded JSON:
{
"id": "uuid-v4",
"version": "1.0",
"timestamp": 1706745600,
"categories": {
"necessary": true,
"functional": false,
"analytics": false,
"marketing": false
}
}GDPR Compliance Features
- Opt-in by default: All optional categories are OFF by default
- Granular control: Users can select individual categories
- Easy withdrawal: Floating button allows changing preferences anytime
- Consent proof: All consents are logged with timestamps
- Re-consent: Policy version changes trigger new consent requests
- IP anonymization: IP addresses are hashed, not stored in plain text
- Data retention: Consent logs can be purged based on your retention policy
Data Export
To export consent data for a specific user (GDPR data request):
SELECT * FROM wp_lw_cookie_consents
WHERE consent_id = 'user-consent-uuid';Data Deletion
To delete consent data (GDPR erasure request):
DELETE FROM wp_lw_cookie_consents
WHERE consent_id = 'user-consent-uuid';Hooks & Filters
Filters
// Get consent categories and their states
$categories = apply_filters( 'lw_cookie_consent_categories', [] );
// Returns: ['necessary' => true, 'analytics' => false, 'marketing' => true]
// Check if user has given any consent
$has_consent = apply_filters( 'lw_cookie_has_consent', false );
// Check if a specific category is allowed
$analytics_ok = apply_filters( 'lw_cookie_is_category_allowed', false, 'analytics' );
// Get current consent ID
$consent_id = apply_filters( 'lw_cookie_consent_id', null );Example: conditional script loading
// Load analytics only if user consented
if ( apply_filters( 'lw_cookie_is_category_allowed', false, 'analytics' ) ) {
wp_enqueue_script( 'my-analytics', '...' );
}REST API
LW Cookie uses REST API endpoints for consent logging (replaces admin-ajax for cache compatibility).
AI Abilities
When used with LW Site Manager, the following abilities are available for AI agents. All abilities are registered under the cookie category and require manage_options capability.
lw-cookie/get-options (readonly)
Get all LW Cookie consent settings.
Input: none
Output:
{
"success": true,
"options": {
"enabled": true,
"banner_position": "bottom",
"banner_layout": "bar",
"primary_color": "#d4a017",
"consent_duration": 365,
"script_blocking": true,
"gcm_enabled": false
}
}lw-cookie/set-options (write)
Update one or more LW Cookie settings. Only the provided keys are changed.
Input:
{
"options": {
"enabled": true,
"banner_position": "top",
"primary_color": "#2271b1",
"consent_duration": 180
}
}Writable keys: enabled, privacy_policy_page, policy_version, banner_position, banner_layout, primary_color, text_color, background_color, border_radius, cat_functional_name, cat_functional_desc, cat_analytics_name, cat_analytics_desc, cat_marketing_name, cat_marketing_desc, banner_title, banner_message, btn_accept_all, btn_reject_all, btn_customize, btn_save, consent_duration, script_blocking, content_blocking, gcm_enabled, show_floating_button, floating_button_pos
Output:
{
"success": true,
"message": "3 option(s) updated.",
"updated": ["banner_position", "primary_color", "consent_duration"]
}lw-cookie/get-consent-stats (readonly)
Get consent logging statistics from the database, grouped by action type.
Input:
| Field | Type | Default | Description |
|---|---|---|---|
days | integer | 30 | Number of past days to include |
Output:
{
"success": true,
"stats": {
"accept_all": 142,
"reject_all": 38,
"customize": 21
},
"total": 201,
"period_days": 30
}lw-cookie/scan-cookies (write)
Trigger an HTTP header pre-scan across site URLs. Sends HEAD requests to home, pages, posts, and WooCommerce URLs to detect cookies set via Set-Cookie headers. Results are merged into the persistent scanner storage.
Input: none
Output:
{
"success": true,
"cookies": ["_ga", "wc_cart_hash", "wordpress_sec"],
"domains": [],
"urls_count": 12
}Note: This is a write ability because it performs HTTP requests and modifies stored scanner data. For a full browser-based scan (JS cookies, external domains, fonts), use the admin scanner UI.
Troubleshooting
Banner Not Showing
- Check if the plugin is enabled in settings
- Clear any caching plugins
- Check browser console for JavaScript errors
- Verify the consent cookie doesn’t already exist
Scripts Still Loading
- Ensure Script Blocking is enabled
- Check if the script URL matches known patterns
- For custom scripts, add the appropriate data attributes
- Clear server-side cache after changing settings
Google Consent Mode Not Working
- Enable GCM in Advanced settings
- Ensure
gtagis loaded before LW Cookie - Verify consent signals in browser console:
console.log(window.dataLayer);
FAQ
Is this plugin GDPR compliant?
This plugin provides the technical framework for GDPR-compliant cookie consent. However, compliance also depends on how you configure it and your overall privacy practices. Ensure you have a proper privacy policy and only use cookies as described.
How do I customize the banner appearance?
Go to LW Plugins > Cookie > Appearance to customize colors, position, and layout.
What scripts are automatically blocked?
The plugin automatically detects and blocks known tracking scripts including Google Analytics, Google Tag Manager, Facebook Pixel, Hotjar, LinkedIn Insight Tag, Twitter Pixel, TikTok Pixel, Microsoft Clarity, and more.
How does Google Consent Mode work?
When enabled, the plugin sets Google Consent Mode v2 signals based on user consent. This is required for Google Ads and Analytics to function properly in the EU.
Can users change their consent after accepting?
Yes. If you enable the floating button in settings, users can click it anytime to open the preferences modal and change their choices.
Is consent logged?
Yes. All consent actions are logged to the database with a unique consent ID, anonymized IP hash, categories selected, policy version, and timestamp.
What happens when I update my privacy policy?
Change the “Policy Version” setting in the General tab. Users will be asked for consent again on their next visit.
Does it work with page cache plugins?
Yes. Since v1.6.0, LW Cookie uses a client-side blocking architecture that works with any full-page cache plugin (WP Rocket, LiteSpeed Cache, Cloudflare, etc.).