- The release package and the Composer/Packagist dist no longer ship tests, docs or development configuration (
.gitattributesexport-ignore plus unified release excludes) - Service Worker path resolution on subdirectory-core installs (Bedrock/Radicle).
ServiceWorkerManagerresolved the public webroot with core'sget_home_path(), which derives the path from$_SERVER['SCRIPT_FILENAME']and returns/whenever the entry point sits outside the core directory — every front-end request and every WP-CLI run on those installs. The per-requestfile_exists()check in the fallback registration therefore stat'd/lw-cookie-sw.js, emitting anopen_basedirwarning on every page view (reported: ~150k warnings/day, a 101 MBerror.log). The webroot is now derived from the home/site URL path delta applied toABSPATH, and falls back toABSPATHon layouts it cannot resolve. Introduced in 1.7.0; consent blocking itself was unaffected.
- The Service Worker fallback route no longer touches the filesystem when it registers on
init. The URI check inserve_sw()gates the work instead — when the static file really is in the webroot, the web server answers before WordPress boots, so the callback never runs. Removes onestat()from every request.
- Tested up to WordPress 7.1.
- Blocked-embed placeholder (lwplugins/lw-lms#18). When content blocking removed a blocked iframe's
src(YouTube, Vimeo, Maps, etc.), the visitor was left with a bare, blank frame and no signal that consent was required — most visibly on LW LMS lesson pages, whose Vimeo videos rendered as a black box (the plugin is headless, so it never rendered the iframe itself; the gap was here in LW Cookie all along).guard.jsnow replaces a blocked iframe with a placeholder that explains the block and offers an "Accept & load content" button; clicking it grants exactly the category that embed needs and loads it in place. The message and button label are admin-editable (Texts → Blocked Content) and translatable, with a bundled Hungarian translation.
- Granting consent — from the banner or the new placeholder — now restores already-blocked iframes in place via
__lwGuard.refresh(), so loading an embed no longer depends on a full page reload.
- Banner preview mode (issue #7): a "Preview banner on the site" button (General tab) opens the front-end with
?lw-cookie-preview=1, which forces the banner visible for administrators — even before it is enabled or after they have already consented — so it can be reviewed and tuned. - "Hide the banner for logged-in users" option (Advanced tab, default off) so the consent banner never pops up for administrators while they work (issue #7).
- The consent banner and floating button are now hidden inside page-builder editor canvases (Bricks
?bricks=run, Elementor preview), so they no longer clutter the builder (issue #7). - The built-in default banner texts now follow the site language (issue #7). The title, message, buttons and category names/descriptions were stored as literal English and rendered as-is; they are now text-domain-localized (with the bundled Hungarian translation) until the admin overrides them in the Texts tab.
- Consent Service Worker now registers on subdirectory-core installs (issue #5).
lw-cookie-sw.js404'd on Bedrock/Radicle:serve_sw()never overrode the query's 404 status, andinstall()wrote the file to (andregister_fallback()checked)ABSPATH— thewp/core directory — instead of the public webroot the SW URL points to. It now sendsstatus_header( 200 )and resolves the webroot viaget_home_path(). - Google Consent Mode signals now reach GTM-only setups (issue #6).
guard.jsonly sent the consent update when a globalgtag()existed, so on GTM-only sites (no gtag.js) it was never delivered and hits keptnpa=1despite consent. Consent commands now go onto thedataLayerdirectly (with agtagfallback), a GCM v2 default is set before GTM processes its queue, and a returning visitor's granted signal fires immediately instead of waiting forDOMContentLoaded.
- Quality gates: PHPStan level 5 and PHPUnit tests are now enforced in CI alongside PHPCS; minimum PHP raised to 8.2. Bumped
actions/checkoutto v7 (PR #4).
- Privacy Policy link, preferences modal title, "(Required)" badge, Cookie/Provider/Purpose/Duration/Type column headers, and the Manage Cookie Preferences / Delete All Cookies buttons now register with Polylang/WPML even when the Texts tab field is blank — previously they only appeared after a value was saved
- Translations of the above fields are now stable: registration uses the literal English source (e.g. "Privacy Policy") so subsequent edits in Polylang/WPML persist instead of being orphaned by source-string drift between requests
- Added missing
'default' => []to top-levelinput_schemaoflw-cookie/get-consent-statsso it can be invoked without arguments via the Abilities API
- Privacy Policy link text is now editable from the Texts tab and translatable via Polylang/WPML
- Cookie preferences modal: title, "(Required)" badge, and the Cookie/Provider/Purpose/Duration column headers are now editable and translatable
- Cookie declaration page (
[lw_cookie_declaration]): "Manage Cookie Preferences" button, "Delete All Cookies" button, and the Cookie/Provider/Purpose/Duration/Type column headers are now editable and translatable - Texts tab is now grouped into Banner / Buttons / Preferences Modal / Cookie Declaration Page sections, with placeholders showing the built-in default for each field
- Declared-cookie translations: cookie names containing characters that are not valid Polylang/WPML string identifiers (e.g.
wordpress_sec_*,wp-settings-1) are now sanitized when building the registration key, so translations register and resolve consistently
- Polylang, WPML, and TranslatePress integration — all admin-editable strings are registered for translation (banner texts, button labels, category names/descriptions, declared cookie provider/purpose/duration)
- Texts and Categories tabs lock source-text fields when a multilingual plugin is active, with a direct link to the matching translation UI and an "Unlock to edit source" button
- Inline lock-reason banner shown inside the disabled fieldset, naming the active multilingual plugin
- Necessary category name and description are now editable from the Categories tab
- Cookie list shown per category inside the Customize preferences modal (collapsible)
[lw_cookie_declaration]category names and descriptions now go through the Polylang/WPML translation bridge- Hungarian translation fully refreshed for the new strings
- New
banner_box_alignmentsetting (Appearance → Floating Box Alignment): choose left or right for the floating box banner
- Floating "box" banner layout now defaults to the bottom-right corner (was bottom-left)
- Floating Button settings moved from Advanced to Appearance (visual grouping)
- With the Floating Box layout, the floating button now automatically mirrors the banner alignment —
floating_button_posstill applies to the Full-width Bar layout
- Floating button stays hidden while the consent banner is visible (CSS
.lw-cookie-hiddennow covers.lw-cookie-floating-btntoo) - Settings sanitizer now preserves the stored value for keys missing from the submitted form, so locked source strings are not reset to defaults when saving any other tab
- Rename frontend CSS classes from
lw-cookie-bannertolw-cookie-noticeto prevent adblocker false positives
- LW Site Manager integration - cookie consent abilities for AI agents
lw-cookie/get-optionsability - get cookie consent settingslw-cookie/set-optionsability - update cookie consent settingslw-cookie/get-consent-statsability - get consent statisticslw-cookie/scan-cookiesability - trigger cookie scan
- Smarter autoloader fallback - supports root Composer dependency installs
- Graceful error when autoloader is missing (shows admin notice instead of fatal error)
- Inline fallback click handlers for cache-proof banner interaction
- Cookie banner buttons now work on LiteSpeed Cache servers (JS delay/defer bypassed inline config)
- LiteSpeed exclusion patterns now cover lwCookieConfig inline script and lw-cookie prefix
- Added
data-no-lazyattribute to prevent lazy loading of consent script
- Service Worker for network-level request blocking
- MutationObserver for DOM element interception (script/iframe/img)
document.cookieoverride to prevent tracking cookie writes- Inline guard.js runs before any body element is parsed
- REST API endpoint for consent logging (replaces admin-ajax)
- Works with ANY full-page cache plugin (WP Rocket, LiteSpeed, Cloudflare, etc.)
- Major: Complete rewrite to client-side blocking architecture (cache-proof)
- Google Consent Mode v2 always defaults to
denied(cache-safe) - Banner always rendered in HTML with hidden class (guard.js toggles visibility)
- Server-side ScriptBlocker (replaced by client-side guard)
- Server-side ContentBlocker output buffering (replaced by MutationObserver and Service Worker)
- AJAX nonce for consent saving (nonces get cached - now uses REST with rate limiting)
- Cache plugin compatibility layer for LiteSpeed Cache, WP Rocket, Cloudflare Rocket Loader, and PageSpeed
- Cookie banner buttons now work correctly with LiteSpeed Cache and WP Rocket (JS delay/defer compatibility)
- Minor fix
- Hash-based tab navigation on settings page
- New cookie-bite icon
- Updated ParentPage with SVG icon support from registry
- Replace dashicons with inline SVG on floating button (dashicons not available on frontend)
- Minor fix
- Minor fix
- Admin notice isolation for notices relocated by WordPress core JS
- Isolate third-party admin notices on LW plugin pages
- Fresh POT file and Hungarian (hu_HU) translation
- Plugin registry fetched from central GitHub JSON (no more per-plugin registry updates)
- Release ZIP now includes Composer autoloader for non-Composer installs
- Settings page now stays on the active tab after saving
- "Accept & Load Content" button now properly saves consent and loads blocked iframes in-place
- Cookie banner now hides when accepting content via blocked content placeholder
- All blocked content of the same category loads when any placeholder is accepted
- Google Consent Mode v2 now loads at
-PHP_INT_MAXpriority (before any other script) - Meta Pixel (Facebook) consent API support - automatic revoke/grant calls
dataLayer.pushevent for GTM triggers (lw_cookie_consent_update)- WordPress filters for third-party plugin integration
- Script blocking override filter (
lw_cookie_should_block_script)
- Scanner auto-enables all cookie categories during scan for complete detection
- Deep scan using remote headless browser for better cookie detection
- Scanner now combines local and remote scan results automatically
- "Delete All Cookies" button in cookie declaration shortcode
- Preferences modal now always renders (floating button works after consent given)
- ContentBlocker output buffer compatibility with AJAX and REST requests
- ContentBlocker now only processes HTML documents
- Content Blocking - blocks YouTube, Vimeo, Google Maps, and other embeds until consent
- HTTP header cookie detection via
wp_remote_head()
- Scanner now includes random blog posts (not just pages)
- External content scan limit removed (scans all posts)
- Native WordPress admin style for scanner UI
- Server-side Cookie Scanner - detects all cookies including HttpOnly
- LW Plugins Cookie Database API integration (2000+ cookies)
- Automatic cookie enrichment with provider, purpose, and duration
- REST API endpoints for scan results
- Multi-page scanning (home, WooCommerce cart/checkout, posts)
- Modern scanner UI with networkidle detection
- Hungarian (hu_HU) translation
- POT file for translations
- Cookie Declaration admin tab for managing cookie list
[lw_cookie_declaration]shortcode to display cookies on any page- "Add Common Cookies" quick-add feature
- GDPR consent search by consent ID or IP address (CLI)
- GDPR consent deletion/erasure support (CLI)
- Full GDPR compliance with cookie transparency
- Initial release
- GDPR-compliant cookie consent banner
- 4 cookie categories (Necessary, Functional, Analytics, Marketing)
- Customizable appearance (position, layout, colors)
- Script blocking for known tracking scripts
- Google Consent Mode v2 support
- Consent logging with anonymized IP
- Floating button for consent changes
- Modern tabbed admin interface
- Full WP-CLI support for settings, stats, and export