Tired of cookie consent plugins that lock essential features behind paywalls, require cloud accounts, or send your visitors' data to third-party servers?
FAZ Cookie Manager is a WordPress plugin that helps you implement cookie consent and privacy workflows for international regulations -- completely free, with no strings attached.
No account to create. The plugin requires no cloud service connection. Basic features like consent logging and geo-targeting are included -- no premium plan needed. Core consent features run on your own server, and you own all your data.
Why FAZ Cookie Manager?
Most cookie consent plugins follow the same pattern: a free version with crippled features, and a paid tier starting at $10-50/month that unlocks what you actually need (cookie scanning, consent logs, Google Consent Mode, IAB TCF). FAZ Cookie Manager breaks that model:
- Cookie scanner -- Scans your site directly from your browser. No external service, no API limits, no waiting.
- Cookie Policy generator -- Build a jurisdiction-aware Cookie Policy page directly from your admin. Pick GDPR / CCPA / LGPD / POPIA, fill in your company details, and publish via the
[faz_cookie_policy_complete] shortcode. Output ships in en, it, fr, de, es, pt-BR, bg and cs, pulls the live cookie inventory from the scanner, and lets you replace individual sections per jurisdiction and language. Empty editors keep the shipped text as their placeholder; languages without a bundled scaffold, such as Slovak, use the reviewed fallback until you write their text. The standalone [faz_cookie_table] shortcode (and the matching Gutenberg block) still works for embedding just the cookie list.
- Consent logging with CSV export -- Every consent is recorded locally in your database. Export anytime for audits.
- Google Consent Mode v2 -- Sends all 7 consent signals to Google tags. No premium required.
- IAB TCF v2.3 -- Full Transparency and Consent Framework API and UI, built in. To operate as a recognised CMP in the IAB framework you must enter your own registered IAB Europe CMP ID; without one the TCF interface stays inactive (no TC string is produced) so invalid signals are never broadcast to vendors.
- Geo-targeting -- Show banners only to visitors from regulated regions (EU, California, etc.).
- 180+ languages -- Translate every string in the banner, or use one of the built-in translations.
- Script blocking -- Tag any script with
data-faz-tag to block it until the right category is accepted.
- Guided setup wizard (NEW in 1.25.0) -- a first-run wizard detects your environment (multilingual plugin, page cache, WooCommerce, existing consent data) and configures defaults that match your jurisdiction, explaining each choice in plain language. First setup—or switching consent model—applies the expiry and notice controls shown in review; reopening without changing model preserves custom expiry and button visibility. Existing sites are treated as already set up and are never nagged.
- Editable Cookie Policy text (NEW in 1.25.0) -- rewrite any section of the generated policy from the admin, per jurisdiction and per language. Placeholders such as {{COMPANY_NAME}} keep working inside your own wording, and an empty box keeps the reviewed text that ships with the plugin. You can also write the policy in a language the plugin ships no template for -- pick the language, and your text is stored against it. Each override remembers the section it was written for, so a future update that reorders the templates falls back to the reviewed original instead of putting your wording under the wrong heading.
- A/B test your consent banner (NEW in 1.25.0) -- run two or more of your existing banners at once with a persistent random split, then read the accept rate per variant on the Dashboard. Only active, independently compliant banners take part, so improving your wording can never quietly turn into a dark pattern. Off by default.
- Schrems II transfer disclosure (NEW in 1.25.0) -- flag, per cookie, that a service sends personal data to a country without an EU adequacy decision, together with the safeguard you rely on. It appears in the preference centre and in the generated Cookie Policy, worded neutrally: it states the fact and your described safeguard, and never claims that safeguard is legally sufficient. Off by default.
- Age-appropriate consent, GDPR Art. 8 (NEW in 1.25.0) -- an optional age-confirmation checkbox above the buttons. It gates only Accept, never Reject or withdraw, so the two keep equal weight. This is a self-declared affirmation and is not a substitute for the parental-consent verification Art. 8(2) requires. Off by default.
- Ad-blocker resilience (NEW in 1.25.0) -- keeps the legally required notice visible when a cosmetic filter list hides elements whose class contains "cookie" or "consent". A single deferred re-assert: no loop, no cookie wall. It protects a mandatory notice, it does not circumvent a privacy tool. Off by default.
- Editable "Do Not Sell" opt-out text -- customise the title, description and toggle label of the CCPA / US State Laws "Opt-out Preferences" popup, per language, right from the banner editor.
- E-commerce & payment friendly -- a per-gateway opt-in (PayPal, Stripe, Square, Braintree, Klarna, Mollie, Amazon Pay) lets your checkout and payment forms load their SDK before consent when you enable that gateway, so pre-consent blocking never breaks a payment button. Off by default; a real WooCommerce checkout/cart is exempt automatically.
- Cache & object-cache compatible -- automatically purges and bypasses FlyingPress, LiteSpeed, WP Rocket, W3 Total Cache and more on save; epoch-invalidates on Redis Object Cache / Memcached; and keeps WPML, Polylang, TranslatePress and Weglot banners in the right language even behind a full-page cache. See "Cache Plugin Compatibility" below.
- Microsoft UET/Clarity -- Consent integration for Microsoft advertising and analytics tools.
- Revisit consent widget -- Floating button lets visitors change their preferences anytime.
- Accessibility-focused -- Keyboard navigation (Tab, Enter, Escape), screen-reader support, mobile responsive.
Helps with these frameworks
This plugin assists consent and privacy workflows. It does not itself create, provide, or guarantee legal compliance, and you remain responsible for the final configuration for your site and jurisdiction.
- GDPR (EU General Data Protection Regulation) -- Opt-in consent, granular categories, right to withdraw
- CCPA / CPRA (California Consumer Privacy Act) -- "Do Not Sell or Share" opt-out link
- ePrivacy Directive (EU Cookie Law) -- Consent-based script blocking support
- Italian Garante Privacy -- 6-month consent expiry setting and consent logging controls
- EDPB Guidelines -- No scroll-as-consent, no pre-checked categories, equal button prominence options
- LGPD (Brazil General Data Protection Law) -- Consent-based model
- POPIA (South Africa Protection of Personal Information Act) -- Conservative consent-based preset under s.11(1)(a); other s.11(1)(b)-(f) justifications require separate assessment
Try it Live
Try FAZ Cookie Manager in WordPress Playground -- no account, no install, runs entirely in your browser.
How it works
- Install and activate -- the cookie banner appears immediately with sensible defaults
- Scan your site to detect cookies automatically
- Customize the banner design, text, and colors to match your brand
- Enable Google Consent Mode or IAB TCF if you use advertising tools
- Monitor consent analytics on the dashboard
Core banner functionality runs on your WordPress site. Optional update/download features may contact GitHub, IAB Europe, MaxMind,
ip-api.com,
ipinfo.io (opt-in VPN detection), or the AMP CDN depending on which features you enable and use.
Cookie Policy generator (1.16.0+)
Need a Cookie Policy page that explains the cookies your site sets, the jurisdiction it operates under, and who the visitor should contact about their data? FAZ Cookie Manager 1.16.0 ships a dedicated
Cookie Policy admin tab plus the
[faz_cookie_policy_complete] shortcode.
- Jurisdiction-aware -- pick GDPR (EU/EEA/UK), CCPA/CPRA (California), LGPD (Brazil), or POPIA (South Africa). Each jurisdiction ships its own template scaffold with the legal references and required sections for that framework.
- Multilingual (8 languages out of the box) -- en, it, fr, de, es, pt-BR, bg, cs. Override per render with
[faz_cookie_policy_complete lang="it"] or let the visitor's browser language pick. The GDPR, CCPA and LGPD sections are exposed through faz-cookie-manager.pot (the bundled Czech catalogue includes all 33 of them); the POPIA sections ship as reviewed per-language templates and will join the POT at the next catalogue resync.
- Editable section text, per jurisdiction and language -- the advanced Policy text card exposes each effective section as an optional textarea. The shipped wording is the placeholder, not the saved value: leave it empty to keep receiving reviewed plugin updates, or write Markdown that still uses placeholders such as
{{COMPANY_NAME}}. The language selector uses the full site-wide catalogue, so an administrator can author Slovak (sk) or another unbundled language against the reviewed jurisdiction fallback.
- Auto-populated cookie inventory -- the rendered policy pulls live from
wp_faz_cookies, so any cookie discovered by the scanner shows up at the next render with its category, duration and description, in the active language.
- Filled with your company data -- name, address, DPO email, third-party services, retention period: stored in
faz_cookie_policy_data option, edited via the admin form, never seeded from admin_email or blogname (PII protection).
- Legal disclaimer -- every generated policy shows a localized warning by default that the templates are starting points, not legal advice. Administrators can hide it or replace it with reviewed custom text in the Cookie Policy settings.
- Versioning hash -- a
data-faz-policy-version attribute on the rendered article tracks effective template + gettext override + data drift over time. Display-only fields (the visible "Last updated" date) are excluded so the hash doesn't change daily.
- Filter for site builders --
faz_cookie_policy_data lets you inject custom placeholders before template substitution.
- Backwards compatible -- the long-standing
[faz_cookie_policy] shortcode (with site_name / contact / show_table attributes from 1.7.0) is unchanged. The standalone [faz_cookie_table] shortcode and matching faz/cookie-table Gutenberg block still work for embedding just the cookie inventory table.
Multi-banner geo-routing vs multilingual content (1.14.0+)
These are two
orthogonal features that combine freely — multi-banner is per
country, multilingual content is per
language inside each banner.
- Multi-banner geo-routing picks WHICH banner profile to serve based on the visitor's country. Typical setup: a strict GDPR banner for EU/EEA/UK and a CCPA opt-out banner for California (or any other per-region compliance profile). Country resolution chain: Cloudflare
CF-IPCountry header (opt-in via the faz_trust_cf_ipcountry_header filter) → MaxMind GeoLite2 → ip-api.com fallback. Each banner row carries its own target_countries list and a priority integer for overlap resolution.
- Multilingual content lives INSIDE each banner. A single banner stores translations of its title, description and button labels for as many languages as you enable on the Languages page. The language displayed to the visitor is resolved CLIENT-SIDE from
navigator.languages so a country-targeted banner can still be served from a full-page cache (LiteSpeed / WP Rocket / Cloudflare APO) and the right language renders on hydration.
Practical example: an install needs only TWO banner rows, not eight. One EU-targeted GDPR banner with English + Italian + German + French + Polish translations inside, and one US-targeted CCPA banner with English + Spanish translations inside. The country selects the banner; the browser selects the translation inside the banner. Visitors hitting the right cache key get the right banner + the right language.
From the
WordPress.org plugin directory (recommended)
- In your WordPress dashboard go to Plugins > Add New Plugin
- Search for FAZ Cookie Manager
- Click Install Now, then Activate
- Go to FAZ Cookie in the admin sidebar to configure your banner
Manual installation
- Download the ZIP from wordpress.org/plugins/faz-cookie-manager
- In your WordPress dashboard go to Plugins > Add New Plugin > Upload Plugin
- Upload the ZIP and click Install Now, then Activate
- Go to FAZ Cookie in the admin sidebar to configure your banner
The full changelog (every release back to 1.0.0) lives at:
https://github.com/fabiodalez-dev/FAZ-Cookie-Manager/blob/main/CHANGELOG.md
and on the GitHub Releases page:
https://github.com/fabiodalez-dev/FAZ-Cookie-Manager/releases
1.25.0
- Added: administrator-editable Cookie Policy sections, isolated by jurisdiction and language. Shipped text remains the empty textarea placeholder, authored Markdown keeps the normal placeholder substitution pipeline, and unbundled languages such as Slovak can be written against the reviewed jurisdiction fallback. A stored section-heading anchor disables stale overrides after scaffold drift instead of placing legal text under the wrong heading.
- Added: POPIA (South Africa) jurisdiction - a conservative s.11(1)(a) consent-based setup preset (with explicit notice that POPIA also permits the s.11(1)(b)-(f) justifications), a ZA geo region, and Cookie Policy templates in every bundled language covering the Information Officer, data-subject rights under s.23-25, objection under s.11(3), and the PAIA s.25 30-day access window.
- Added: guided first-run setup wizard (8 steps) - detects the environment (multilingual plugin, page cache, WooCommerce, existing consent data) and configures jurisdiction-correct defaults. First setup—or switching consent model—applies the expiry and notice controls shown in review; reopening without changing model preserves custom expiry and button visibility. Upgrading installs are treated as already onboarded and are never nagged.
- Added: A/B testing of banner variants - run two or more active banners with a persistent random split and read the accept rate per variant on the Dashboard. Only active, independently compliant banners take part. Default off; skipped under Cache Compatibility Mode.
- Added: inline age-appropriate consent gate (GDPR Art. 8) - an optional age-confirmation checkbox that gates only the accept path, never Reject, withdraw or close, so button weight stays equal. Self-declared affirmation only, not a substitute for the parental-consent verification Art. 8(2) requires. Default off.
- Added: per-cookie Schrems II third-country transfer disclosure, shown in the preference-center declaration and the generated Cookie Policy. The wording names the fact and the safeguard the admin describes, and never asserts that the safeguard is legally sufficient. Default off.
- Added: opt-in banner resilience against ad-block cosmetic filter lists - one deferred re-assert that keeps the mandatory notice visible, with no loop and no cookie wall. Default off.
- Added: placeholder blocking for Smash Balloon Instagram Feed and the Elementor Video widget, contributed by @roboes (#190).
- Added: the generated Cookie Policy text is now editable - one box per section, per jurisdiction and per language, on a collapsed "Policy text" card. An empty box keeps the reviewed shipped text; placeholders keep resolving inside your own wording. Languages the plugin ships no template for can be selected too, so a policy can be written in any language without editing plugin files. Each override remembers the heading it was written against and deactivates if a later release reorders the templates.
- Changed: a jurisdiction="..." shortcode override no longer bypasses that jurisdiction's mandatory fields. It previously rendered even with those fields unset, on the reasoning that a degraded policy beat a blank page - the wrong trade for a legal document. Administrators now see the configuration notice; anonymous visitors receive nothing, so an incomplete policy is never published. If you use a shortcode override, fill in that jurisdiction's required fields.
- Security: the consent dashboard widget is now gated on capability, and the CCPA opt-out endpoints enforce a strict same-origin (Fetch Metadata with Referer fallback) check.
- Fixed: provider scripts whose blocking pattern ends on a separator were never blocked - the HubSpot tracker ran before consent (#196). A pattern such as js.hs-scripts.com/ already carries its own right-hand boundary, so demanding another separator after it meant js.hs-scripts.com/12345.js went unblocked. Twenty shipped provider definitions were affected; fixed in both the PHP and JavaScript matchers.
- Fixed: a banner cached under a previous site address kept requesting assets from the old origin (#195) - an address change now drops the cache, and a render-time repair rewrites and persists a stale origin, which also covers a restored database that never fires the hook.
- Fixed: the setup wizard's scan reported a fraction of the cookies the Cookies page found. The browser engine is now shared by both surfaces, retries public paths through the admin origin when home/admin hosts differ, and refuses to import misleading server-only findings when no page is observable. Wizard completion is atomic across banner/GCM/settings, preserves same-model customisations on re-entry, uses the site locale and jurisdiction-aligned geo defaults, and safely normalises false-like REST values.
- Fixed: a blocked Cookie Policy save now names the offending field, opens its section and focuses it, instead of doing nothing; background scans under a web SAPI run through WP-Cron with honest counts; third-country transfer labels resolve in the banner or policy language rather than the ambient request locale.
1.24.0
- Added: editable opt-out (Do Not Sell) modal text (#187) — a new "Opt-out (Do Not Sell) Text" card on the Cookie Banner > Preference Center tab edits the "Opt-out Preferences" popup's title, description and toggle label, per language, on CCPA / US State Laws (and Both) banners. Previously that copy was fixed to the bundled default. Translated into every bundled locale.
- Added: FlyingPress cache integration (#125) — saving a banner/cookie/category/setting purges FlyingPress's cached HTML; country-dependent pages bypass its cache via flying_press_is_cacheable; the consent scripts are excluded from its JS delay/defer/minify so the banner is never held back.
- Added: the Cookie Policy generator now flows through the WordPress gettext pipeline, so the policy honours the site locale and .mo overrides.
- Changed: payment-gateway scripts are now a per-gateway opt-in (Settings > Script Blocking > Payment gateways) instead of an automatic allow-list. A payment SDK can track, so it stays blocked until consent unless the store owner enables that gateway or it is strictly necessary on a real WooCommerce checkout/cart (the marketing pixel stays blocked either way). Migration: if you use Stripe elements outside a WooCommerce checkout, enable Stripe there after updating.
- Changed: the server-side cookie shredder moved to template_redirect (reliable checkout/cart conditionals), and an explicit per-service/per-cookie denial now wins over the admin cookie whitelist on both server and client.
- Fixed: category toggles rendering as editable text fields when another active plugin filters wp_kses_allowed_html (#188) — the allow-list no longer loses type="checkbox" regardless of filter order.
- Fixed: banner/cookie saves not sticking on sites with a persistent object cache (Redis Object Cache, Memcached) — internal cache invalidation now rotates the transient prefix instead of scanning wp_options (#125).
- Fixed: WPML, TranslatePress and Weglot banners showing only the default language under Cache Compatibility Mode — URL-keyed language negotiation (directory/domain) now resolves the per-URL language while staying cache-friendly.
- Fixed: the per-service consent toggle now appears for JS-injected embeds on block-first sites (#134/#146); the consent banner no longer double-initialises under Cloudflare Rocket Loader (#185); the icon-only notice dismiss link is now labelled for screen readers.
1.23.0
- Added: "Box (centered)" banner type - positions the consent box in the centre of the screen via CSS transform, a common pattern on European sites.
- Added: "Dim the page behind the banner" option - a semi-transparent overlay greys out the page to draw attention to the banner. The overlay is a visual cue only (pointer-events: none) and never blocks reading, scrolling, or clicking, so it does not act as a cookie wall. Available for Box corner, Box centered, and Full-width Banner types; automatically disabled for the Classic layout.
- Changed: geo-routing admin clarity - corrected the misleading "automatic per-country" copy (runtime rule-set application is off; the catalogue is preview/reference only, while per-country banner selection still works), exposed the runtime off-state in the geo status endpoint, and finished i18n of the Pipeline-status panel.
1.22.0
- Added: inline-CSS url()/@import blocking before consent — a Google Fonts @font-face src url() or @import in a tag previously reached the provider with consent denied; any url()/@import pointing at a blocked provider in a denied category is now neutralised (inert data: placeholder, restored on consent). Server-rendered and direct runtime HTMLStyleElement writes are covered by default; a new opt-in "Advanced inline CSS URL blocking" setting (default off) additionally hooks page-builder/CSS-in-JS channels (innerHTML/insertAdjacentHTML, CharacterData incl. nodeValue/replaceWith, replaceChildren/insertAdjacentText, Constructable Stylesheets/insertRule).
- Added: wider runtime resource blocking for /// (extends #163/#167) — beyond the src/href property setters, the setAttribute('src'|'href'|'srcset') path and the srcset property setter are gated, blocked src/srcset are parked, and the MutationObserver also parks parsed img/link/source.
- Added: Advanced Consent Mode for Google Consent Mode v2 (#165) — opt-in (default off); the Google tag stack (gtag.js/GA4/Ads) may load before consent with a synchronous denied consent default, while non-Google trackers and the GTM container stay blocked.
- Added: manual service registration from the built-in catalogue (#161) — register a known provider's cookies into the declaration table from the Cookies page without a scan.
- Fixed: map tiles, lazy-loaded embeds and runtime-injected stylesheets now blocked before consent (#163, #167). Leaflet/OpenStreetMap and Bricks Map tiles load as runtime , Bricks lazy-load swaps a URL into iframe.src, and Web Font Loader injects a Google Fonts at runtime — all bypassed the blocker. The src/href property setters are now gated on the image, iframe and link prototypes: a cross-origin resource matching a blocked provider in a denied category is parked until consent, then restored.
- Fixed: banner chrome (Always Active, cookie-table headers) now translates on non-English single-language sites (#164); European Portuguese banner content corrected (#159).
1.21.1
- Fix: on full-page-cached sites with Cache Compatibility Mode enabled, the cookie banner could fail to appear on the first visit (and trackers could run) because the rendered page still varied per visitor and one cached copy is shared between everyone — a search-engine or cache-warming crawler produced a banner-less copy, or a wrong-jurisdiction/wrong-language copy, that the cache then served to all visitors. Under Cache Compatibility Mode the render is now fully visitor-invariant: the banner script is always enqueued (no bot/geo skip), the IAB TCF gdprApplies signal is conservative, AMP banner selection is country-neutral, and the banner language no longer reads cookie/session state from TranslatePress, Weglot or WPML "No language in URLs" mode (URL-based Polylang/WPML stay correct; the visitor's real language is still corrected client-side). Reported on gooloo.de.
- Fix: the consent script-blocker no longer interferes with the WordPress 6.5+ Interactivity API (native type="module"/importmap scripts) or with optimiser-deferred scripts (LiteSpeed Cache / WP Rocket "Delay JS"), while still blocking trackers — including a tracker shipped as a module or restored in place by the optimiser.
1.21.0
- Feature: Cache Compatibility Mode (#158). A new Banner Control toggle keeps the page fully cacheable by LiteSpeed, QUIC.cloud, Varnish, Nginx FastCGI and WP Rocket. When enabled, the plugin stops emitting the no-cache/no-store/X-LiteSpeed-Cache-Control headers and the DONOTCACHEPAGE constant for anonymous visitors and renders a single visitor-invariant page — the default banner, with every non-necessary script blocked server-side and no per-country or per-consent variance — so the static HTML can be cached and the banner runs entirely client-side from the consent cookie. Off by default; keep it off when the banner output varies by country (IAB TCF, geo-targeting, country-targeted banners or runtime geo-routing), where a cached page would otherwise reach the wrong jurisdiction. Applied across the initial render, the AMP consent path and the REST banner endpoint.
- Fix: the bundled "Always Active", "Show more" and "Show less" default labels are now translatable while preserving any admin-customised text.
1.20.0
- Feature: per-cookie consent (#135). With per-service consent enabled, a new "Enable per-cookie consent" setting adds a nested row for each cookie a service declares. Cookies the site can write on its own domain are enforced on both sides — the client-side cleanup and the server-side template_redirect shredder both read the same ck.. tokens (per-cookie > per-service > category), so a denied first-party cookie is removed on every request. Cookies set by embedded third-party services on their own domains (for example YouTube, Vimeo, Maps and social embeds) cannot be deleted individually by a first-party banner; those rows are shown disabled with an explanation, and the enforceable control is allowing or blocking the whole embed. Payment-gateway cookies stay exempt only when that gateway is explicitly enabled or strictly necessary on the current WooCommerce checkout/cart request; admin-whitelisted cookies remain exempt from category fallback, while an explicit per-service/per-cookie denial still wins. Opt-in, off by default.
- Feature: per-service consent for blocked embeds on block-first sites (#134, #146). Per-service toggles now appear for embedded providers blocked before they can set a cookie, which the scanner never detected. The preference center is present-aware: a toggle is revealed for every provider the page actually blocks — server placeholders, JS-injected embeds caught by the runtime MutationObserver, lazy iframes and page-builder lightbox video links — without dumping the whole catalogue. A service the visitor explicitly accepted or rejected stays visible for withdrawal even on pages without its embed (GDPR Art. 7(3)). Added a fail-open banner watchdog so the banner still appears even if a JS/CSS-optimiser strips the inline reveal, plus a read-only fazcookie._diag() support snapshot.
- Fix: the Cookie Policy generator no longer lands on a blank admin.php page when its script does not run (the form refuses the native submit and shows a recoverable message). Server provider-URL matching now uses the same word-boundary check as the client, so notyoutube.com/embed is no longer treated as youtube.com/embed. Completed the provider catalogue (parity test added) and renamed openstreetmaps to openstreetmap. Accessibility: aria-describedby on disabled third-party cookie rows, aria-atomic on runtime-revealed service rows, theme-adaptive note colour, cursor:not-allowed on locked rows.
1.19.2
- Fix: the consent-log user-agent migration no longer errors on SQLite-backed WordPress (e.g. WordPress Playground). It previously used MySQL's SHA2()/REGEXP, which do not exist on SQLite, so the migration failed and emitted a database error on every request; it now runs in PHP with the identical hash.
- Fix: the Google Consent Mode non-personalized-ads
npa signal is now most-restrictive across regions. Because npa is a global signal that cannot be region-scoped, the pre-consent default emits a single value (non-personalized whenever any configured region denies ads) instead of letting the last-evaluated region win; the region-scoped Consent Mode v2 states are unaffected.
1.19.1
- Fix: legacy "Both" (GDPR + US) banners no longer silently lose their Do-Not-Sell opt-out. Very old banners stored it only in a legacy key that the settings sanitiser drops; the runtime now back-fills the opt-out from the raw stored settings so the US control still renders.
- Fix: the Google Consent Mode non-personalized-ads fallback now signals
npa on the FIRST visit too (legacy non-Consent-Mode ad tags previously only got it after a reject), and the signal is two-sided — it clears within the session once marketing is granted.
- Hardening: the consent-log
status column is constrained to the known set (unknown values fold to partial) so a crafted REST payload can't pollute the dashboard statistics; the client-side cookie cleanup gained a longer-tail pass to catch trackers that write a cookie well after page load; and an admin's explicit custom block rule is no longer silently exempted when it is a substring of an always-allowed payment-gateway pattern.
1.19.0
- Feature: per-service consent is reintroduced and now actually enforced. Granular per-service sub-toggles return under each category in the preference center (opt-in, sourced from the cookies actually detected on the site). A denied service is enforced server-side (pre-consent script block + cookie shredder) and client-side, an explicit allow overrides a denied category, and the choice persists across reloads and is written to the consent log. Enable it in Settings > Per-service consent. Extension filters:
faz_per_service_services, faz_store_data.
- Feature: Czech (cs_CZ) cookie-policy templates for the GDPR, CCPA and LGPD generators, with correct legal terminology and date grammar.
- Feature: opt-out success message for US state-law / CCPA "Do Not Sell or Share" — an accessible confirmation (
role="status" + aria-live, focus moved, countdown, auto-close) instead of a silent disappear. Headline/subtext editable via [faz_optout_success_text] / [faz_optout_success_subtext].
- Compliance: Quebec / Law 25 sub-national routing, Do-Not-Sell-My-Personal-Information enforcement, DSAR export/erase wiring, scanner TLS verify-by-default (loopback-exempt), and new geo rulesets (Minnesota, Maryland, New Hampshire, New Jersey, Texas, Canada / PIPEDA).
- Fix: changing the banner's applicable law now reloads the law-appropriate notice copy — a CCPA description could survive on a GDPR banner and tell visitors to click a Do-Not-Sell link no longer rendered — without overwriting a customised description.
- Fix: the "Do Not Sell or Share" link on a Classic-layout CCPA (or "Both") banner is no longer a dead click; such banners are migrated to a popup-capable layout in the editor and at runtime, with a re-show fallback.
- Fix: the banner template cache signature now includes the plugin version and the per-service / per-cookie flags, so a plugin update can no longer serve a stale cached template to the updated script.
- Fix: blocked-embed placeholder keeps its branded styling; a service-level placeholder accept records the choice; toggling a service no longer collapses its category accordion.
- Fix: the geo "source not configured" admin notice no longer fires when a GeoLite2 database (or
FAZ_MAXMIND_DB_PATH) is actually configured.
- Change: per-cookie consent remains hard-off pending its correctness rework, and is now also rejected on the settings REST / import path.
1.18.2
- Change: the experimental opt-in features added in 1.18.0 (per-service / per-cookie consent toggles and the
faz_geo_ruleset_runtime runtime geo-routing) are temporarily disabled pending a correctness rework — they did not, when enabled, deliver the granular guarantees their UI implied. They are now hard-off at their entry points. The default category-level consent flow (the path covered by the compliance suite) is byte-for-byte unchanged.
- Change: per-service / per-cookie toggles are hidden in Settings and forced off. As shipped a denied cookie was not enforced server-side or on reload, the granular decisions were not written to the consent log, a large override set could exceed the browser's ~4 KB cookie limit, and the list showed catalogue wildcards rather than detected cookies.
- Change: runtime geo-routing no longer applies a resolved ruleset to the live banner (a CCPA-style jurisdiction was mapped to a GDPR banner without rendering its Do-Not-Sell / GPC / sensitive-opt-in obligations). Catalogue-based multi-banner geo-routing — choosing which saved banner to show per country — is unaffected.
- Fix: corrected an overstated per-cookie help text that claimed a denied cookie "is deleted whenever it appears." That enforcement only ran client-side at save time and did not persist, so the claim was inaccurate.
1.18.1
- Fix: the Cookies admin "Scan Site" and "Auto-categorize" dropdown menus are no longer clipped by the card's rounded-corner overflow — the menu now drops over the table below and shows all options.
1.18.0
- Feature: geo-routing runtime (opt-in). With the
faz_geo_ruleset_runtime filter enabled, the resolved per-jurisdiction ruleset drives the live banner — pre-consent default state, script blocking, Google Consent Mode v2 defaults and banner selection follow the visitor's jurisdiction (GDPR, CCPA/CPRA, Quebec Law 25, POPIA, LGPD, …). Off by default: existing sites are unchanged until you enable the filter.
- Feature: GeoLite2 edition choice (Country vs City) under Settings > GeoIP Database. Country (~10 MB) stays the default; City (~60 MB) adds province/state detection needed by sub-national rules such as Quebec's Law 25. The UI explains the size/use trade-off, and the existing Country download keeps working exactly as before.
- Feature: granular per-cookie consent toggles (opt-in, requires per-service consent). A nested toggle for each cookie a service declares, so visitors can opt out of specific cookies within an accepted service. A denied cookie is deleted whenever it appears — the same enforcement used for per-service opt-out.
- Fix: GeoLite2 database activation is validated and atomic. A corrupt or wrong-edition download is rejected instead of silently breaking lookups; the previous database is preserved on error, and the edition preference is saved only after a successful download.
- Translations: all six bundled locales (Italian, French, German, Dutch, Croatian, Czech) completed and re-synced (1144 strings each).
- Hardening: per-cookie consent keys escape special characters so an exotic custom cookie name can't corrupt the consent cookie; runtime geo-routing custom saves honour the visitor's per-category toggles and fail closed when an opt-in ruleset has no matching banner; the GeoLite2 edition setting is whitelisted on save.
Older versions
Older releases (1.14.x and earlier) are listed in the full changelog on GitHub, linked at the top of this section.