Comply DP

Docs

Consent Manager

How to put the banner on a site, gate tags, and turn on the age gate.

Where it lives

Open Consent Manager from the dashboard. It has four screens: Install, Configure, Cookie scan, and Consent logs. Everything on those screens belongs to the entity selected in the header. Every member of that entity sees the same site, scans, and logs.

What you install

There is no package to install from npm. The site loads one script from consent.complydp.com. That script sets Google Consent Mode to denied for ads and analytics, fetches this site’s settings, shows the banner, and later turns tags on only for categories the visitor allowed. Replace YOUR_SITE_ID with the id from Install.

Plain HTML

Put the loader in the head, before analytics or marketing tags. The defer attribute keeps it from blocking the first paint, and the script still registers Consent Mode before those tags run.

index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Example</title>
    <script src="https://consent.complydp.com/v1/loader.js?site_id=YOUR_SITE_ID" defer></script>
  </head>
  <body>
    <!-- page -->
  </body>
</html>

Next.js (App Router)

Load the script with next/script and strategy beforeInteractive so it runs before the rest of the app. Put it in the root layout, once.

app/layout.tsx
import Script from "next/script"

const LOADER =
  "https://consent.complydp.com/v1/loader.js?site_id=YOUR_SITE_ID"

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        <Script src={LOADER} strategy="beforeInteractive" />
        {children}
      </body>
    </html>
  )
}

WordPress

There is no WordPress plugin. Add the script from the theme so it prints in the head of every public page. Priority 1 keeps it ahead of most other tags. Do not also paste the script in a header plugin.

functions.php
add_action('wp_head', function () {
  if (is_admin()) {
    return;
  }
  echo '<script src="https://consent.complydp.com/v1/loader.js?site_id=YOUR_SITE_ID" defer></script>';
}, 1);

Create the site first

  1. Sign in and select the right entity.
  2. Open Consent Manager → Install.
  3. Enter the domain shoppers type in the browser, such as brand.com, and choose Create site.
  4. Copy the Site ID into the script above. The Install page also shows the tag already filled in.

Shopify

Do not paste the script into theme.liquid if you use the app. The theme embed injects the same loader. Installing the ComplyDP app does not turn the banner on by itself.

  1. Install the ComplyDP app on the store and link this organisation.
  2. Create the consent site with the storefront domain and copy the Site ID.
  3. In Shopify admin, open Online Store → Themes → Customize → App embeds.
  4. Turn on ComplyDP consent banner, paste the Site ID, and save.
  5. Open the storefront in a private window and confirm the banner appears.

The embed also writes the choice into Shopify’s Customer Privacy API, so Shopify’s own pixels follow it. Install, Configure, the scan, and the logs stay on complydp.com.

Stop tags that ignore the banner

The loader records the choice and updates Google Consent Mode (ad_storage, analytics_storage, ad_user_data, ad_personalization). A script tag with a normal src still downloads immediately. For Meta, LinkedIn, PostHog, and similar tags, change the tag so the loader can turn it on after that category is granted. Categories are necessary, functional, analytics, and marketing. Necessary is always on.

Gated marketing tag
<!-- Runs immediately. Do not ship this. -->
<script src="https://snap.licdn.com/li.lms-analytics/insight.min.js"></script>

<!-- Runs only after marketing is allowed. -->
<script
  type="text/plain"
  data-category="marketing"
  src="https://snap.licdn.com/li.lms-analytics/insight.min.js"
></script>
Gated analytics tag
<script
  type="text/plain"
  data-category="analytics"
  src="https://example.com/analytics.js"
></script>

Age gate

The age gate is configured in Consent Manager → Configure, on the Age gate card. Turn on Show age-gate popup, write the question in Default copy, choose an audience mode, and choose Save age gate. No extra script is required. The same loader reads the setting.

The question is a self-declaration, not an identity check. The buttons are fixed: I am 18 or older, and I am under 18. The threshold stored for the site is 18, which matches the DPDP definition of a child. The sentence you type is the question above those buttons. If you add copy for a language, the loader picks the page language (the html lang attribute, then the browser language), then the language without the region, then default.

While the question is on screen, ads and analytics stay denied and only necessary cookies are allowed. The answer is stored in a first-party cookie named complydp_age_band for 180 days. Closing the dialog without answering is stored as unknown. The consent log for that visitor includes the age band: adult, minor, or unknown.

  • General or mixed: an adult continues to the normal banner and can allow functional, analytics, and marketing. A minor, or someone who dismisses the question, stays on necessary cookies only. Ads and analytics remain denied.
  • Child-directed: the site stays on necessary cookies only, including when the visitor says they are 18 or older.
  • The loader does not treat mixed differently from general. Child-directed is the mode that never opens the full banner.

Configure is where you turn the popup on, edit the question, and pick the audience mode. You do not add another script. When the site also has a guardian handoff URL, a minor (or every visitor on a child-directed site) stays on a second overlay: “A parent or guardian can continue”, with a link to that URL. The link is given site_id, visitor_id, and age_band. Dismissing the question does not open that link. Turning the age gate off skips the question and the lock.

Name a logged-in user

Link logged-in users is off until you enable it on Install. Your server mints a short-lived HS256 JWT and the page passes it to the loader after login. Claims: sub (your user id), iss (the site id), aud complydp, exp, and jti. Optional emh is HMAC-SHA256 of the identity secret and the lowercased trimmed email. Old logs stay anonymous. On logout call unidentify.

Node: mint the token
const crypto = require("crypto")
const jwt = require("jsonwebtoken")

function complydpToken(user) {
  const email = user.email.trim().toLowerCase()
  const emh = crypto
    .createHmac("sha256", process.env.COMPLYDP_IDENTITY_SECRET)
    .update(email)
    .digest("hex")
  return jwt.sign(
    { emh },
    process.env.COMPLYDP_IDENTITY_SECRET,
    {
      subject: String(user.id),
      issuer: process.env.COMPLYDP_SITE_ID,
      audience: "complydp",
      expiresIn: "15m",
      jwtid: crypto.randomUUID(),
    },
  )
}
Browser: after login and on logout
ComplyDP.identify(token)
// later
ComplyDP.unidentify()

Configure, scan, and logs

  • Configure sets the banner title, description, colours, cookie categories, and the age gate. Save, then reload the site. You do not edit the theme again for wording or colours.
  • Cookie scan visits the domain and lists cookies so you can place them in a category.
  • Consent logs are the recorded choices, including the age band when the age gate is on.

Disconnect

Disconnect website removes the site from this entity so you can register another domain. The script already on the site keeps loading the banner. To stop the popup, remove that script. On Shopify, turn off the ComplyDP consent banner app embed.