{"id":325830,"date":"2026-06-16T13:51:44","date_gmt":"2026-06-16T13:51:44","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/plain-cookie-consent\/"},"modified":"2026-06-16T14:00:40","modified_gmt":"2026-06-16T14:00:40","slug":"plain-cookie-consent","status":"publish","type":"plugin","link":"https:\/\/km.wordpress.org\/plugins\/plain-cookie-consent\/","author":8052959,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.6.3","stable_tag":"0.6.3","tested":"7.0","requires":"6.0","requires_php":"8.0","requires_plugins":null,"header_name":"Plain Cookie Consent","header_author":"Ontario7","header_description":"Minimal clean-room GDPR\/ePrivacy consent banner with Google Consent Mode v2 defaults, early inline replay, and no upsells or tracking.","assets_banners_color":"1d2327","last_updated":"2026-06-16 14:00:40","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/plain-cookie-consent.com\/","header_author_uri":"","rating":0,"author_block_rating":0,"active_installs":0,"downloads":33,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"0.6.3":{"tag":"0.6.3","author":"ontario777","date":"2026-06-16 14:00:40"}},"upgrade_notice":{"0.6.3":"<p>Bugfix + performance update. No breaking changes; stored consent hashes for ordinary User-Agents are unchanged.<\/p>","0.6.2":"<p>Maintenance and documentation update. No breaking changes.<\/p>","0.6.0":"<p>New features only \u2014 no breaking changes. <code>ConsentLog<\/code> \/ <code>ConsentMirror<\/code> moved to the Core namespace with backwards-compatible aliases kept; migrate custom extensions to the <code>Core\\<\/code> namespace at your convenience.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3574584,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3574584,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3574584,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3574584,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["0.6.3"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3574584,"resolution":"1","location":"assets","locale":"","width":1280,"height":720},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3574584,"resolution":"2","location":"assets","locale":"","width":1280,"height":720},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3574584,"resolution":"3","location":"assets","locale":"","width":1280,"height":720},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3574584,"resolution":"4","location":"assets","locale":"","width":1280,"height":720},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3574584,"resolution":"5","location":"assets","locale":"","width":1280,"height":720}},"screenshots":{"1":"Consent banner \u2014 first layer.","2":"Cookie preferences modal \u2014 equal-weight Accept \/ Reject.","3":"Settings page \u2014 Privacy Policy URL, consent revision, policy version, controller name.","4":"Diagnostics panel \u2014 checks including policy-version drift, Google Fonts, and reCAPTCHA presence.","5":"Consent Health dashboard widget."}},"plugin_section":[262246],"plugin_tags":[223629,16626,131786,131785,396],"plugin_category":[54],"plugin_contributors":[267362],"plugin_business_model":[],"class_list":["post-325830","plugin","type-plugin","status-publish","hentry","plugin_section-dashboard-widgets","plugin_tags-consent-mode","plugin_tags-cookie-consent","plugin_tags-eprivacy","plugin_tags-gdpr","plugin_tags-privacy","plugin_category-security-and-spam-protection","plugin_contributors-ontario777","plugin_committers-ontario777"],"banners":{"banner":"https:\/\/ps.w.org\/plain-cookie-consent\/assets\/banner-772x250.png?rev=3574584","banner_2x":"https:\/\/ps.w.org\/plain-cookie-consent\/assets\/banner-1544x500.png?rev=3574584","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/plain-cookie-consent\/assets\/icon-128x128.png?rev=3574584","icon_2x":"https:\/\/ps.w.org\/plain-cookie-consent\/assets\/icon-256x256.png?rev=3574584","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/plain-cookie-consent\/assets\/screenshot-1.png?rev=3574584","caption":"Consent banner \u2014 first layer."},{"src":"https:\/\/ps.w.org\/plain-cookie-consent\/assets\/screenshot-2.png?rev=3574584","caption":"Cookie preferences modal \u2014 equal-weight Accept \/ Reject."},{"src":"https:\/\/ps.w.org\/plain-cookie-consent\/assets\/screenshot-3.png?rev=3574584","caption":"Settings page \u2014 Privacy Policy URL, consent revision, policy version, controller name."},{"src":"https:\/\/ps.w.org\/plain-cookie-consent\/assets\/screenshot-4.png?rev=3574584","caption":"Diagnostics panel \u2014 checks including policy-version drift, Google Fonts, and reCAPTCHA presence."},{"src":"https:\/\/ps.w.org\/plain-cookie-consent\/assets\/screenshot-5.png?rev=3574584","caption":"Consent Health dashboard widget."}],"raw_content":"<!--section=description-->\n<p>Plain Cookie Consent is a no-frills GDPR + ePrivacy consent banner for WordPress. It ships a single banner, Google Consent Mode v2 defaults, a server-side audit log with pseudonymised subject hashing, a DSAR lookup helper, and constant-gated Meta Pixel \/ Microsoft Clarity \/ LinkedIn Insight Tag helpers \u2014 all under GPL v2, with no upsells and no external telemetry.<\/p>\n\n<p>The plugin is designed to support a GDPR\/ePrivacy-compliant consent setup. Final compliance depends on the site owner's configuration and linked privacy policy.<\/p>\n\n<h4>Core compliance features<\/h4>\n\n<ul>\n<li>Google Consent Mode v2 defaults injected at <code>wp_head<\/code> priority 1, before any tag manager or gtag snippet.<\/li>\n<li>Early inline consent replay with a revision gate \u2014 consent recorded before a policy revision bump is not replayed; the banner re-prompts instead.<\/li>\n<li>Server-side audit log (<code>wp_plain_consent_log<\/code>) with a privacy-preserving SHA-256 subject hash over a daily-rotating salt, and a 730-day default retention purge (filterable via constant).<\/li>\n<li>Consent revision system with a \"Force re-consent for all users now\" admin action and strict rollback if the audit insert fails.<\/li>\n<li>Two-step choice pattern: the first layer offers Accept All and Show Options; the preferences screen (one click away) offers equal-weight Accept All, Reject All, and Save Preferences buttons.<\/li>\n<li>Server-mirror consent cookie via a cache-safe <code>GET \/mirror-nonce<\/code> endpoint (<code>Cache-Control: no-store<\/code>), so full-page caching does not break nonce validation.<\/li>\n<li>Geo targeting: the consent-required region set is the EEA (EU-27 plus Iceland, Liechtenstein, Norway) plus the United Kingdom. Detection uses the Cloudflare <code>CF-IPCountry<\/code> header when present, with a fail-safe default: if the country cannot be determined, the visitor is treated as in-scope.<\/li>\n<li>CSV\/JSON streamed export of the consent log, plus a pre-uninstall evidence warning with one-click export.<\/li>\n<li>DSAR lookup admin tool: recompute a visitor's subject hash from IP + User-Agent and list matching consent-log entries (GDPR Art. 15 support).<\/li>\n<\/ul>\n\n<h4>Integrations<\/h4>\n\n<ul>\n<li>Meta Pixel: define <code>PLAIN_COOKIE_CONSENT_FACEBOOK_PIXEL_ID<\/code> in <code>wp-config.php<\/code>.<\/li>\n<li>Microsoft Clarity: define <code>PLAIN_COOKIE_CONSENT_CLARITY_PROJECT_ID<\/code> in <code>wp-config.php<\/code>.<\/li>\n<li>LinkedIn Insight Tag: define <code>PLAIN_COOKIE_CONSENT_LINKEDIN_PARTNER_ID<\/code> in <code>wp-config.php<\/code>.<\/li>\n<li>Public <code>window.plainCookieConsent<\/code> JavaScript API (<code>getCategories<\/code>, <code>hasConsent<\/code>, <code>onChange<\/code>, <code>onGrant<\/code>, <code>onRevoke<\/code>) for site-specific vendors.<\/li>\n<li>Cookie cleanup on revoke with curated defaults for LinkedIn, TikTok, Hotjar, Clarity, Yandex Metrica, and Snapchat (<code>plain_cookie_consent_autoclear_cookies<\/code> filter).<\/li>\n<li><code>localStorage<\/code> \/ <code>sessionStorage<\/code> cleanup on a real granted-to-revoked transition (<code>plain_cookie_consent_clear_storage_keys<\/code> filter).<\/li>\n<\/ul>\n\n<h4>Accessibility<\/h4>\n\n<ul>\n<li>The banner and preferences modal are attested against WCAG 2.1 AA.<\/li>\n<li>axe-core smoke tests (<code>wcag2a<\/code>, <code>wcag2aa<\/code>, <code>wcag21aa<\/code> tags) run on every push and pull request via GitHub Actions.<\/li>\n<li>Site-level accessibility remains the operator's responsibility.<\/li>\n<\/ul>\n\n<h4>Languages<\/h4>\n\n<p>Translation catalogs ship for nine languages: English, German, Russian, Spanish, French, Italian, Dutch, Polish, and Portuguese. Banner language auto-resolution covers all nine shipped languages, including regional variants (for example de-AT or pt-BR), with any other locale falling back to English. Any shipped catalog can also be selected explicitly, and translators can override strings the standard WordPress gettext way.<\/p>\n\n<h4>Not included<\/h4>\n\n<ul>\n<li>TCF v2.2 (programmatic publishers).<\/li>\n<li>Consent analytics dashboards beyond the read-only Consent Health widget.<\/li>\n<li>Multi-domain consent sync.<\/li>\n<li>Banner A\/B testing.<\/li>\n<li>Script auto-blocking beyond Consent Mode and the documented vendor helpers.<\/li>\n<\/ul>\n\n<h3>External services<\/h3>\n\n<p>This plugin has no telemetry and never sends data to its own or the author's servers. Consent records stay in your own WordPress database.<\/p>\n\n<p>The plugin can optionally load three well-known third-party marketing\/analytics tags <strong>on your behalf<\/strong>. Each one is OFF by default and only ever loads when BOTH of the following are true:<\/p>\n\n<ol>\n<li>You explicitly enable it by defining the matching constant in <code>wp-config.php<\/code>, and<\/li>\n<li>The visitor grants the relevant consent category in the banner.<\/li>\n<\/ol>\n\n<p>If you do not define these constants, the plugin makes no third-party requests at all. Once enabled, the tag still loads only after the visitor grants the relevant consent category in the banner.<\/p>\n\n<h4>Meta (Facebook) Pixel<\/h4>\n\n<p>Optional advertising measurement. Enabled by defining <code>PLAIN_COOKIE_CONSENT_FACEBOOK_PIXEL_ID<\/code>. When a visitor grants <strong>advertising<\/strong> consent, the plugin loads <code>https:\/\/connect.facebook.net\/en_US\/fbevents.js<\/code> and initialises the Pixel with your Pixel ID. From then on, on each page view, Meta receives standard Pixel data: your Pixel ID, the page URL and referrer, the visitor's IP address and browser\/user-agent, and a PageView event. Nothing is sent before advertising consent.\nProvider: Meta Platforms, Inc. Privacy Policy: https:\/\/www.facebook.com\/privacy\/policy\/ \u2014 Business Tools Terms: https:\/\/www.facebook.com\/legal\/terms\/businesstools<\/p>\n\n<h4>Microsoft Clarity<\/h4>\n\n<p>Optional session analytics (heatmaps and session insights). Enabled by defining <code>PLAIN_COOKIE_CONSENT_CLARITY_PROJECT_ID<\/code>. When a visitor grants <strong>analytics<\/strong> consent, the plugin loads <code>https:\/\/www.clarity.ms\/tag\/&lt;your-project-id&gt;<\/code>. From then on, on each page view, Microsoft receives Clarity analytics data: your project ID, the page URL, the visitor's IP address and browser\/user-agent, and interaction events such as clicks and scrolls. Nothing is sent before analytics consent.\nProvider: Microsoft Corporation. Privacy Statement: https:\/\/www.microsoft.com\/privacy\/privacystatement \u2014 Clarity Terms of Service: https:\/\/clarity.microsoft.com\/terms<\/p>\n\n<h4>LinkedIn Insight Tag<\/h4>\n\n<p>Optional advertising measurement on LinkedIn. Enabled by defining <code>PLAIN_COOKIE_CONSENT_LINKEDIN_PARTNER_ID<\/code>. When a visitor grants <strong>advertising<\/strong> consent, the plugin loads <code>https:\/\/snap.licdn.com\/li.lms-analytics\/insight.min.js<\/code> with your Partner ID. From then on, on each page view, LinkedIn receives Insight Tag data: your Partner ID, the page URL, and the visitor's IP address and browser\/user-agent. Nothing is sent before advertising consent.\nProvider: LinkedIn Corporation. Privacy Policy: https:\/\/www.linkedin.com\/legal\/privacy-policy \u2014 LinkedIn Ads Agreement: https:\/\/www.linkedin.com\/legal\/ads-agreement<\/p>\n\n<h3>Disclaimer<\/h3>\n\n<p>This plugin is provided \"as is\", free of charge, for evaluation and use at\nthe site operator's own discretion and risk.<\/p>\n\n<ul>\n<li>The site operator alone chooses which plugins to install and run on their\nsite, and bears full responsibility for that choice and its consequences.<\/li>\n<li>The plugin is offered for informational and evaluation purposes. The\nauthors make no guarantees and no promises of any kind \u2014 including\ncorrectness, completeness, fitness for a particular purpose, or\nuninterrupted operation.<\/li>\n<li>Software may contain errors. Any errors, malfunctions, data loss, or\nlegal consequences arising from the use of this plugin are the sole\nresponsibility of the site operator.<\/li>\n<li>Nothing in this plugin or its documentation constitutes legal advice.\nThe plugin is designed to support a GDPR\/ePrivacy-oriented consent setup,\nbut it does not and cannot guarantee legal compliance of any specific\nsite \u2014 final compliance always depends on the operator's configuration,\nvendors, and policies.<\/li>\n<li>The warranty disclaimer and limitation of liability are governed by\nsections 11 and 12 of the GNU GPL v2 license that ships with this plugin.<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>plain-cookie-consent<\/code> folder to <code>\/wp-content\/plugins\/<\/code>.<\/li>\n<li>Activate the plugin via the Plugins menu.<\/li>\n<li>Visit Settings \u2192 Plain Cookie Consent to configure the Privacy Policy URL, policy version, and optional data-controller name.<\/li>\n<li>For Meta Pixel \/ Microsoft Clarity \/ LinkedIn Insight: define the relevant constant in <code>wp-config.php<\/code>.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"is%20recaptcha%20covered%3F\"><h3>Is reCAPTCHA covered?<\/h3><\/dt>\n<dd><p>The plugin does not auto-gate reCAPTCHA, because its legal basis is context-dependent: on contact forms it generally requires consent, while as payment anti-fraud it may be consent-exempt. The Diagnostics \"reCAPTCHA \/ security CAPTCHA\" probe flags its presence so you can decide. The bundled docs\/INTEGRATION.md documents gating patterns.<\/p><\/dd>\n<dt id=\"is%20switzerland%20covered%3F\"><h3>Is Switzerland covered?<\/h3><\/dt>\n<dd><p>No. Switzerland (CH) is deliberately excluded from the consent-required region set. The Swiss revFADP has no prior-consent rule for cookies equivalent to ePrivacy Art. 5(3), so Swiss traffic falls under the rest-of-world (granted-by-default) branch. The in-scope set is the EEA (EU-27 + Iceland, Liechtenstein, Norway) plus the United Kingdom.<\/p><\/dd>\n<dt id=\"does%20the%20plugin%20collect%20any%20data%20itself%3F\"><h3>Does the plugin collect any data itself?<\/h3><\/dt>\n<dd><p>No. There is no external telemetry. Consent records stay in your own WordPress database, with the subject identifier stored only as a salted SHA-256 hash.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>0.6.3<\/h4>\n\n<ul>\n<li>Fixed: DSAR lookups now reliably match visitors whose User-Agent contains escaped characters or stray whitespace \u2014 the recording and lookup paths now canonicalise the User-Agent identically. Hashes for ordinary User-Agents are unchanged.<\/li>\n<li>Performance: the Consent Health dashboard widget caches its 7-day counts for a few minutes instead of querying the audit log on every admin page load.<\/li>\n<li>Internal hardening and cleanup (input unslashing, prefixed uninstall globals).<\/li>\n<\/ul>\n\n<h4>0.6.2<\/h4>\n\n<ul>\n<li>Banner language now auto-resolves across all nine shipped locales, including regional variants (for example de-AT or pt-BR), with English fallback.<\/li>\n<li>Localized the optional data-controller banner label.<\/li>\n<li>Documented the optional Meta Pixel \/ Microsoft Clarity \/ LinkedIn Insight Tag integrations under a new \"External services\" section.<\/li>\n<li>Housekeeping: admin notice\/menu scripts and styles are now enqueued; the Consent Mode defaults use the standard inline-script API; removed a redundant translation-loading call.<\/li>\n<\/ul>\n\n<h4>0.6.1<\/h4>\n\n<ul>\n<li>Added an explicit Disclaimer section (no warranties, operator responsibility, not legal advice).<\/li>\n<\/ul>\n\n<h4>0.6.0<\/h4>\n\n<ul>\n<li>localStorage \/ sessionStorage cleanup on consent revoke (transition-only, filterable allowlist).<\/li>\n<li>DSAR lookup admin tool (GDPR Art. 15 support).<\/li>\n<li>Microsoft Clarity helper (constant-gated, analytics consent).<\/li>\n<li>LinkedIn Insight Tag helper (constant-gated, advertising consent).<\/li>\n<li>New Diagnostics probes: reCAPTCHA presence, Google Fonts remote loading, policy-version drift.<\/li>\n<li>Optional data-controller identity line in the banner.<\/li>\n<li>gettext i18n migration with shipped catalogs for 9 languages (en, de, ru, es, fr, it, nl, pl, pt).<\/li>\n<li>Optional floating \"Cookie Settings\" reopen icon (off by default).<\/li>\n<li>Consent Health dashboard widget (read-only, local data only).<\/li>\n<li>WCAG 2.1 AA attestation backed by axe-core CI smoke tests.<\/li>\n<li>Core namespace extraction (<code>ConsentLog<\/code>, <code>ConsentMirror<\/code>) with documented public hooks and backwards-compatible class aliases.<\/li>\n<li>New INTEGRATION.md covering WooCommerce, Stripe, reCAPTCHA, AMP, and page-cache rules.<\/li>\n<\/ul>\n\n<h4>0.5.2<\/h4>\n\n<ul>\n<li>Raised the minimum supported PHP to 8.0.<\/li>\n<li>Documentation clarifications (compliance posture, Switzerland geo stance).<\/li>\n<\/ul>\n\n<h4>0.5.1<\/h4>\n\n<ul>\n<li>Documentation hotfix after the 0.5.0 release audit.<\/li>\n<\/ul>\n\n<h4>0.5.0<\/h4>\n\n<ul>\n<li>Public <code>window.plainCookieConsent<\/code> JavaScript API.<\/li>\n<li>Expanded cookie auto-clear filter for LinkedIn \/ TikTok \/ Hotjar \/ Clarity \/ Yandex Metrica \/ Snapchat.<\/li>\n<li>CSV\/JSON audit-log export and pre-uninstall evidence warning.<\/li>\n<li>Optional YouTube <code>youtube-nocookie.com<\/code> oEmbed rewrite.<\/li>\n<li>Rate limit on the <code>\/mirror<\/code> REST endpoint.<\/li>\n<\/ul>\n\n<h4>0.4.0<\/h4>\n\n<ul>\n<li>Server-mirror consent cookie, audit log, revision system, and policy version.<\/li>\n<li>Cache-safe <code>\/mirror-nonce<\/code> endpoint.<\/li>\n<li>Versioned boot-time migrator and multisite-correct activation\/deactivation.<\/li>\n<li>Early-replay revision gate.<\/li>\n<\/ul>","raw_excerpt":"Minimal clean-room GDPR\/ePrivacy consent banner with Google Consent Mode v2, early inline replay, DSAR helper, and no upsells.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/km.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/325830","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/km.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/km.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/km.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=325830"}],"author":[{"embeddable":true,"href":"https:\/\/km.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/ontario777"}],"wp:attachment":[{"href":"https:\/\/km.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=325830"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/km.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=325830"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/km.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=325830"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/km.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=325830"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/km.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=325830"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/km.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=325830"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}