Title: DT-PM Consent
Author: dtpm
Published: <strong>November 5, 2026</strong>
Last modified: November 5, 2026

---

Search plugins

![](https://ps.w.org/dt-pm-consent/assets/banner-772x250.png?rev=3786727)

![](https://ps.w.org/dt-pm-consent/assets/icon.svg?rev=3786727)

# DT-PM Consent

 By [dtpm](https://profiles.wordpress.org/dtpm/)

[Download](https://downloads.wordpress.org/plugin/dt-pm-consent.1.1.4.zip)

 * [Details](https://wordpress.org/plugins/dt-pm-consent/#description)
 * [Reviews](https://wordpress.org/plugins/dt-pm-consent/#reviews)
 *  [Installation](https://wordpress.org/plugins/dt-pm-consent/#installation)
 * [Development](https://wordpress.org/plugins/dt-pm-consent/#developers)

 [Support](https://wordpress.org/support/plugin/dt-pm-consent/)

## Description

DT-PM Consent stops third-party scripts and embeds from loading before the
 visitor
has consented. It shows a banner with equally weighted buttons for accept and reject,
allows a choice per purpose, and records every configuration change as evidence.

#### What you get

 * A guided setup in four steps. It shows what your site loads, proposes an
    entry
   for every service it recognises, and names what is still open before it lets 
   you call the setup finished.
 * A scanner in two parts, both included. The server side reads the scripts and
   
   stylesheets WordPress knows about; a collector records what actually loads in
   your own browser while you are logged in, so a script injected at runtime is 
   found as well — not only one that sits in a registry. It finds and names; where
   it cannot block, it says so instead.
 * 24 ready-made service templates, each with provider, purpose, storage period
   
   and third-country transfer, and each backed by a source. Where a provider states
   nothing, the template says so rather than inventing a value, and for payment 
   services and tag managers the category is deliberately left to you. Your own 
   code can add entries through a documented filter.
 * A cookie declaration for your privacy policy, as a shortcode or a block. It
    
   is built from the same data as the banner and through the same code, so the two
   cannot end up saying different things.
 * An archive of every configuration change, exportable as CSV. It records what
   
   your banner said and when — it is not a log of individual visitors, and the plugin
   keeps none.
 * One consent cookie, carrying a fingerprint of the configuration rather than a
   
   bare counter: when the service or purpose list changes in substance, the fingerprint
   no longer matches and the banner asks again. The decision can optionally be shared
   across your own subdomains — switched off by default, and the FAQ below says 
   when to leave it off.
 * Warnings where an entry would be worthless. A service without a cookie name
    
   cannot have its cookies deleted on withdrawal, and a service with nothing this
   plugin can hold back is listed as a defect instead of counting as configured.
 * Keyboard operation, stated rather than implied: Escape rejects while no
    decision
   has been made and only closes the dialog once one exists, and the banner says
   which of the two applies. The banner passes axe-core against the WCAG 2.2 AA 
   rule set without a violation (Chromium, Twenty Twenty-Five, at 1280 and 640 pixels
   and at 200 % text size). No screen reader was used, so whether the error message
   is actually announced (4.1.3) is untested, and the check covered the visitor’s
   banner, not the admin screens.
 * German and English included.
 * GPLv2 or later. Nothing is held back for a paid version, and the plugin sends
   
   no request to any server of ours — not on a schedule, not at all.

No page-view limit, no domain limit, no seat count, and no switch that trips
 once
your site grows. There is nothing to count against: the plugin contacts no server
of ours, so no number about your site ever leaves it.

#### What the plugin does

 * Rewrites registered scripts of consent-requiring services into inert
    placeholders.
   The browser neither loads nor executes them.
 * Blocks the inline snippets WordPress attaches to a script as well — with
    analytics
   integrations, that is usually where the call that sets the cookie lives.
 * Replaces embedded iframes of known providers with a placeholder that names
    the
   provider and offers a button to load it.
 * Names each service and its provider visibly on the first banner level.
    Purpose,
   storage period, third-country transfer and the cookie names sit next to it, expandable—
   on the same level, without having to consent first.
 * Offers a way to withdraw consent from every page. Withdrawing deletes the
    affected
   cookies and reloads the page, so that scripts already running actually stop.
 * Compares today’s state against the last scan at the press of a button and
    reports
   what is new. Reminds you when the last scan is more than 30 days old.
 * Raises a configuration version whenever the service or purpose list changes
    
   in substance. Existing consents become invalid and the banner appears again.

#### What the plugin explicitly does NOT do

**It blocks nothing on its own.** Whatever is not in the service list is not
 blocked.
The setup helper shows the scripts that loaded and suggests an entry for the ones
it recognises — but it adopts nothing without your confirmation. That is a deliberate
decision: a plugin that decides by itself which scripts on someone else’s website
perform tracking would either block too little (and pretend safety) or too much (
and take the site down).

**Detection is not complete.** It knows a limited number of common services.
 An
unrecognised script is marked as unknown and presented with empty fields — the plugin
guesses neither provider nor purpose nor storage period. An empty row you have to
fill in is more honest than a filled-in one that is wrong.

**The setup helper puts two cases first: external servers and recognised
 services.

Everything else — WordPress itself, your theme, plugins on your
 own server — sits
below, collapsed but complete. That is a display decision and not a legal assessment:
a plugin can live on your server and still set cookies. Go through the second list
instead of relying on the first.

**It does not catch scripts written into the markup around the WordPress
 API.
 
The collector _finds_ them and tells you they are there — block them
 the plugin
cannot. You then have to act yourself: remove the integration from the theme, register
it through `wp_enqueue_script`, or serve the file from your own server.

**It stops nothing that is loaded from inside a stylesheet.** An
 @import url(‘https://
fonts.googleapis.com/…’) or a font in an `@font-face` rule keeps loading even when
the service is listed as blocked: the plugin can stop a stylesheet by its ADDRESS,
but it does not read what a stylesheet does inside. Four routes are affected — `@
import` in a `<style>` block, `@import` in an enqueued stylesheet, `url()` in an`@
font-face` rule, and background-image.

The setup helper _finds_ and names these cases for every stylesheet enqueued
 through
WordPress, under “Stylesheets that load from elsewhere”. Acting on them is up to
you: serve the font from your own server, or remove the reference in the theme. 
Many themes have a setting for exactly this. A

In detail: blocking applies to scripts registered through
 wp_enqueue_script(), 
to their inline snippets, to snippets entered in the admin area, and to iframes 
in post content, text widgets and oEmbed output. A theme that writes a tracking 
script directly into a template file is not covered. Check this after setup with
your browser’s developer tools: open the network tab, load the page without consenting,
go through the list.

**“Inline snippets” means less than it sounds like, and the difference
 matters.

It is the snippet WordPress attaches to a registered script — not
 any `<script>`
you put into a post. And a script that builds a further script while the page runs(`
document.createElement('script')`) loads in any case: the address it assembles exists
only in the browser, and the plugin never sees it. This route is measured and open;
it was the same in earlier versions.

**It stores no consent of individual visitors.** No server-side log, no IP
 address,
no visitor identifier. The duty to demonstrate consent is met through the configuration
archive: it records which services, purposes and texts were served at which point
in time. The guidance of the German data protection authorities for providers of
digital services states in para. 84 that demonstrating consent does not require 
long-lived identifiers.

**It is not legal advice.** Whether your website meets the requirements with
 this
plugin depends on which services you use and how you describe them. The plugin provides
the technology; the substantive accuracy of the entries and the legal assessment
remain with you.

## Screenshots

[⌊The banner as a first-time visitor sees it. Every category names the services 
behind it, with the provider; "Reject all" carries the same weight as "Accept all".⌉⌊
The banner as a first-time visitor sees it. Every category names the services behind
it, with the provider; "Reject all" carries the same weight as "Accept all".⌉[

The banner as a first-time visitor sees it. Every category names the services behind
it, with the provider; “Reject all” carries the same weight as “Accept all”.

[⌊The guided setup. A script the plugin does not recognise is not guessed at - it
is handed to you with its origin, the pages it turned up on, and a category to choose.⌉⌊
The guided setup. A script the plugin does not recognise is not guessed at - it 
is handed to you with its origin, the pages it turned up on, and a category to choose
.⌉[

The guided setup. A script the plugin does not recognise is not guessed at – it 
is handed to you with its origin, the pages it turned up on, and a category to choose.

[⌊One service in the list: provider, purpose, storage period, third-country transfer
and the safeguard it rests on, plus the cookie names and script handles that are
blocked and deleted on withdrawal.⌉⌊One service in the list: provider, purpose, 
storage period, third-country transfer and the safeguard it rests on, plus the cookie
names and script handles that are blocked and deleted on withdrawal.⌉[

One service in the list: provider, purpose, storage period, third-country transfer
and the safeguard it rests on, plus the cookie names and script handles that are
blocked and deleted on withdrawal.

[⌊The scan compares what your website loads with what your service list declares,
and says what is still open. It changes nothing by itself.⌉⌊The scan compares what
your website loads with what your service list declares, and says what is still 
open. It changes nothing by itself.⌉[

The scan compares what your website loads with what your service list declares, 
and says what is still open. It changes nothing by itself.

[⌊The cookie declaration on the website, from the [dt_consent_cookies] shortcode.
It is generated from the same service list - there is no second place to maintain.⌉⌊
The cookie declaration on the website, from the [dt_consent_cookies] shortcode. 
It is generated from the same service list - there is no second place to maintain
.⌉[

The cookie declaration on the website, from the `[dt_consent_cookies]` shortcode.
It is generated from the same service list – there is no second place to maintain.

## Blocks

This plugin provides 1 block.

 *   Cookie declaration

## Installation

 1. Copy the `dt-pm-consent` directory into `wp-content/plugins/`.
 2. Activate the plugin.
 3. Under “DT-PM Consent”, enter every service that sets cookies or transfers data 
    to third parties.
 4. Check the result: open the site in a private window and use the network tab to 
    confirm that no request goes to a third party before consent.

Step 4 is not optional. A consent banner whose blocking does not work is worse than
none — it documents that the obligation was known.

## FAQ

### How do I find the script handle of a service?

As a rule, no longer by hand: open “DT-PM Consent  Setup helper”, visit your
 site’s
front end while logged in, and come back. The scripts that loaded are listed there
with their handle and source.

If you do want to look it up yourself: in the page source the handle sits in
 the`
id` of the script tag, with `-js` appended. So

### Why does the page reload after a withdrawal?

Because a script that has already run cannot be unloaded again. It keeps
 listening
for events and would immediately set the deleted cookies anew. Only a fresh page
load, in which the scripts are never activated, actually enforces the withdrawal.

### Why can I not change the label of “Reject all”?

Because supervisory authorities regularly object to banners in which the
 rejection
has been renamed, hidden or removed altogether. The plugin therefore does not allow
that configuration.

### Do I lose the evidence archive when I uninstall?

Yes. Deleting the plugin removes all of its data, the archive included. If you
 
still need it for an ongoing or expected audit, back it up first.

### May I share consent across subdomains of a shared domain?

**Only if every subdomain is yours.** If you share the parent domain with
 other
people’s websites — typical for site-builder and hosting offers of the form `yourname.
provider.com` — please do not switch on “Valid on subdomains”.

The reason is a limit that cannot be closed technically: whoever can set
 cookies
on a neighbouring subdomain can also write a consent cookie for your site. Since
0.16.0 the plugin reliably detects that a cookie comes from a DIFFERENT installation
and rejects it. That does not help against deliberate forgery: the check value sits
in the source of every page and can be read from there. Only a server-side check
would be forgery-proof — and that cannot be reconciled with this plugin’s cache 
compatibility (see the next question).

With the setting switched off — the default — the problem does not arise.

### Does a withdrawal also delete cookies from neighbouring subdomains?

Possibly, yes — and that is a deliberate decision. Many tracking cookies,
 _ga from
Google Analytics among them, do not sit on your host but on the parent domain. Without
deleting there, a withdrawal would have no effect. Whether “the parent domain” is
yours alone cannot be decided without a constantly maintained list of every domain
suffix in the world.

The trade-off: either the withdrawal fails to delete what it is supposed to
 delete,
or on a shared domain someone else’s statistics lose a counter. The first would 
be a breach of the law, the second an annoyance. Your own consent cookie has not
been affected since 0.16.0 — a neighbour’s decision is no longer deleted along with
it.

### Why do I see an empty area instead of a notice when JavaScript is off?

Since 0.19.0 the server only renders a blocked embed harmless; the visible
 notice
and its button are built by the plugin script in the browser.

The reason is the safety of the blocking itself: as long as the server
 assembled
the placeholder, it carried over the remaining attributes of the original embed —
and two routes arose along which an embed kept loading inside the placeholder. The
server now outputs no foreign attribute at all.

Without JavaScript nobody can consent anyway; the button had no effect there
 before
either. Nothing loads without JavaScript — the blocking does not depend on the script.

### Why is an embed blocked although no third party appears in it?

This concerns embeds that carry their content in the `srcdoc` attribute. If
 there
is a `<script>` inside, the plugin blocks — even when no known provider is recognisable.
A script can load anything when it runs, and the plugin cannot judge what. In case
of doubt it does not allow it.

That is the only place where more is blocked on purpose than might be
 necessary.
A `srcdoc` without outward references is left alone.

### Does the plugin work with caching plugins?

Yes, and that is measured rather than merely argued. The HTML served is
 identical
for every visitor; the decision about consent is made exclusively in the browser.

Tested against a real page cache on Apache: a visitor without consent is
 served
exactly the page that was previously generated and cached for a consenting visitor—
and still loads no script that requires consent.

An upstream proxy cache (Varnish or Cloudflare, say) has not been measured. It
 
passes on the same HTML, so the statement holds there too — but it is not demonstrated
for it.

### Which cookie does DT-PM Consent set itself, and who provides the plugin?

One cookie, named `dt_consent`. It stores the visitor’s consent decision – which

categories were accepted – together with a fingerprint of the configuration, so 
that only the services consented to are loaded and the banner does not appear again
on every page. When the service or purpose list changes in substance, the fingerprint
no longer matches and the banner appears again.

It is kept for 365 days by default; the period can be changed on the “Banner”
 tab.
The plugin sets it in the visitor’s browser and sends it to no one: there is no 
transfer to a third party and none to a third country.

DT-PM Consent is provided by DT PM GmbH, Forckenbeckstr. 10, 48431 Rheine, Germany.

### Can I extend the plugin from my own code?

Yes, and without touching its files. Four hooks are documented and will not
 change
their names:

 * `dt_consent_service_catalogue` (filter) adds your own service to the built-in
   
   catalogue, so the plugin recognises it like any other.
 * `dt_consent_scan_report` (action) hands you every finished scan report, for
    
   your own monitoring or ticket system.
 * `dt_consent_configuration_archived` (action) hands you every configuration
    that
   went into the evidence archive, for your own records.
 * `dt_consent_banner_classes` (filter) adds a CSS class to the banner, so a
    theme
   can style it without copying markup.

The content of the banner is deliberately not filterable: both buttons, the
 purposes
and their order are what this software is measured against.

### How do I style the banner with my own CSS?

Add your rules to your theme or to a custom-CSS field. The banner uses the
 classes`
dtc-banner` (the overlay), `dtc-banner__inner` (the box) and dtc-button (both level-
one buttons). The filter dt_consent_banner_classes adds a class of your own to the
banner, so you can target your site without copying any markup.

**Since 1.0.10 a plain class is no longer enough.** The plugin’s own rules
 repeat
their class four times, so

    ```
    .dtc-button { background: #123456; }
    ```

will not take effect. Use the same specificity:

    ```
    .dtc-button.dtc-button.dtc-button.dtc-button { background: #123456; }
    ```

The reason is measured, not theoretical: some themes raise the specificity of
 their
own button rules above a plain class, and on those themes none of this plugin’s 
buttons showed the colour the plugin sets – not the two level-one buttons, not the
save button, not the revoke entry that sits on every page. Repeating the class is
what wins against that pattern. It is not a guarantee against every theme, and a
theme using `!important` still wins.

**Whatever you change, change it for both level-one buttons.** “Accept all”
 and“
Reject all” share one class on purpose. Supervisory authorities treat a prominent
accept button next to a quiet reject button as unlawful influence (DSK guidance,
para. 60), and this plugin is built so that there is no place where only one of 
the two can be coloured. A rule that singles one of them out defeats that, and it
is your installation that has to answer for it.

The save button (`dtc-button--quiet`) is deliberately quieter. It confirms a
 selection
you have already made; it is not a third alternative to accepting and rejecting,
so the equivalence requirement does not apply to it.

### Why does the cookie declaration name DT PM GmbH?

Because the plugin sets the `dt_consent` cookie on your site, and a visitor is
 
entitled to know who is behind a cookie (Art. 13 GDPR). The cookie declaration therefore
lists DT-PM Consent like any other service, and the provider line names the company
that provides the plugin.

This is information about a cookie, not a credit. It is plain text: no link, no

logo, no promotional wording. It appears only where you place the cookie declaration(
the `[dt_consent_cookies]` shortcode or the block) – never in the banner, the footer
or anywhere else on your pages. It disappears when the plugin is deactivated, because
then the cookie is no longer set.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“DT-PM Consent” is open source software. The following people have contributed to
this plugin.

Contributors

 *   [ dtpm ](https://profiles.wordpress.org/dtpm/)

[Translate “DT-PM Consent” into your language.](https://translate.wordpress.org/projects/wp-plugins/dt-pm-consent)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/dt-pm-consent/), check
out the [SVN repository](https://plugins.svn.wordpress.org/dt-pm-consent/), or subscribe
to the [development log](https://plugins.trac.wordpress.org/log/dt-pm-consent/) 
by [RSS](https://plugins.trac.wordpress.org/log/dt-pm-consent/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 1.1.4

**Housekeeping after the first round of the WordPress.org review.** Nothing you

have configured is touched: your services, texts and record archive stay as they
are.

 * **A snippet of your own can no longer break the page.** Where a necessary
    service
   carries its own snippet, a closing script tag inside it – which several providers’
   installation instructions include – used to end the tag early, and the rest of
   it landed in the page as markup, banner included. The snippet is now written 
   so that cannot happen, on every WordPress version this plugin supports.
 * **The check for third-party fonts now looks in the right places.** Where a
    site
   keeps its plugins or themes outside `wp-content`, style files there were not 
   examined at all, and the check reported nothing found. It now resolves those 
   directories too.
 * The page address the collector records is cleaned before it is stored, and
    the
   service fields that take one entry per line – script handles, script and iframe
   hosts – now drop an entry that cannot be one instead of storing it.
 * Two internal names got a longer prefix so they cannot collide with another
    plugin’s.
   One of them is a cache; it refills by itself.

#### 1.1.3

 * **Housekeeping for the WordPress.org listing.** The plugin’s text domain is
    
   now `dt-pm-consent`, matching the slug the directory assigned. Nothing about 
   the plugin’s behaviour changes, and nothing you have configured is touched: your
   services, texts and record archive are stored under names that stay as they are,
   and the `[dt_consent_cookies]` shortcode and the cookie declaration block keep
   working in the pages you already published.

#### 1.1.2

 * **The overview no longer sends you to a page where there is nothing to
    do.
    
   It said “14 findings from the last scan are not assigned to any
    service” and
   offered “Go to setup”; the setup then said “Nothing open: every finding assigned”–
   and finishing it led back to the overview with the same 14. The overview was 
   counting from the scan report, which is frozen at the moment of the scan, while
   the setup counts today’s state. Assigning a finding changes the second and not
   the first, so the number only ever cleared by running another scan. Both screens
   now read the same source: what is open today. The scan report still says what
   a scan found – it no longer says what is still open.
 * **A third party that blocking cannot reach is now named on its own, as a
    note.
   
   It used to be counted into the number above, which sent you off to
    assign it–
   the one thing that does not help: assigned, it would stand in the banner as if
   it were handled and keep loading. It is not a task either, because the fix is
   to change how the script is loaded, and that is often not yours to do. So the
   overview says it, the scan page lists it per host, and neither pretends you have
   something to tick off.

#### 1.1.1

 * **The destination-country field no longer shows an internal marker.** Where
    
   a provider says nothing about transfers, the field was printing keine-angabe –
   a German word on an English screen, and a token that means nothing to a reader.
   It is empty now, and the placeholder says what belongs there. The banner and 
   the record export already put it into a sentence; only this field did not. Nothing
   about blocking changes, and no entry of yours is altered.
 * The same field is wide enough for its own hint now. It stood at the
    browser’s
   default of about twenty characters, so “Destination country, e.g. USA” was cut
   off – which nobody saw while the field was never empty.

Older entries of this changelog have moved to `changelog.txt` in the plugin
 folder.

## Meta

 *  Version **1.1.4**
 *  Last updated **17 hours ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.2 or higher **
 *  Tested up to **7.1.4**
 *  PHP version ** 7.4 or higher **
 * Tags
 * [consent](https://wordpress.org/plugins/tags/consent/)[cookies](https://wordpress.org/plugins/tags/cookies/)
   [dsgvo](https://wordpress.org/plugins/tags/dsgvo/)[GDPR](https://wordpress.org/plugins/tags/gdpr/)
   [tdddg](https://wordpress.org/plugins/tags/tdddg/)
 *  [Advanced View](https://wordpress.org/plugins/dt-pm-consent/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/dt-pm-consent/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/dt-pm-consent/reviews/)

## Contributors

 *   [ dtpm ](https://profiles.wordpress.org/dtpm/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/dt-pm-consent/)