DPO Radio

Black Friday: 50% off CMP annual plans for the first year! Use Code BF50

AesirX CMP - Standalone JS Developer Guide

AesirX CMP - Standalone JS Developer Guide

AesirX CMP - Standalone JS Developer Guide

Ship-ready reference for integrators using the standalone JavaScript build of AesirX CMP. Covers init/config, events, feature Opt‑In, vendor recipes (GA4, YouTube, Google Maps, Intercom), CSP guidance, QA checklists, and ISO/IEC 27560 mapping.

1. Getting Started

Include & Initialize

  1. Include the CMP bundle (self-hosted recommended)
copy icon
<script src="/assets/aesirx-consent.min.js" defer></script>
  1. Initialize AFTER the bundle has loaded
copy icon
<script>
  // Holdback definitions (executed after user consent)
  // There are 5 available categories:
  //   - essential
  //   - functional
  //   - analytics
  //   - advertising
  //   - custom
  //
  // "name" can be customized to describe your specific integration.
  window.aesirxHoldBackJS = [
    {
      category: "analytics",
      name: "Google Analytics",
      script: () => {
        // Load google analytics script
        console.log("analytics scripts");
      },
    },
    {
      category: "advertising",
      name: "Google Tag Manager",
      script: () => {
        // Load Google Tag Manager script
        console.log("Tag Manager scripts");
      },
    },
    // Add more vendor entries here...
  ];

  window.funcAfterConsent = () => {
    // These will load only after the user has given consent
    console.log("user consented");
  };

  window.funcAfterReject = () => {
    // These will load only after the user has reject consent
    console.log("user rejected consent");
  };
</script>

2. Events

All events are dispatched on window as CustomEvents.

Event NameDefines category for hold back js
aesirxHoldBackJSUser grants consent
funcAfterConsentUser withdraws consent
funcAfterRejectWhen it fires

3. Feature Opt‑In (per‑feature modal)

Use Opt‑In when a specific feature (e.g., payment, embedded map, video, chat) needs consent at the moment of use.

Global (vanilla JS)

copy icon
<button data-optin-open="payment">Enable payment</button>

<script>
  window.optInConsentData = [
    {
      title: "payment",
      content:
        "<div>We need consent to enable payment (explain vendor & purpose).</div>",
      handleAccept: async function () {
        // run payment feature logic here
      },
      handleReject: async function () {
        // run alert reject feature here
      },
      replaceAnalyticsConsent: false,
    },
  ];

  // Semantic trigger—no direct class toggles
  document.addEventListener("click", (e) => {
    const t = e.target.closest("[data-optin-open]");
    if (t)
      document.querySelector(".opt-in-consent.payment").classList.add("show");
  });
</script>

NextJS

Create a provider for Opt-In Consent

copy icon
import { createContext, useContext, useEffect, useState } from "react";
import dynamic from "next/dynamic";

const OptInConsent = dynamic(
  () => import("aesirx-consent").then((module) => module.OptInConsent),
  {
    ssr: false,
    loading: () => <></>,
  }
);
// Expose handleOpen + isConsentPayment for consumption anywhere in the app
const ConsentContext = createContext({
  handleOpen: undefined,
  isConsentPayment: false,
});
const ConsentContextProvider = ({ children }) => {
  return <ConsentContextApp>{children}</ConsentContextApp>;
};
const ConsentContextApp = ({ children }) => {
  const [showModal, setShowModal] = useState(false); // Controls if modal is visible
  const [isConsentPayment, setIsConsentPayment] = useState(false); // Track if user already consented
  /**
   * handleOpen()
   * - This function is used to trigger the opt-in modal.
   * - You can call this anywhere in your application using useConsentContext().
   */
  const handleOpen = () => {
    setShowModal(true);
  };
  /**
   * handleConsentPayment()
   * - Triggered when the user ACCEPTS the opt-in consent.
   * - Sets isConsentPayment to true and closes the modal.
   * - You can also persist the status here if needed.
   */
  const handleConsentPayment = () => {
    setIsConsentPayment(true);
    setShowModal(false);
  };
  /**
   * handleRejectPayment()
   * - Triggered when the user REJECTS consent.
   * - The modal is simply closed without applying consent.
   */
  const handleRejectPayment = () => {
    setShowModal(false);
  };
  /**
   * useEffect()
   * - Runs on first load of the page.
   * - Checks if payment consent was already granted during this session.
   * - If true → skip showing modal and treat as already consented.
   */
  useEffect(() => {
    if (sessionStorage.getItem("aesirx-analytics-optin-payment") === "true") {
      handleConsentPayment();
    }
  }, []);
  return (
    <ConsentContext.Provider
      value={{
        handleOpen,
        isConsentPayment,
      }}
    >
      <OptInConsent
        optInConsentData={[
          {
            title: "payment",
            content: `<div>YOUR_CONTENT_INPUT_HERE</div>`,
            show: showModal,
            handleConsent: handleConsentPayment,
            handleReject: handleRejectPayment,
          },
          // ... You can add more opt-in consent modals depending on your needs
        ]}
      />
      {children}
    </ConsentContext.Provider>
  );
};
const useConsentContext = () => useContext(ConsentContext);
export { ConsentContextProvider, useConsentContext };

To enable the opt-in consent modal globally in your application, you need to wrap your root component with ConsentContextProvider. This makes the consent state and the handleOpen() trigger function available anywhere in your app via useConsentContext().

copy icon
// Replace "path/to/ConsentContext" with the actual path to your file,
// for example: "@/context/ConsentContext" or "../context/ConsentContext"
import { ConsentContextProvider } from "path/to/ConsentContext";

<ConsentContextProvider>
 <Component {...pageProps} />
</ConsentContextProvider>

Trigger opt-in consent modal from a component

ReactJS

Create a provider for Opt-In Consent

copy icon
import { createContext, useContext, useEffect, useState } from "react";
import dynamic from "next/dynamic";

const OptInConsent = dynamic(
  () => import("aesirx-consent").then((module) => module.OptInConsent),
  {
    ssr: false,
    loading: () => <></>,
  }
);
// Expose handleOpen + isConsentPayment for consumption anywhere in the app
const ConsentContext = createContext({
  handleOpen: undefined,
  isConsentPayment: false,
});
const ConsentContextProvider = ({ children }) => {
  return <ConsentContextApp>{children}</ConsentContextApp>;
};
const ConsentContextApp = ({ children }) => {
  const [showModal, setShowModal] = useState(false); // Controls if modal is visible
  const [isConsentPayment, setIsConsentPayment] = useState(false); // Track if user already consented
  /**
   * handleOpen()
   * - This function is used to trigger the opt-in modal.
   * - You can call this anywhere in your application using useConsentContext().
   */
  const handleOpen = () => {
    setShowModal(true);
  };
  /**
   * handleConsentPayment()
   * - Triggered when the user ACCEPTS the opt-in consent.
   * - Sets isConsentPayment to true and closes the modal.
   * - You can also persist the status here if needed.
   */
  const handleConsentPayment = () => {
    setIsConsentPayment(true);
    setShowModal(false);
  };
  /**
   * handleRejectPayment()
   * - Triggered when the user REJECTS consent.
   * - The modal is simply closed without applying consent.
   */
  const handleRejectPayment = () => {
    setShowModal(false);
  };
  /**
   * useEffect()
   * - Runs on first load of the page.
   * - Checks if payment consent was already granted during this session.
   * - If true → skip showing modal and treat as already consented.
   */
  useEffect(() => {
    if (sessionStorage.getItem("aesirx-analytics-optin-payment") === "true") {
      handleConsentPayment();
    }
  }, []);
  return (
    <ConsentContext.Provider
      value={{
        handleOpen,
        isConsentPayment,
      }}
    >
      <OptInConsent
        optInConsentData={[
          {
            title: "payment",
            content: `<div>YOUR_CONTENT_INPUT_HERE</div>`,
            show: showModal,
            handleConsent: handleConsentPayment,
            handleReject: handleRejectPayment,
          },
          // ... You can add more opt-in consent modals depending on your needs
        ]}
      />
      {children}
    </ConsentContext.Provider>
  );
};
const useConsentContext = () => useContext(ConsentContext);
export { ConsentContextProvider, useConsentContext };

To enable the opt-in consent modal globally in your application, you need to wrap your app with ConsentContextProvider. This makes the consent state and the handleOpen() trigger function available anywhere in your app via useConsentContext().

  • If using CRA → index.js
  • If using Vite → main.jsx

Trigger opt-in consent modal from a component

copy icon
import { useConsentContext } from "path/to/ConsentContext";
const EnablePaymentButton = () => {
 const { handleOpen } = useConsentContext();

 return <button onClick={handleOpen}>Consent Payment</button>;
};

export default EnablePaymentButton;

4. Opt‑In Consent: End‑to‑End Example (Vanilla)

A minimal, production‑safe example showing a feature Opt‑In for payment with clear Accept/Reject flows and a semantic trigger.

copy icon
<!-- Trigger somewhere in your UI -->
<button data-optin-open="payment" class="btn">Enable payment</button>

<!-- Optional inline fallback (hidden by default) -->
<div data-feature-fallback="payment" hidden>
  Payment is unavailable until you provide consent.
</div>

<script>
  // 1) Define the Opt‑In item (as an ARRAY, not a string)
  window.optInConsentData = [
    {
      title: "payment",
      content:
        "<p>We use a third‑party payment provider. Accept to enable checkout.</p>",
      handleAccept: async function () {
        // Execute your payment bootstrap here
        initPaymentWidget();
      },
      handleReject: async function () {
        const fb = document.querySelector('[data-feature-fallback="payment"]');
        if (fb) fb.hidden = false;
      },
      replaceAnalyticsConsent: false,
    },
  ];

  // 2) Semantic trigger to open the Opt‑In
  document.addEventListener("click", (e) => {
    const t = e.target.closest("[data-optin-open]");
    if (t)
      document.querySelector(".opt-in-consent.payment").classList.add("show");
  });

  // Example payment bootstrap (replace with your real code)
  function initPaymentWidget() {
    if (window.__paymentLoaded) return;
    window.__paymentLoaded = true;
    const s = document.createElement("script");
    s.src = "https://payments.example.com/widget.js";
    s.async = true;
    if (window.__cspNonce) s.nonce = window.__cspNonce;
    document.head.appendChild(s);
  }
</script>

5.Vendor Recipes

Now that your CMP is installed and configured, you can start adding vendor integrations.

AesirX CMP Guide: How to Integrate Web Vendors (Top 25)

6. Content Security Policy (CSP)

Provide your users a working baseline:

copy icon
Content-Security-Policy:
      default-src 'self';
      script-src 'self' 'nonce-<server-nonce>' https://www.googletagmanager.com https://www.google-analytics.com https://www.youtube-nocookie.com https://widget.intercom.io;
      frame-src  'self' https://www.youtube-nocookie.com;
      connect-src 'self' https://region1.google-analytics.com https://api-iam.intercom.io https://nexus-websocket-a.intercom.io;
      img-src    'self' data: https://i.ytimg.com;
      style-src  'self' 'unsafe-inline'; /* or nonce your inline styles */

7. Accessibility & UX

  • Modal: role, aria-labelledby, aria-describedby, focus trap, ESC to close.
  • Keyboard path to Accept/Reject. No alert() for rejections; use inline fallbacks.
  • Clear purpose descriptions; no pre‑ticked toggles.
  • Respect GPC where required; reflect status in UI text.

8. Appendix - ISO/IEC 27560 Mapping (Consent Receipt)

AesirX CMP maintains first‑party consent logs compatible with 27560 fields. Typical record fields:

Field (ISO/IEC 27560) AesirX CMP Field / Note
Controller Identifier First‑party site/app identifier
Data Subject Identifier Pseudonymous session ID (no direct personal data)
Purpose(s) purposes map (essential, functional, analytics, advertising, custom)
Processing BasisConsent (granular)
Consent StatusGiven / Withdrawn / Updated
Timestampms since epoch
UI Version / Policy Hashversion + policy/notice hash (configurable)
SignalsGPC honored (boolean + region context)
Proof ArtifactsInternal log refs; optional ZKP receipt (future‑ready)

Export profile: Provide an exporter to output JSON/CSV for audits. (If using ZK proofs, store the proof receipt hash and reference to on‑chain anchor.)

10. Embedding in Popular CMS & Ecommerce (Generic)

The standalone bundle works anywhere you can inject HTML/JS. Prefer self‑hosting and add CSP nonces if your site uses a strict CSP.

WordPress (theme/site without plugin)

  • Where: header.php (or via a Code Snippets plugin) for bundle include; initialize in a small inline

Enjoyed this read? Share the blog!