{"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-26T11:57:00","modified_gmt":"2026-06-26T11:57:00","slug":"plain-cookie-consent","status":"publish","type":"plugin","link":"https:\/\/en-nz.wordpress.org\/plugins\/plain-cookie-consent\/","author":8052959,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.7.0","stable_tag":"0.7.0","tested":"7.0","requires":"6.0","requires_php":"7.4","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-26 11:57:00","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":87,"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-20 09:14:12"},"0.7.0":{"tag":"0.7.0","author":"ontario777","date":"2026-06-26 11:57:00"}},"upgrade_notice":{"0.7.0":"<p>Uninstall now keeps the consent log and settings by default; opt into permanent deletion via Settings \u2192 Data on uninstall. Full admin i18n. No breaking changes.<\/p>","0.6.3":"<p>Bugfix + performance update. No breaking changes; stored consent hashes for ordinary User-Agents are unchanged.<\/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","0.7.0"],"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. Uninstalling keeps the consent log and settings by default (GDPR Art. 7.1 evidence), with an explicit opt-in to permanently delete via Settings \u2192 Data on uninstall.<\/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%20uninstalling%20the%20plugin%20delete%20its%20data%3F\"><h3>Does uninstalling the plugin delete its data?<\/h3><\/dt>\n<dd><p>No \u2014 not by default. The consent audit log and all plugin settings are <strong>preserved<\/strong> when you uninstall (GDPR Art. 7.1 evidence; a reinstall finds prior records and configuration intact). To permanently delete all data, go to Settings \u2192 Plain Cookie Consent \u2192 Data on uninstall, switch to delete mode (type <code>DELETE<\/code> to confirm), and then proceed with the WordPress uninstall. The rotating subject salt is always removed in both modes. Exporting the log first (CSV or JSON) is recommended for portable evidence before any permanent deletion.<\/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.7.0<\/h4>\n\n<ul>\n<li>New: uninstall now keeps the consent audit log and all plugin settings by default (GDPR Art. 7.1 evidence); a reinstall finds prior records and configuration intact. Opt into permanent deletion via Settings \u2192 Data on uninstall (typed DELETE confirmation required).<\/li>\n<li>New: full admin-UI internationalization \u2014 all admin strings are now translatable.<\/li>\n<li>Changed: minimum PHP lowered back to 7.4 (from 8.0); the code is verified 7.4-safe, widening host compatibility.<\/li>\n<\/ul>\n\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>","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:\/\/en-nz.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/325830","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/en-nz.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/en-nz.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/en-nz.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=325830"}],"author":[{"embeddable":true,"href":"https:\/\/en-nz.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/ontario777"}],"wp:attachment":[{"href":"https:\/\/en-nz.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=325830"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/en-nz.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=325830"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/en-nz.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=325830"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/en-nz.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=325830"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/en-nz.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=325830"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/en-nz.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=325830"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}