Consent Management

Category-based script blocking, GTM Consent Mode v2, and an accessible consent banner.

4 min read

Consent Management

DPOKit blocks non-essential third-party scripts until the visitor grants consent, stores consent records, and integrates with Google Tag Manager Consent Mode v2.

Consent banner displayed at the bottom of a page with Accept All, Reject All, and Manage Preferences buttons

Consent categories

CategoryDescriptionBlocked by default?
FunctionalEssential for the site to workNo — always active
AnalyticsUsage analytics (e.g. GA4, Plausible)Yes
MarketingAdvertising and retargetingYes
PersonalisationPersonalised content and recommendationsYes

Each category maps to one or more vendors from your data map. You can rename categories and add custom ones.

The consent banner

The banner appears on first visit for all visitors. It offers:

  • Accept all — grants all non-functional categories
  • Reject all — denies all non-functional categories
  • Manage preferences — opens the preference centre modal

Preference centre modal showing per-category toggles with descriptions for each consent category

Accessibility

The banner and preference centre are WCAG 2.1 AA compliant:

  • Keyboard navigable (Tab / Shift+Tab / Enter / Space)
  • All interactive elements have ARIA labels
  • Focus is trapped within the modal when open
  • Screen reader announcements on consent state change

Customisation

Go to DPOKit → Consent → Appearance to configure:

  • Banner position (bottom bar, bottom-left corner, top bar)
  • Heading and body text
  • Button labels and colours
  • Custom CSS (no code editing required in most cases)

Consent banner appearance settings screen with position, colour, and text customisation options

Storing consent records

Consent events are stored in the pv_consent_log database table:

FieldDescription
idAuto-increment primary key
timestampWhen consent was given or changed
categoriesJSON: {"analytics": true, "marketing": false, ...}
user_agentVisitor browser string
ip_hashSHA-256 of the IP address (not the raw IP)
versionConsent banner version at time of consent

Consent is stored in a first-party cookie (pv_consent) and in the database for audit purposes.

GTM Consent Mode v2

DPOKit fires the following GTM Consent Mode signals before the GTM container loads:

gtag('consent', 'default', {
  analytics_storage:     'denied',
  ad_storage:            'denied',
  ad_user_data:          'denied',
  ad_personalization:    'denied',
  functionality_storage: 'granted',
  security_storage:      'granted',
});

When the visitor grants consent, DPOKit calls gtag('consent', 'update', {...}) with the appropriate granted categories.

Script blocking

Scripts are blocked using one of two mechanisms:

  1. type attribute swap — DPOKit rewrites type="text/javascript" to type="text/plain" for known scripts and restores the type on consent.
  2. Filter-based blocking — DPOKit hooks into wp_print_scripts / wp_enqueue_scripts to dequeue plugins' scripts that are registered with DPOKit.

Registering a script for consent gating

add_filter( 'pv_consent_gated_scripts', function( $scripts ) {
    $scripts[] = [
        'handle'   => 'my-analytics-script',
        'category' => 'analytics',
    ];
    return $scripts;
} );

Registering multiple scripts

add_filter( 'pv_consent_gated_scripts', function( $scripts ) {
    // Gate a marketing pixel under the "marketing" category
    $scripts[] = [
        'handle'   => 'my-retargeting-pixel',
        'category' => 'marketing',
    ];
 
    // Gate a personalisation script with a callback on consent grant
    $scripts[] = [
        'handle'          => 'my-personalisation',
        'category'        => 'personalisation',
        'on_consent'      => function( bool $granted ) {
            // Called client-side via wp_add_inline_script when consent changes
        },
    ];
 
    return $scripts;
} );

Adding a custom consent category

add_filter( 'pv_consent_categories', function( $categories ) {
    $categories['social'] = [
        'label'       => 'Social Media',
        'description' => 'Enables embedded social media content and sharing buttons.',
        'default'     => false,
    ];
    return $categories;
} );

Reacting to consent changes (server-side)

// Fired when a visitor's consent record is saved or updated
add_action( 'pv_consent_recorded', function( $consent_id, $categories, $ip_hash ) {
    // $categories: [ 'analytics' => true, 'marketing' => false, ... ]
    if ( ! empty( $categories['analytics'] ) ) {
        // Analytics consent granted — do something server-side
    }
}, 10, 3 );

Reacting to consent changes (client-side)

// Listen for DPOKit consent events dispatched on window
window.addEventListener('pv:consent:updated', (event) => {
  const { categories } = event.detail;
  // categories: { analytics: true, marketing: false, ... }
 
  if (categories.analytics) {
    // Re-initialise analytics tools
  }
});

Consent withdrawal

Visitors can change their consent at any time by clicking the Privacy Preferences link (added automatically to your footer) to reopen the preference centre.

On withdrawal, DPOKit:

  1. Updates the pv_consent cookie
  2. Logs a new consent record
  3. Reloads the page to unload any scripts that were already running