FAZ Cookie Manager

Description

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

  1. Install and activate — the cookie banner appears immediately with sensible defaults
  2. Scan your site to detect cookies automatically
  3. Customize the banner design, text, and colors to match your brand
  4. Enable Google Consent Mode or IAB TCF if you use advertising tools
  5. 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 buildersfaz_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.

External Services

GitHub / Raw GitHubusercontent (Open Cookie Database)

Used to refresh the built-in cookie definitions snapshot for the optional auto-categorize feature.

Triggered when: you click the definitions update action in the Cookies screen.

Data sent: your server IP address and standard HTTP request headers.

Service URLs:
* https://raw.githubusercontent.com/fabiodalez-dev/Open-Cookie-Database/master/open-cookie-database.json

Terms of Service / Privacy Policy:
* https://docs.github.com/en/site-policy/github-terms/github-terms-of-service
* https://docs.github.com/en/site-policy/privacy-policies/github-privacy-statement

IAB Europe / vendor-list.consensu.org

Used to download the Global Vendor List and purpose translations for the optional IAB TCF feature.

Triggered when: you manually update the vendor list, and weekly while IAB TCF is enabled.

Data sent: your server IP address and standard HTTP request headers.

Service URLs:
* https://vendor-list.consensu.org/v3/vendor-list.json
* https://vendor-list.consensu.org/v3/purposes-en.json

Privacy Policy:
* https://iabeurope.eu/privacy-policy/

MaxMind

Used to download a GeoLite2 database for optional geo-targeting. You choose the edition in Settings GeoIP Database: the smaller Country edition (default, country-level only) or the larger City edition (adds region/subdivision data for sub-national province/state routing such as Quebec Law 25). City is a much larger download; pick it only if you rely on region-level routing.

Triggered when: you enter a MaxMind license key in Settings and start the database download.

Data sent: your server IP address, the license key you provide, and standard HTTP request headers.

Service URL:
* https://download.maxmind.com/app/geoip_download

Terms of Service / Privacy Policy:
* https://www.maxmind.com/en/terms-of-use
* https://www.maxmind.com/en/privacy-policy

ip-api.com

Used as a fallback geolocation lookup for the optional geo-targeting and multi-banner geo-routing features, only when MaxMind is unavailable.

Triggered when: a frontend page renders the banner while geo-targeting / multi-banner geo-routing is enabled AND neither the Cloudflare CF-IPCountry header (opt-in) nor the MaxMind GeoLite2 database produces a result. The visitor’s IP is sent to ip-api.com for country resolution; the resolved country code is cached in a transient (hash-keyed by IP) for one hour to avoid repeating the lookup.

Data sent: the visitor’s IP address and standard HTTP request headers.

Service URL:
* http://ip-api.com/json/{ip}?fields=countryCode

Terms of Service / Privacy Policy:
* https://ip-api.com/docs/legal

ipinfo.io (geo-routing v2 only)

Used for VPN/proxy/Tor detection when the admin opts in to enhanced geo detection via Settings Geo-routing ipinfo settings. The plugin sends the visitor IP to ipinfo.io to determine whether the visitor is masking their location; when VPN is detected, the most-protective rule-set is applied regardless of the visitor’s apparent country.

Triggered when: a frontend page renders the banner AND the admin has configured an ipinfo API key AND has explicitly attested to having a DPF / SCC / DPA agreement with ipinfo.io for cross-border data transfer of EU/UK visitor IPs. Without the admin opt-in, ipinfo is NEVER called.

Data sent: the visitor’s IP address (in cleartext, as required by ipinfo’s lookup contract), the configured API key, and standard HTTP request headers. The plugin caches the VPN classification locally for 24 hours hash-keyed by the IP (with monthly salt rotation) so repeat visitors do not trigger fresh calls.

Service URL:
* https://ipinfo.io/{ip}/privacy

Terms of Service / Privacy Policy:
* https://ipinfo.io/terms-of-service
* https://ipinfo.io/privacy-policy
* DPA (Data Processing Agreement) available on request: https://ipinfo.io/contact

Plugin REST endpoint /faz/v1/banner (public)

Used by the plugin’s own front-end JavaScript (script.js) to fetch the per-language / per-country banner payload after the page has loaded. This is an INTERNAL endpoint hosted by the plugin on the same WordPress install — no third-party network call leaves the visitor’s browser to a remote service. It is documented here only because the response carries bannerSlug and activeLaw, two strings that describe which banner profile and which legal regime (gdpr / ccpa) currently applies to the visitor.

Triggered when: the front-end banner script bootstraps on a page that has multi-banner geo-routing active.

Data sent: only what the visitor’s browser already sends with any page request to the same origin. The plugin does not forward the request to any remote service.

Service URL:
* …

Screenshots

Blocks

This plugin provides 3 blocks.

  • Cookie Table
  • Cookie Policy
  • Manage Cookies Button

Installation

From the WordPress.org plugin directory (recommended)

  1. In your WordPress dashboard go to Plugins > Add New Plugin
  2. Search for FAZ Cookie Manager
  3. Click Install Now, then Activate
  4. Go to FAZ Cookie in the admin sidebar to configure your banner

Manual installation

  1. Download the ZIP from wordpress.org/plugins/faz-cookie-manager
  2. In your WordPress dashboard go to Plugins > Add New Plugin > Upload Plugin
  3. Upload the ZIP and click Install Now, then Activate
  4. Go to FAZ Cookie in the admin sidebar to configure your banner

FAQ

Does this plugin require a cloud account or subscription?

No required cloud account or subscription is needed. Core consent features run locally, while some optional refresh/download features can contact documented third-party services such as GitHub, IAB Europe, MaxMind, or AMP infrastructure.

Is it really free? What’s the catch?

It’s free and open source (GPL-3.0). There are no premium upgrades, no feature gates, and no upsells. The plugin is based on the GPL-licensed CookieYes v3.4.0 codebase, with cloud dependencies removed and all included features running locally.

Is it compatible with Google Consent Mode v2?

Yes. The plugin sends all 7 consent signals (ad_storage, analytics_storage, ad_user_data, ad_personalization, functionality_storage, personalization_storage, security_storage) and supports Google Additional Consent Mode (GACM) for ad technology providers.

Does the banner block cookies before consent?

Yes. Any script tagged with data-faz-tag="category-name" is blocked until the visitor grants consent for that category. This helps you implement consent-based blocking for ePrivacy/GDPR workflows.

How does the cookie scanner work?

Go to FAZ Cookie > Cookies and click Scan Site. The scanner runs in your browser using iframes, crawling your site’s pages to detect all cookies. Choose from quick scan (10 pages), standard (100), deep (1000), or full scan. No external service involved.

Can I log consent for GDPR accountability?

Yes. Every consent action (accept, reject, customize) is recorded in a local database table with timestamp, consent ID, categories chosen, anonymized IP, and page URL. Export to CSV anytime from the Consent Logs page.

Does it support multiple languages?

Yes. The Languages page lets you select from 180+ available languages. Each banner you create carries its own translations for every language you enable — the banner text (title, description, button labels) is stored per-language inside the banner row, and the language displayed to the visitor is resolved client-side from navigator.languages. WPML / Polylang URL-based language switching is auto-detected and always cache-safe.

Does multi-banner mean one banner per language?

No — multi-banner routing is per visitor country (e.g. GDPR vs CCPA, EU vs US), not per language. Each banner row carries its OWN multilingual content: title, description and button labels translated for every language you support. The visitor’s country selects the banner; the visitor’s browser language then selects which translated strings to render inside that banner. So an install with one EU-targeted GDPR banner (carrying English + Italian + German + French translations) and one US-targeted CCPA banner (carrying English + Spanish translations) needs only TWO banner rows, not eight. See the “Multi-banner geo-routing vs multilingual content” section in the Description for the full architecture.

Can users change their consent after accepting?

Yes. A floating revisit widget appears on every page, letting visitors reopen the preference center and change their choices at any time.

Is the banner accessible?

Yes. The banner supports full keyboard navigation (Tab, Enter, Escape), proper ARIA labels, and is responsive down to 375px viewports. Buttons have equal visual prominence to avoid dark patterns.

Does it work with caching plugins?

Yes. The consent banner is rendered via JavaScript from a cached template, so it works with all major caching plugins (WP Super Cache, W3 Total Cache, LiteSpeed Cache, etc.).

Does the plugin send any data home or collect telemetry?

No. The plugin contains no telemetry, no analytics beacon, and no “phone home”. Dashboard numbers are computed locally from your own wp_faz_pageviews and wp_faz_consent_logs tables. Every outbound request that can happen is documented in the “External services” section and is gated behind an explicit admin action.

Where is the source of the bundled minified JavaScript?

The minified files we ship are frontend/js/script.min.js, frontend/js/gcm.min.js, frontend/js/tcf-cmp.min.js and frontend/js/a11y.min.js. The full, unminified sources live next to each one as script.js, gcm.js, tcf-cmp.js and a11y.js, and the build command npm run build:min rebuilds them all with terser. No obfuscation is used.

Does uninstalling the plugin remove my data?

By default, no — your consent logs, banner configuration and categories stay in the database so you can reinstall without losing work. To wipe everything on uninstall, enable Settings General Remove all data on uninstall or define FAZ_REMOVE_ALL_DATA as true in wp-config.php before deleting the plugin.

Does the plugin include a CCPA “Do Not Sell” opt-out form?

Yes. Place [faz_do_not_sell] on any page (e.g. your Privacy Policy) to show a California Consumer Privacy Act opt-out form. When a visitor submits the form, the opt-out is logged in the local consent table with a hashed IP address, a long-lived cookie is set so the visitor sees a confirmation on subsequent visits, and the site admin receives a notification email. Optional attributes: title (heading text) and button (submit label). No external service is involved.

Does the plugin include a GDPR Data Subject Access Request (DSAR) form?

Yes. Place [faz_dsar_form] on any page to show a GDPR-compliant request form covering six rights: Access (Art. 15), Erasure (Art. 17), Data Portability (Art. 20), Rectification (Art. 16), Restriction (Art. 18), and the Right to Object (Art. 21). On submission, the request is stored as a private post in the WordPress database (so it survives email failures), a notification is sent to the admin with a direct link to the record, and a confirmation is sent to the requester. The form includes a honeypot field and nonce verification to block spam bots. Optional attributes: button (submit label).

Reviews

July 23, 2026 1 reply
I’m testing this plugin and first impressions is that it has almost everything you need without having to upgrade.Would be great if the policy wording could be customised especially if you are not in the legal regions that it covers, e.g. South Africa.The default wording is a great starting point. The banner is customisable, there over 700 custom rules available.
July 21, 2026
Despite being relatively new, it is very promising, open source and free. It is the only free solution (i found) that includes Consent Logs, Google Consent Mode v2 and an Automatic cookie scanner. The developer is very responsive—after I reported an issue, they released a bug fix within just a few days. Keep the good job!!
July 17, 2026
I tried it, and it’s absolutely comprehensive, fully functional, and free. Finally, you can avoid those basic GDPR plugins that annoyingly advertise paid features…
July 16, 2026 1 reply
Just discovered this plugin. Very promising. Side note: How can we keep you working on this project, Fabio?
Read all 21 reviews

Contributors & Developers

“FAZ Cookie Manager” is open source software. The following people have contributed to this plugin.

Contributors

Translate “FAZ Cookie Manager” into your language.

Interested in development?

Browse the code, check out the SVN repository, or subscribe to the development log by RSS.

Changelog

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 /

<

iframe>// (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.