COOKR Documentation
Documentation

COOKR

WordPress consent infrastructure built around a single principle: consent controls execution, not just UI state. Scripts are intercepted server-side before the browser receives them. There is no race condition.


Installation

COOKR requires WordPress 6.0 or later and PHP 7.4 or later. No additional dependencies.

Install CORE

Download cookr-core-vX.X.X.zip and install via Plugins → Add New → Upload Plugin. Activate. The plugin is operational immediately — no setup wizard, no account required.

On first activation, COOKR does not block any scripts and does not show a banner until you configure and enable it in the admin panel. Safe to activate on a live site.

Install with RADR

Install cookr-vX.X.X.zip instead. The RADR panel appears at the top of the COOKR settings page. Run an initial runtime scan after activation.

Updates

Standard WordPress update flow. Configuration is preserved across updates. Or via WP-CLI:

wp plugin update cookr

Uninstall

Deactivating stops all front-end interception immediately. Deleting the plugin removes all stored data via uninstall.php — unless Preserve data on uninstall is enabled in settings, in which case no data is deleted.


CORE vs RADR

COOKR ships in two configurations. CORE is the released infrastructure layer. RADR is an emerging intelligence layer built on top of it.

CORE
  • Consent banner & UI
  • Server-side script interception
  • Auto-Blocker
  • Script restoration after consent
  • Runtime Inspector
  • CSP-aware mode
  • Google Consent Mode v2
  • JavaScript API
  • No account required
RADR
  • Everything in CORE
  • Service detection & classification
  • Tracker signature database
  • Automatic blocking recommendations
  • Risk assessment per service
  • Automatic signature updates

The distinction matters architecturally. CORE intercepts and controls execution. RADR identifies what is being executed and interprets it.

CORE is complete consent infrastructure. RADR adds operational visibility and automatic configuration. Sites running CORE with manually configured blocked_domains get the same enforcement guarantees as RADR — RADR just discovers and configures those domains for you.


Basic Setup

1. Enable the banner

In the COOKR admin panel, configure your banner text, privacy policy URL, and imprint URL. The live preview updates as you change settings. Save.

2. Enable the Auto-Blocker

The Auto-Blocker is the core enforcement mechanism. Enable it under Settings → Auto-block third-party scripts. Test your site after enabling — particularly if you use a caching plugin or JavaScript optimiser.

3. Configure blocked domains

Add the domains of third-party services that require consent. Examples: www.googletagmanager.com, connect.facebook.net, analytics.tiktok.com. RADR does this automatically. CORE users configure it manually.

4. Verify

Load your site while logged out. The consent banner should appear. Inspect network requests — configured domains should not fire until consent is granted. Use the Runtime Inspector (?cookr_debug=1) to observe script execution.


Runtime-first CORE

Most consent plugins operate at the UI layer. They show a banner, record a choice, and rely on tag managers or JavaScript conditions to act on that choice later. Scripts often fire before the user has made any decision.

COOKR operates at the runtime layer. Blocking happens in the PHP output buffer, before the browser receives the page. There is no race condition.

How it works

WordPress generates a page via PHP. Before the response is sent, COOKR intercepts the output buffer and processes the HTML using WP_HTML_Tag_Processor — WordPress's native HTML parser. Scripts requiring consent are neutralized: their type attribute is rewritten to text/plain, preventing browser execution. Original attributes are stored in data-cookr-* attributes for restoration after consent.

Why server-side

JavaScript-based blocking cannot guarantee pre-consent execution is prevented. Any script that loads before the consent JS initializes will execute. Load order, caching, CDN behaviour, and browser quirks all create real attack surface. Server-side blocking is deterministic: a script cannot execute if it was never delivered as executable.

Consent state

Consent is stored in a first-party cookie (cookr_consent). On each request, the PHP runtime reads this cookie to determine whether scripts should be blocked or passed through. No consent cookie = all configured scripts blocked. Blocking is the default.


Auto-Blocker CORE

The Auto-Blocker is the enforcement engine. It intercepts scripts and iframes matching configured domains before the browser executes them.

Script neutralization

When a script matches a blocked domain, COOKR rewrites it in-place:

<!-- Original -->
<script src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXXX"></script>

<!-- After COOKR -->
<script
  type="text/plain"
  data-cookr-src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXXX"
  data-cookr-type="text/javascript"
  data-cookr-category="analytics"
></script>

type="text/plain" is the standard browser mechanism for preventing script execution. The original attributes are preserved for restoration.

What is blocked

The Auto-Blocker intercepts <script> tags with external src attributes matching configured domains, and <iframe> tags for configured external services.

What is never blocked

The blocker preserves WordPress core scripts, theme scripts, plugin infrastructure, application/json, application/ld+json, import maps, and hydration payloads. These are classified as application infrastructure, not third-party tracking.

Caching compatibility

Caching plugins that serve HTML from cache will bypass the output buffer interceptor. For sites using WP Rocket, LiteSpeed Cache, or similar — configure your cache plugin to exclude pages from caching when no consent cookie is present, or use their consent-mode integration if available. Test after enabling.


Runtime Inspector CORE

The Runtime Inspector observes what executes on your site at runtime — before COOKR has classified or blocked it. It provides raw visibility into third-party script and iframe activity.

Runtime Inspector is distinct from RADR. The Inspector exposes raw execution. RADR interprets it — classifying services, assessing risk, recommending configuration. The Inspector is infrastructure. RADR is intelligence.

Enable

Enable under Settings → Runtime Inspector. It is on by default. To observe findings, visit any page on your site while logged in and append ?cookr_debug=1 to the URL. Open the Runtime tab in the debug panel.

Auto-disable

The Inspector auto-disables after a configurable duration (default 24 hours). It is an admin-only tool — zero overhead for visitors. No data is transmitted externally.

What it shows

Every external domain contacted by scripts or iframes during a page load — including domains COOKR has not yet classified. This is the discovery surface for new tracking services before they have signatures or configured blocking rules.


CSP-aware Mode CORE

CSP-aware mode restores blocked scripts without requiring unsafe-inline CSP exceptions. When a CSP nonce is present, COOKR propagates it to restored scripts at the point of restoration, not at the point of injection.

Why it exists

Standard consent plugin restoration approaches re-inject scripts dynamically via innerHTML or document.write — both incompatible with a strict CSP. COOKR's restoration mechanism reconstructs script elements via the DOM API and propagates nonces explicitly, preserving CSP integrity without requiring policy weakening.

Requirements

Your server must emit a Content-Security-Policy header with a nonce-{value} source. WordPress 6.4+ sets nonces on core scripts automatically. For custom CSP headers, ensure the nonce value rotates per request and is passed to COOKR by defining the COOKR_CSP_NONCE constant before WordPress loads the plugin.

define( 'COOKR_CSP_NONCE', your_nonce_generator() );

Script Restoration CORE

When a visitor grants consent, COOKR restores blocked scripts to their original executable state. Restoration is synchronous, deterministic, and order-preserving.

How restoration works

The JS runtime finds all neutralized scripts — identified by the presence of data-cookr-src — reconstructs their original attributes, and re-inserts them into the document as executable elements. Scripts execute in the order they were originally placed in the document.

Category-scoped restoration

Consent is granted per category (analytics, marketing, external_media). A consent grant for analytics restores only scripts in that category. A grant for all categories restores everything.

Consent withdrawal

When consent is withdrawn, the page reloads. Blocked scripts are not re-neutralized in-place — a page reload is the only reliable mechanism for ensuring previously executed scripts cannot continue to operate. This is correct behaviour, not a limitation.


JavaScript API CORE

COOKR exposes a stable JS API via the global window.cookrConsent object. Available after the page has loaded.

Check consent state

// Synchronously check a single category
cookrConsent.has( 'analytics' )   // → true | false
cookrConsent.has( 'marketing' )
cookrConsent.has( 'external_media' )
cookrConsent.has( 'necessary' )   // always true

// Get the full stored consent object
cookrConsent.getConsent()
// → { analytics: true, marketing: false, externalMedia: false, ts: 1234567890, pv: "1" }
// → null if no consent recorded yet

// Get consent cookie expiry
cookrConsent.getExpiry()   // → Date | null

// List all categories
cookrConsent.categories()
// → [ 'necessary', 'analytics', 'marketing', 'external_media' ]

React to consent

// Call immediately if consent exists, or queue until granted
cookrConsent.require( 'analytics', function( prefs ) {
  initAnalytics()
} )

// Promise-based version
cookrConsent.whenConsented( 'marketing' ).then( function( prefs ) {
  loadFbPixel()
} )

Subscribe to events

cookrConsent.on( 'consent', function( prefs ) {
  // fired when consent is granted or updated
} )

cookrConsent.on( 'change', function( prefs ) {
  // fired when consent categories change after initial grant
} )

cookrConsent.on( 'decline', function( prefs ) {
  // fired when all optional categories are declined
} )

cookrConsent.on( 'reset', function() {
  // fired on cookrConsent.reset()
} )

// Unsubscribe
cookrConsent.off( 'consent', handler )

Reset consent

// Clears the consent cookie and reloads the page
cookrConsent.reset()

Troubleshooting

Scripts still fire before consent

Most likely cause: a caching plugin is serving cached HTML that predates COOKR's output buffer interception. Clear all caches after enabling the Auto-Blocker. Verify the cache is not serving a pre-interception version of the page to logged-out users.

Second likely cause: the domain is not in your blocked_domains list. RADR will detect this automatically. CORE users should verify the domain with the Runtime Inspector.

Banner not appearing

Check that the banner is enabled in the COOKR admin panel. Verify the cookr_consent cookie is not already set in your browser from a previous session. Clear cookies and reload.

WP Rocket / LiteSpeed conflicts

JavaScript optimisation features — particularly defer inline JS and combine JS — can interfere with COOKR's output buffer. Exclude cookr from any JS combination or deferral rules. In WP Rocket, add cookr to the JS exclusion list.

Autoptimize conflict

Disable Also defer inline JS in Autoptimize settings, or add cookr to the Autoptimize JS exclusion list. COOKR detects this conflict automatically and shows an admin notice when both conditions are active.

CSP violations on restoration

If restored scripts trigger CSP violations, enable CSP-aware mode and define the COOKR_CSP_NONCE constant. See CSP-aware Mode.

Debug Inspector

Append ?cookr_debug=1 to any URL while logged in as an admin. The debug panel shows: blocked scripts, consent state, active categories, runtime findings, and a diagnostics summary.


What is RADR?

RADR is the intelligence layer built on top of COOKR's runtime infrastructure. Where CORE intercepts and controls script execution, RADR identifies what is being executed and interprets its consent relevance.

RADR is in gradual rollout. The concepts below reflect how the system works. Full operational documentation will follow as availability expands.

The distinction

Runtime Inspector (CORE)
  • Raw runtime visibility
  • Observes what executes
  • No classification
  • Discovery surface
RADR
  • Interpreted runtime intelligence
  • Identifies services
  • Classifies by category & risk
  • Recommends configuration

Why it exists

Manual domain configuration requires knowing which domains need blocking. On a real site, this is non-trivial — tracking services load sub-resources from unexpected domains, tag managers inject scripts dynamically, and the surface changes over time. RADR answers the question: "What is actually running on my site before consent?"


Runtime Detection RADR

RADR scans your site's rendered output and matches detected domains against a curated signature database. Each detected service is classified by category, risk level, and blocking recommendation.

Detection states

State Meaning
block Detected, not yet blocked. RADR recommends automatic blocking.
blocked Detected and actively blocked before consent. Protected.
review Detected, but RADR is not confident enough to auto-block. Manual review recommended.
unknown Detected but not in the signature database. No classification available.

Signatures

RADR ships with a curated signature database of known tracking and analytics services. With an active RADR subscription, signatures update automatically from a remote endpoint — pulled periodically, cached locally. The blocking runtime never depends on remote availability. A failed update request does not affect consent enforcement.


Events CORE

These DOM events are dispatched on document.

Event Fired when e.detail
cookr:consent Consent is granted or updated Consent object { analytics, marketing, externalMedia, ts, pv }
cookr:script-restored A blocked script has been restored after consent { src, category }
cookr:inline-blocked An inline script was blocked before consent { category }

The cookrConsent API also provides an event bus via cookrConsent.on() for consent, change, decline, and reset events. See JavaScript API.

Usage

document.addEventListener( 'cookr:consent', function ( e ) {
  var consent = e.detail
  // consent.analytics → true | false
  // consent.marketing → true | false
  // consent.externalMedia → true | false
} )

PHP Hooks & Filters CORE

COOKR currently exposes a minimal set of integration points. Additional hooks and extension points are planned for future releases.

Constants

Constant Description
COOKR_CSP_NONCE Define this constant with a per-request nonce string to enable CSP-aware script restoration. COOKR will attach the nonce to restored script elements.

Example

define( 'COOKR_CSP_NONCE', your_nonce_generator() );

Configuration beyond this is done via the admin settings page or directly via the cookr_settings option in wp_options.


Settings Reference

Setting Default Description
auto_block 0 Enable server-side script interception. Recommended — test with caching plugins.
blocked_domains [] Array of domains to intercept. Configured manually or via RADR.
gcm_enabled 0 Send Google Consent Mode v2 signals. Enable only if GTM is installed.
runtime_inspector_enabled 1 Observe third-party script execution. Admin-only, zero visitor overhead.
preserve_data 1 When enabled, deleting the plugin leaves all data intact. Disabled = full wipe on delete.
accent_color #F37022 Banner accent colour. Applied to buttons, icon, and links.
banner_position bottom-right Banner position on screen. One of 9 grid positions.
policy_version 1 Increment to trigger re-consent when your privacy policy changes.

All settings are stored in wp_options under the key cookr_settings with autoload = false.