WP Manifestindependent plugin directory
manifest / privacy / core-privacy-consent-manager

Core Privacy Consent Manager

Lightweight opt-out cookie consent banner for WordPress: Google Consent Mode v2 + Meta Pixel, GPC honoring, [cookie_preferences] shortcode.

by olegtymo · github.com/olegtymo/core-privacy-consent-manager

0stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/olegtymo/core-privacy-consent-manager/archive/refs/heads/main.zip

Readme

Core Privacy Consent Manager

A lightweight, reusable opt-out cookie consent banner for our WordPress sites. It stores the visitor's choice, blocks non-essential tracking after opt-out, signals Google Consent Mode v2 and Meta Pixel, and exposes a [cookie_preferences] shortcode so visitors can change their mind.

Legal model: opt-out (US, non-CA contractor sites). Tracking loads by default and stops after a visitor opts out. This is not GDPR opt-in.


1. Install & configure

  1. Activate Core Privacy Consent Manager.
  2. Go to Settings → Cookie Consent and fill in:
    • Notice text, button labels, Privacy Policy URL.
    • Colors.
    • Emit Google Consent Mode v2 signals (leave on if you use GA4 / Google Ads / GTM).
    • Remember choice for (days) — default 365.
    • Consent version — bump this number to re-prompt every visitor (e.g. after a policy change).

That's the whole setup for a new site — no code edits required.


2. How script gating works (hybrid model)

Service Mechanism What you do
GA4 / Google Ads / GTM Consent Mode v2 signals (ad_storage, analytics_storage, ad_user_data, ad_personalization) Nothing — the plugin emits gtag('consent', ...) automatically. Keep your GTM/GA snippet in WP Code as-is.
Meta Pixel fbq('consent', 'grant'|'revoke') Add the one-line guard below to your Pixel snippet.
Other pixels / non-Google scripts JS guard window.CPCM.allows() Wrap the snippet body in the guard below.

The plugin prints the Consent Mode default state at the very top of <head> (before your GTM/GA snippet), so Google tags respect consent even though they still load. For visitors who already opted out, it immediately sends an update → denied. It also sets url_passthrough and ads_data_redaction so Google Ads keeps measuring conversions when storage is denied.

Global Privacy Control (GPC): if a visitor's browser sends a GPC signal (navigator.globalPrivacyControl) and they have no explicit choice yet, the plugin honors it as an opt-out — CPCM.allows() returns false and a denied update is sent. Under CCPA/CPRA a GPC signal is a valid opt-out.

Closing the notice = implied acceptance: the banner has a close (×) button, and Escape does the same. In this opt-out model that records "accept" so the notice isn't shown again (tracking was already active). Explicit Opt Out still blocks tracking.


3. WP Code snippet templates

3a. Google (GA4 / GTM / Google Ads)

No change needed. Keep your existing snippet. The plugin handles consent via Consent Mode v2. Just make sure Emit Google Consent Mode v2 signals is enabled.

3b. Meta Pixel

Add the last line to your existing Pixel snippet (opt-out model: granted by default, revoked when the visitor opts out):

<script>
  !function(f,b,e,v,n,t,s){/* standard Meta Pixel loader */}(window, document,'script',
  'https://connect.facebook.net/en_US/fbevents.js');
  fbq('init', 'YOUR_PIXEL_ID');
  fbq('track', 'PageView');

  // CPCM: revoke if this visitor has opted out.
  if (window.CPCM && !CPCM.allows()) { fbq('consent', 'revoke'); }
</script>

3c. Any other non-essential script (Hotjar, LinkedIn, TikTok, call tracking…)

Wrap the snippet body so it only runs when consent allows it:

<script>
  (function () {
    function load() {
      // --- paste the third-party snippet body here ---
    }
    if (!window.CPCM || CPCM.allows()) {
      load(); // opt-out model: load by default unless opted out
    } else {
      // optional: load later if the visitor accepts during this session
      CPCM.onChange(function (granted) { if (granted) load(); });
    }
  })();
</script>

4. Cookie Preferences link (let visitors change their choice)

  • Shortcode anywhere: [cookie_preferences] or [cookie_preferences label="Manage cookies"]
  • Manual / theme link:
    <a href="#" onclick="window.CPCM.openSettings(); return false;">Cookie Preferences</a>

5. JavaScript API (window.CPCM)

Method Returns Purpose
CPCM.getChoice() 'accepted' | 'opted_out' | null Current stored choice.
CPCM.hasChoice() boolean Whether a valid choice exists.
CPCM.allows() boolean True when non-essential scripts may run.
CPCM.accept() Persist "accept" + resume tracking.
CPCM.optOut() Persist "opt out" + block tracking.
CPCM.dismiss() Implied acceptance (close/Esc): records "accept" so the notice isn't shown again.
CPCM.reset() Forget the choice.
CPCM.onChange(cb) unsubscribe fn cb(granted, choice) on every change.
CPCM.openSettings() Re-open the banner.

6. Storage & lifetime

  • First-party cookie cpcm_consent = {"choice":"accepted|opted_out","ts":<ms>,"v":<version>}, SameSite=Lax (source of truth).
  • Mirrored to localStorage.cookieConsent (accepted / opted_out) for compatibility with the classic pattern localStorage.getItem("cookieConsent") !== "opted_out".
  • Default lifetime 365 days (configurable). After expiry, or when Consent version changes, the banner re-appears.

7. Architecture

core-privacy-consent-manager.php   Bootstrap: constants, autoloader, activation
includes/class-plugin.php          Orchestrator (composition root)
includes/class-settings.php        Settings model (defaults + read) + cookie/choice constants
admin/class-settings-page.php      Settings API page + input sanitization
frontend/class-banner-renderer.php Asset enqueue + banner markup
frontend/class-consent-mode.php    Google Consent Mode v2 default/update
frontend/class-shortcode.php       [cookie_preferences] shortcode
assets/js/consent-sdk.js           window.CPCM (state, storage, signals)
assets/js/banner.js                Banner UI
assets/css/banner.css              Fluid styles (CSS vars + clamp())

8. QA checklist

  1. First visit (no choice): banner shows; GA4/GTM load; consent default = granted.
  2. Accept: banner hides; cookie choice = accepted; tracking continues; reload → no banner.
  3. Opt Out: banner hides; cookie choice = opted_out; Consent Mode update → denied in dataLayer; no new GA/Ads cookies; Meta fbq consent revoke (no new Pixel requests).
  4. Persistence/expiry: choice survives reload; clearing cookie or bumping Consent version re-shows the banner.
  5. Preferences: [cookie_preferences] re-opens the banner.
  6. Performance/a11y: scripts are deferred (footer); no layout shift; keyboard navigable; visible focus.

Read the full README on GitHub →