Consent Management
Category-based script blocking, GTM Consent Mode v2, and an accessible consent banner.
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 categories
| Category | Description | Blocked by default? |
|---|---|---|
| Functional | Essential for the site to work | No — always active |
| Analytics | Usage analytics (e.g. GA4, Plausible) | Yes |
| Marketing | Advertising and retargeting | Yes |
| Personalisation | Personalised content and recommendations | Yes |
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

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)

Storing consent records
Consent events are stored in the pv_consent_log database table:
| Field | Description |
|---|---|
id | Auto-increment primary key |
timestamp | When consent was given or changed |
categories | JSON: {"analytics": true, "marketing": false, ...} |
user_agent | Visitor browser string |
ip_hash | SHA-256 of the IP address (not the raw IP) |
version | Consent 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:
typeattribute swap — DPOKit rewritestype="text/javascript"totype="text/plain"for known scripts and restores the type on consent.- Filter-based blocking — DPOKit hooks into
wp_print_scripts/wp_enqueue_scriptsto 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:
- Updates the
pv_consentcookie - Logs a new consent record
- Reloads the page to unload any scripts that were already running