ConsentPixel – Privacy · Verified

🚀 Getting Started

ConsentPixel — Privacy · Verified

One <script> tag in your <head>. Full CIPA, GDPR, CCPA, and US state law compliance — automatic. No plugins, no dependencies, no page reload required. Load time under 50ms from Cloudflare's global edge.

✓ Works on any platform

WordPress, Shopify, Webflow, Next.js, Squarespace, Wix, raw HTML — or any other framework. The pixel is framework-agnostic vanilla JS. If you can add a <script> tag to your site's <head>, you can install ConsentPixel.

How it works

The ConsentPixel pixel does five things in sequence on every page load:

  1. Blocks all non-essential scripts before the browser can execute them — MutationObserver intercept rewrites type="text/javascript" to text/plain on any script not categorised as strictly necessary.
  2. Fetches your banner configuration from Cloudflare's edge network in under 50ms — your branding, categories, language settings.
  3. Detects the visitor's jurisdiction from Cloudflare request headers — GDPR for EU/EEA/UK, CCPA for California, state-specific rules for VA/CO/TX/FL/CT.
  4. Renders the consent banner in a Shadow DOM — fully isolated from your site's styles, keyboard-navigable, WCAG 2.1 AA accessible.
  5. On consent decision — restores blocked scripts per category, fires Google Consent Mode v2 signals, posts an immutable consent log to your dashboard.

Prerequisites

  • A ConsentPixel account — sign up free (14-day trial, no card)
  • Your Site ID — found in your portal under Settings → Sites → Your site → Pixel snippet
  • Ability to edit your site's <head> tag
⚠ Install in <head>, not <body>

The pixel must load in the <head> tag — before any other scripts — to block trackers before the browser executes them. Installing in the footer or after other scripts defeats the CIPA protection entirely. The script is async so it will not block page rendering.

📦 Installation

Install the pixel in 4 steps

From zero to full compliance in under 10 minutes on any platform.

1
Get your pixel snippet from the portal
Log in to your ConsentPixel portal → Settings → Sites → select your site → copy the pixel snippet. It looks like this — your SITE_ID is pre-filled:
HTML
<!-- ConsentPixel — Privacy · Verified -->
<script
  src="https://cdn.consentpixel.com/pixel.min.js"
  data-site-id="YOUR_SITE_ID"
  async
></script>
2
Paste it as the first child of <head>
Add the snippet to your site's <head> tag — before any other scripts, stylesheets, or third-party tags. This is critical: the pixel must run before any other scripts to intercept them.
HTML
<html>
<head>
  <!-- ConsentPixel FIRST — before all other scripts -->
  <script src="https://cdn.consentpixel.com/pixel.min.js"
    data-site-id="YOUR_SITE_ID" async></script>

  <!-- All other scripts AFTER -->
  <script src="https://www.googletagmanager.com/gtag/js" async></script>
  <!-- ... rest of <head> ... -->
</head>
3
Configure your consent banner in the portal
Go to your ConsentPixel portal → Banner Builder. Set your brand colours, logo, and text. Choose your regulation mode (Auto is recommended — the pixel detects each visitor's jurisdiction automatically). Hit Publish. The banner goes live on your site within 60 seconds — no code change needed.
4
Verify the pixel is working
Your portal will automatically detect the pixel within 2–5 minutes of your first page load. You'll see a green ✓ next to your site in the dashboard. You can also verify manually — see Verify Install for debugging steps.

Optional configuration attributes

The pixel script tag accepts optional data-* attributes to override defaults:

AttributeTypeDefaultDescription
data-site-idstringRequired Your site's unique identifier from the portal.
data-modestring"auto"Regulation mode. Options: auto | gdpr | ccpa | cipa. Auto detects per visitor location.
data-languagestring"auto"Banner language. Auto detects from browser headers. Override with ISO 639-1 code e.g. en, de, fr.
data-block-on-loadbooleantrueWhether to block non-essential scripts on load. Set false only if you manage blocking manually via the JS API.
data-gpc-respectbooleantrueWhether to honour the Global Privacy Control signal. Required for CCPA 2026 compliance — do not disable.
data-consent-expirynumber365Days before re-prompting for consent. Minimum 90 for GDPR. Maximum 395.
✅ Verify Install

Verify your installation

Three ways to confirm the pixel is installed correctly and blocking pre-consent tracking.

Method 1 — Portal auto-detection

After installing the pixel, load any page on your site in a browser. Within 2–5 minutes, your ConsentPixel portal will show a green ✓ next to your site. If you see a yellow ⚠ after 10 minutes, check that the pixel is in <head> and the data-site-id matches your portal site ID exactly.

Method 2 — Browser network inspector

Open your site in a fresh private/incognito window. Open DevTools → Network tab. Load the page. Look for a request to cdn.consentpixel.com/pixel.min.js — it should be one of the first requests. Then look at the request timing for any third-party trackers — they should show either blocked status or fire only after a consent event.

Method 3 — Browser console

JavaScript — browser console
// Paste in browser console on your site
const cp = window.ConsentPixel;

if (cp) {
  console.log('✓ Pixel loaded — version:', cp.version());
  console.log('Current consent:', cp.getConsent());
  console.log('Regulation detected:', cp.getRegulation());
  console.log('Blocked scripts:', cp.getBlockedScripts());
} else {
  console.error('✗ ConsentPixel not found — check <head> installation');
}
✓ Expected output when installed correctly

✓ Pixel loaded — version: 1.2.0
Current consent: { analytics: false, marketing: false, functional: true }
Regulation detected: "gdpr" (or ccpa / cipa depending on visitor location)
Blocked scripts: ["hotjar.com", "static.hotjar.com", "clarity.ms", ...]

🔌 Platform Guides

Platform-specific installation

Step-by-step guides for the most common platforms. The pixel code is identical across all platforms — only where you paste it differs.

WordPress

Recommended: Use the theme's header. This is faster and more reliable than a plugin.

  1. Go to Appearance → Theme File Editor (or Appearance → Theme Editor).
  2. Select header.php from the file list on the right.
  3. Find the opening <head> tag and paste the ConsentPixel snippet immediately after it — before any other scripts.
  4. Click Update File.
Using a child theme?

Always edit the child theme's header.php, not the parent theme. Parent theme updates will overwrite changes to the parent's files. If your child theme doesn't have a header.php, copy it from the parent theme first.

Alternative — wp_head hook: Add this to your child theme's functions.php:

PHP — functions.php
function consentpixel_head() {
    echo '<script src="https://cdn.consentpixel.com/pixel.min.js"
      data-site-id="YOUR_SITE_ID" async></script>';
}
add_action( 'wp_head', 'consentpixel_head', 1 );

Priority 1 ensures ConsentPixel loads before any other wp_head hooks. Do not use priority 10 (default) — other plugins will load their scripts before ConsentPixel.

Shopify

  1. In your Shopify admin, go to Online Store → Themes.
  2. Click Actions → Edit code on your active theme.
  3. Open layout/theme.liquid.
  4. Find the <head> tag and paste the ConsentPixel snippet as the very first line inside it.
  5. Click Save.
Liquid — theme.liquid
<head>
  {%- comment -%} ConsentPixel — must be first {%- endcomment -%}
  <script
    src="https://cdn.consentpixel.com/pixel.min.js"
    data-site-id="YOUR_SITE_ID"
    async
  ></script>

  {%- render 'head-tags' -%}
  {{- content_for_header -}}
  <!-- ... rest of head ... -->
Important: Shopify checkout pages

Shopify's checkout pages (/checkout, /thank_you) require a Shopify Plus plan to inject custom head scripts. On non-Plus plans, use Shopify's Customer Privacy API alongside ConsentPixel on non-checkout pages. Contact support@consentpixel.com for the Shopify Plus checkout guide.

Webflow

  1. In the Webflow Designer, open Project Settings → Custom Code.
  2. In the Head Code field, paste the ConsentPixel snippet.
  3. Click Save Changes then Publish your site.

Webflow's Head Code field loads before all other scripts — ideal for ConsentPixel. No additional configuration needed for standard Webflow sites.

Webflow — Project Settings → Head Code
<!-- ConsentPixel — Privacy · Verified -->
<script
  src="https://cdn.consentpixel.com/pixel.min.js"
  data-site-id="YOUR_SITE_ID"
  async
></script>

Next.js

Use Next.js's built-in <Script> component with strategy="beforeInteractive" to ensure the pixel loads before any other scripts — including those injected by the Next.js runtime.

TypeScript — app/layout.tsx (App Router)
import Script from 'next/script';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <head>
        {/* ConsentPixel — must use beforeInteractive */}
        <Script
          src="https://cdn.consentpixel.com/pixel.min.js"
          data-site-id={process.env.NEXT_PUBLIC_CONSENTPIXEL_SITE_ID}
          strategy="beforeInteractive"
        />
      </head>
      <body>{children}</body>
    </html>
  );
}

Add your site ID to .env.local:

.env.local
NEXT_PUBLIC_CONSENTPIXEL_SITE_ID=your_site_id_here
Pages Router (older Next.js)?

Add the Script component to pages/_document.tsx inside the <Head> component from next/document, with strategy="beforeInteractive". Do not use _app.tsx — it loads too late.

Squarespace

  1. Go to Website → Pages → Website Tools → Code Injection.
  2. In the HEADER field, paste the ConsentPixel snippet.
  3. Click Save.
Squarespace plan requirement

Code Injection requires a Business plan or higher. The Personal plan does not support custom code injection. If you're on Personal, upgrade or contact us about the Squarespace-specific workaround via our agency partners.

Squarespace — Header Code Injection
<script
  src="https://cdn.consentpixel.com/pixel.min.js"
  data-site-id="YOUR_SITE_ID"
  async
></script>

Wix

  1. In your Wix dashboard, go to Settings → Custom Code.
  2. Click + Add Custom Code.
  3. Paste the ConsentPixel snippet.
  4. Set Place Code inHead.
  5. Set Add Code to PagesAll Pages.
  6. Set Load Code Oncetrue.
  7. Click Apply.
Wix load order limitation

Wix does not guarantee script load order within the head. If you notice analytics firing before consent, enable the data-block-on-load attribute and contact support@consentpixel.com for the Wix-specific configuration guide that works around this limitation.

📊 Google Consent Mode v2

Google Consent Mode v2

ConsentPixel — Privacy · Verified automatically implements Google Consent Mode v2. No additional configuration is required if you've installed the pixel before your GA4 or GTM tags. This section explains what happens and how to verify it.

How ConsentPixel handles Consent Mode v2

On every page load, ConsentPixel injects a gtag('consent', 'default', ...) call into the dataLayer before Google Tag Manager or GA4 loads. All four v2 signals are set to 'denied' by default. When the visitor makes a consent decision, ConsentPixel fires gtag('consent', 'update', ...) with the appropriate signal values.

The four Consent Mode v2 signals
SignalWhat it controlsDefault
ad_storage Enables storage of advertising cookies and identifiers. Controls whether Google Ads and DoubleClick cookies are set. denied
analytics_storage Enables storage of analytics cookies. Controls whether GA4 sets measurement cookies and collects full session data. denied
ad_user_data Controls whether user data can be sent to Google for advertising purposes — remarketing audiences, customer match. denied
ad_personalization Controls whether personalised advertising is enabled — interest-based targeting and remarketing. denied

Automatic signal mapping

ConsentPixel maps your consent categories to Consent Mode v2 signals automatically:

Visitor consents toSignals set to granted
Analytics categoryanalytics_storage: 'granted'
Marketing categoryad_storage: 'granted', ad_user_data: 'granted', ad_personalization: 'granted'
Accept allAll four signals set to 'granted'
Decline all / GPC signalAll four signals remain 'denied'

Manual signal control (advanced)

You can override the automatic mapping using the JavaScript API:

JavaScript
// Override GCM signals manually (advanced use only)
window.ConsentPixel.setConsentModeSignals({
  ad_storage: 'denied',
  analytics_storage: 'granted',
  ad_user_data: 'denied',
  ad_personalization: 'denied',
});

// Listen for consent updates and sync to GCM
window.ConsentPixel.on('consent:update', (decision) => {
  // decision.categories: { analytics: bool, marketing: bool, functional: bool }
  // ConsentPixel handles GCM update automatically — this is for custom logic
  console.log('Consent updated:', decision);
});

Verify Consent Mode is active

In Google Tag Manager, add a GA4 Configuration tag and enable Require additional consent for ad measurement. Then use the GTM Preview mode — you should see consent state in the dataLayer events before any GA4 events fire.

In GA4, go to Admin → Data Streams → your stream → Consent settings. If Consent Mode is active, you'll see the modelled conversion data toggle available.

🏷 GTM Integration

Google Tag Manager integration

ConsentPixel — Privacy · Verified intercepts the GTM dataLayer before GTM loads, injecting consent state at the source. Tags configured with consent checks in GTM will respect ConsentPixel decisions automatically.

Step 1 — Load order

ConsentPixel must load before GTM. Verify your <head> order:

HTML — correct load order
<head>
  <!-- 1. ConsentPixel FIRST -->
  <script src="https://cdn.consentpixel.com/pixel.min.js"
    data-site-id="YOUR_SITE_ID" async></script>

  <!-- 2. GTM second -->
  <script>
    (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
    new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
    j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
    'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
    })(window,document,'script','dataLayer','GTM-XXXXXXX');
  </script>
</head>

Step 2 — Configure consent in GTM

In GTM, go to Admin → Container Settings → Additional Settings and enable Enable consent overview. Then for each tag, click the shield icon (🛡) in the tag editor and configure which consent type must be granted before the tag fires:

  • GA4 — requires analytics_storage: granted
  • Google Ads — requires ad_storage: granted and ad_user_data: granted
  • Meta Pixel — requires ad_storage: granted
  • Hotjar / FullStory / Clarity — requires analytics_storage: granted (or block entirely at pixel level — recommended for CIPA)

Step 3 — Test with GTM Preview

Open GTM → Preview mode → visit your site. In the dataLayer panel, you should see a consent_default event fired by ConsentPixel before any other events. After you interact with the consent banner, you should see a consent_update event with the updated signal values.

⚠ GTM-injected Hotjar / Clarity

If Hotjar or Clarity are loaded via GTM, configuring GTM consent checks is not sufficient for CIPA protection — GTM itself fires before consent and can still load scripts. ConsentPixel's MutationObserver intercept blocks the GTM container's injected scripts too, but only if ConsentPixel loads before GTM. Verify load order is correct using the browser console method in the Verify Install section.

⚙️ JavaScript API

window.ConsentPixel API Reference

After the pixel loads, window.ConsentPixel exposes a stable public API for reading consent state, responding to consent events, and programmatically controlling the banner.

API availability

The window.ConsentPixel object is available as soon as the pixel loads. Because the script is async, check availability before calling API methods, or listen for the ConsentPixel:ready event on window.

Core methods

MethodReturnsDescription
.version()stringReturns the current pixel version string. e.g. "1.2.0"
.getConsent()ConsentStateReturns the visitor's current consent decision object. Null if no decision has been made yet.
.getRegulation()RegulationReturns the detected regulation for this visitor. One of "gdpr" | "ccpa" | "cipa" | "none".
.getGeo()GeoInfoReturns the visitor's detected country and region codes used for regulation detection.
.hasConsented(category)booleanReturns true if the visitor has consented to the given category. Category: "analytics" | "marketing" | "functional".
.getBlockedScripts()string[]Returns array of third-party domains currently being blocked pending consent.
.getBannerVersion()stringReturns the version identifier of the banner currently shown to this visitor. Used in consent logs.

Banner control methods

MethodReturnsDescription
.showBanner()voidProgrammatically shows the consent banner. Useful for "Manage preferences" links in your footer.
.hideBanner()voidHides the consent banner. Only use if implementing a fully custom consent UI.
.acceptAll()Promise<void>Programmatically accepts all categories. Posts consent log. Re-enables all blocked scripts. Updates GCM signals.
.declineAll()Promise<void>Programmatically declines all non-essential categories. Posts consent log. All trackers remain blocked.
.setConsent(categories)Promise<void>Sets consent for specific categories. Accepts a partial ConsentCategories object.
.resetConsent()Promise<void>Clears the stored consent decision and re-shows the banner. Use for "Withdraw consent" UI.

Event methods

MethodReturnsDescription
.on(event, handler)voidRegisters an event listener. See Events section for all event types.
.off(event, handler)voidRemoves a previously registered event listener.
.once(event, handler)voidRegisters a one-time event listener that fires at most once then removes itself.

Advanced methods

MethodReturnsDescription
.setConsentModeSignals(signals)voidManually override Google Consent Mode v2 signals. See GCM section for signal names.
.getConsentLog()ConsentLogEntryReturns the most recent consent log entry for this visitor — timestamp, decision, banner version, regulation.
.isGPCActive()booleanReturns true if the visitor has Global Privacy Control enabled in their browser.

Usage examples

JavaScript — common patterns
// Wait for ConsentPixel to be ready
window.addEventListener('ConsentPixel:ready', () => {
  const cp = window.ConsentPixel;

  // Check if visitor has consented to analytics
  if (cp.hasConsented('analytics')) {
    // Load your own analytics code
  }

  // React to consent changes
  cp.on('consent:update', (decision) => {
    if (decision.categories.analytics) {
      // User accepted analytics — initialise your tool
    }
  });
});

// Add "Manage preferences" link to footer
document.getElementById('manage-cookies')
  .addEventListener('click', () => {
    window.ConsentPixel.showBanner();
  });
🔷 TypeScript Types

TypeScript type definitions

Full TypeScript type definitions for the window.ConsentPixel API. Add these to a .d.ts file in your project for full type safety.

TypeScript — consentpixel.d.ts
/** ConsentPixel — Privacy · Verified — Type Definitions v1.2 */

declare global {
  interface Window {
    ConsentPixel: ConsentPixelAPI;
  }
}

type Regulation = 'gdpr' | 'ccpa' | 'cipa' | 'none';

type ConsentCategory = 'functional' | 'analytics' | 'marketing';

type GCMSignalValue = 'granted' | 'denied';

interface ConsentCategories {
  functional: boolean;   // always true — strictly necessary
  analytics: boolean;
  marketing: boolean;
}

interface ConsentState {
  categories: ConsentCategories;
  timestamp: string;         // ISO 8601
  bannerVersion: string;
  regulation: Regulation;
  isGPCActive: boolean;
  method: 'explicit' | 'gpc' | 'implied';
}

interface GeoInfo {
  country: string;           // ISO 3166-1 alpha-2 e.g. "US"
  region: string | null;    // US state code e.g. "CA", null for non-US
  regulation: Regulation;
}

interface GCMSignals {
  ad_storage: GCMSignalValue;
  analytics_storage: GCMSignalValue;
  ad_user_data: GCMSignalValue;
  ad_personalization: GCMSignalValue;
}

interface ConsentDecisionEvent {
  categories: ConsentCategories;
  previousCategories: ConsentCategories | null;
  regulation: Regulation;
  gcmSignals: GCMSignals;
  timestamp: string;
}

interface ConsentLogEntry {
  visitorId: string;          // SHA-256 hashed — not a raw identifier
  siteId: string;
  timestamp: string;
  bannerVersion: string;
  regulation: Regulation;
  geo: { country: string; region: string | null };
  decision: ConsentCategories;
}

type ConsentPixelEvent =
  | 'consent:update'    // visitor made or changed consent decision
  | 'consent:reset'     // consent was cleared / banner re-shown
  | 'banner:show'       // banner became visible
  | 'banner:hide'       // banner was dismissed
  | 'script:unblocked'  // a script was re-enabled after consent;

interface ConsentPixelAPI {
  // Core
  version(): string;
  getConsent(): ConsentState | null;
  getRegulation(): Regulation;
  getGeo(): GeoInfo;
  hasConsented(category: ConsentCategory): boolean;
  getBlockedScripts(): string[];
  getBannerVersion(): string;
  isGPCActive(): boolean;

  // Banner control
  showBanner(): void;
  hideBanner(): void;
  acceptAll(): Promise<void>;
  declineAll(): Promise<void>;
  setConsent(categories: Partial<ConsentCategories>): Promise<void>;
  resetConsent(): Promise<void>;

  // Events
  on<E extends ConsentPixelEvent>(
    event: E,
    handler: (data: ConsentDecisionEvent) => void
  ): void;
  off<E extends ConsentPixelEvent>(
    event: E,
    handler: (data: ConsentDecisionEvent) => void
  ): void;
  once<E extends ConsentPixelEvent>(
    event: E,
    handler: (data: ConsentDecisionEvent) => void
  ): void;

  // Advanced
  setConsentModeSignals(signals: Partial<GCMSignals>): void;
  getConsentLog(): ConsentLogEntry | null;
}

export {};  // make this a module
📡 Events

ConsentPixel events

Subscribe to consent lifecycle events using window.ConsentPixel.on(). All events are dispatched on the window.ConsentPixel event emitter and also as native CustomEvent on window with the prefix ConsentPixel:.

Event nameWhen firedEvent data
consent:updateAny time the visitor makes or changes their consent decision — initial decision, preference update, or GPC detectionConsentDecisionEvent
consent:resetWhen resetConsent() is called or consent expires and is cleared{ timestamp: string }
banner:showWhen the consent banner becomes visible — initial load or showBanner() call{ regulation: Regulation, bannerVersion: string }
banner:hideWhen the banner is dismissed (any action) or hidden via hideBanner(){ action: 'accept' | 'decline' | 'partial' | 'close' }
script:unblockedWhen a previously blocked script is re-enabled after consent{ domain: string, category: ConsentCategory }

Listening via native CustomEvent

JavaScript
// Via ConsentPixel event emitter (recommended)
window.ConsentPixel.on('consent:update', (e) => {
  console.log('Analytics consented:', e.categories.analytics);
  console.log('Marketing consented:', e.categories.marketing);
  console.log('GCM signals:', e.gcmSignals);
});

// Via native window CustomEvent (alternative)
window.addEventListener('ConsentPixel:consent:update', (e) => {
  const decision = e.detail;
  // same shape as ConsentDecisionEvent
});
📋 DSAR Form Embed

DSAR form embed

Embed a Data Subject Access Request form on any page of your site. Submissions are routed directly to your ConsentPixel portal's DSAR inbox, where you can track status, set deadlines, and export responses for legal compliance.

Embed code

Paste this snippet anywhere in your page body where you want the DSAR form to appear — typically on your Privacy Policy page or a dedicated "Your Privacy Rights" page.

HTML — DSAR form embed
<!-- ConsentPixel DSAR Form -->
<div
  id="cp-dsar-form"
  data-site-id="YOUR_SITE_ID"
  data-lang="auto"
  data-theme="light"
></div>
<script
  src="https://cdn.consentpixel.com/dsar-form.js"
  async
></script>

Form preview

This is how the embedded form appears to your visitors:

Exercise Your Privacy Rights
GDPR · CCPA · All US state laws — response within 30 days

We will respond within 30 days (GDPR) or 45 days (CCPA). Your request is processed securely by ConsentPixel — Privacy · Verified. Privacy Policy.

Configuration options

AttributeTypeDefaultDescription
data-site-idstringRequired Your ConsentPixel site ID.
data-langstring"auto"Form language. Auto-detects from browser. Override with ISO 639-1 code.
data-themestring"light"Visual theme. Options: light | dark | system.
data-accent-colorstring"#00B896"CSS hex colour for the submit button and focus rings. Match your brand.
data-show-typesstring"all"Comma-separated list of request types to show. e.g. "access,deletion,portability".
data-redirect-urlstringURL to redirect to after successful submission. If not set, shows an inline success message.

Handling submissions in the portal

Submitted requests appear in your ConsentPixel portal under Compliance → DSAR Requests. Each request shows:

  • Requester name and email
  • Request type and any additional details
  • Submission timestamp and applicable regulation
  • Response deadline (auto-calculated — 30 days GDPR, 45 days CCPA)
  • Status workflow: Received → In review → Responded → Closed

All DSAR activity is logged to an immutable audit trail for regulatory compliance purposes.

🏅 Trust Badge

Privacy Verified trust badge

Display a cryptographically verified compliance badge on your site. The badge reflects your real-time compliance status — green when clean, amber when action is needed. It cannot be faked: the badge is served dynamically from our CDN and validates your domain on every request.

Badge embed code

HTML — trust badge embed
<!-- ConsentPixel Privacy Verified badge -->
<a
  href="https://verify.consentpixel.com/YOUR_SITE_ID"
  target="_blank"
  rel="noopener"
>
  <img
    src="https://badge.consentpixel.com/YOUR_SITE_ID"
    alt="Privacy Verified by ConsentPixel"
    width="160"
    height="40"
  />
</a>

How the badge is verified

The badge image is served by a Cloudflare Worker that checks your site's current compliance status on every request. The badge URL includes an HMAC-SHA256 token tied to your site ID and domain — any attempt to use the badge on a different domain returns a fraud-indicator badge automatically.

The badge reflects your most recent scan result: green (A/B grade), amber (C/D grade or outstanding alert), or red (F grade or domain mismatch). It updates automatically when your next scan completes — no code change needed.

📝 Changelog

Pixel changelog

All notable changes to the ConsentPixel pixel. The pixel is delivered via CDN — updates deploy automatically. Breaking changes are announced with 30 days notice.

v1.2.0 — May 2026

  • New: window.ConsentPixel.isGPCActive() method — query GPC status directly
  • New: script:unblocked event — know exactly when a blocked script is re-enabled
  • New: data-consent-expiry attribute — configure re-prompt interval (default 365 days)
  • Improved: GTM dataLayer intercept now handles dynamically injected GTM containers
  • Improved: Shadow DOM banner now correctly renders in all major browsers including Safari 17+
  • Fixed: GPC signal detection was not firing on Firefox 124+ — resolved
  • Fixed: Banner z-index conflict with Intercom widget on mobile — resolved

v1.1.0 — March 2026

  • New: CCPA 2026 dark pattern enforcement — asymmetric button configurations rejected at publish time
  • New: window.ConsentPixel.getConsentLog() — retrieve the current visitor's consent log entry
  • New: 12-language support — auto-detection from Accept-Language header
  • Improved: Pixel bundle size reduced from 9.2kb to 7.8kb gzipped
  • Improved: Consent Mode v2 signals now fired synchronously before any dataLayer.push

v1.0.0 — January 2026

  • Initial release — MutationObserver script blocker, shadow DOM banner, Cloudflare edge delivery
  • Google Consent Mode v2 — all four signals
  • GDPR, CCPA, CIPA regulation auto-detection
  • Immutable consent log POST to Supabase Edge Functions
  • GPC signal support (navigator.globalPrivacyControl + Sec-GPC header)
Scroll to Top