| src | ||
| .gitignore | ||
| .npmignore | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
@pdntechnology/cookie-consent
A lightweight, open-source Consent Management Platform (CMP) for React and Next.js that implements Google Consent Mode v2 the same way certified tools do.
No heavy dependencies. No vendor lock-in. Works with Google Tag Manager, GA4, Google Ads, and Meta Pixel.
Why this exists
Google-certified CMPs (Cookiebot, OneTrust, CookieYes, …) follow the same technical flow:
- Set denied defaults before any Google tag loads
- Load GTM / gtag.js
- Show a consent banner
- On user choice →
gtag('consent', 'update', …)+ dataLayer event - When ads are denied → enable
ads_data_redactionandurl_passthrough
This library implements that flow in ~15 KB of readable JavaScript.
Note: Certified CMPs additionally provide IAB TCF v2.2 signals and appear on Google's certified vendor list. This library covers the Consent Mode v2 technical integration. You are responsible for privacy policy text and legal compliance.
Features
- Google Consent Mode v2 (all 7 signals)
- Granular categories: Necessary / Analytics / Marketing
ads_data_redaction+url_passthroughwhen marketing is denied- Regional default consent (EEA, etc.)
- React banner + Next.js bootstrap component
- Optional GTM and Meta Pixel loaders (consent-gated)
- Framework-agnostic core API (vanilla JS supported)
- TypeScript definitions included
Installation
npm install @pdntechnology/cookie-consent
Next.js setup
Add to next.config.mjs:
const nextConfig = {
transpilePackages: ["@pdntechnology/cookie-consent"],
};
Quick start
1. Configure (optional)
// lib/consent-config.js
import { configureConsent } from "@pdntechnology/cookie-consent";
configureConsent({
storageKey: "my_site_consent", // localStorage key
waitForUpdateMs: 500, // time GTM waits for consent update
adsDataRedaction: true, // Google recommendation when ads denied
urlPassthrough: true, // pass click IDs in URL when cookies denied
debug: false,
});
Import this file in your root layout before ConsentBootstrap.
2. Bootstrap consent defaults (before GTM)
// app/layout.jsx
import "@pdntechnology/cookie-consent/styles.css";
import "@/lib/consent-config";
import ConsentBootstrap from "@pdntechnology/cookie-consent/react/ConsentBootstrap";
export default function RootLayout({ children }) {
return (
<html>
<body>
<ConsentBootstrap />
{children}
</body>
</html>
);
}
3. Banner + tags
// app/providers.jsx
import {
CookieConsent,
GoogleTagManager,
FacebookPixel,
} from "@pdntechnology/cookie-consent/react";
export function Providers({ children }) {
return (
<>
{children}
<CookieConsent
policyHref="/privacy"
labels={{
accept: "Accept all",
reject: "Reject all",
manage: "Manage preferences",
}}
/>
<GoogleTagManager gtmId="GTM-XXXXXXX" />
<FacebookPixel pixelId="123456789" />
</>
);
}
4. Re-open preferences (footer link)
import { openPreferences } from "@pdntechnology/cookie-consent";
<button type="button" onClick={openPreferences}>
Cookie settings
</button>
How categories map to Google signals
| Banner category | User choice | Google Consent Mode signals |
|---|---|---|
| Necessary | Always on | security_storage: granted |
| Analytics | Opt-in | analytics_storage |
| Marketing | Opt-in | ad_storage, ad_user_data, ad_personalization, functionality_storage, personalization_storage |
When marketing is denied, the library also sets:
ads_data_redaction: trueurl_passthrough: true
Project structure
src/
├── index.js Public API
├── config.js configureConsent()
├── constants.js Events, signal names
├── preferences.js Parse / serialize user choices
├── storage.js localStorage read/write
├── consent-api.js acceptAll, rejectAll, getConsent, …
├── google/
│ ├── gtag.js dataLayer helpers
│ ├── consent-signals.js Category → signal mapping
│ ├── consent-lifecycle.js default + update calls
│ └── bootstrap-script.js Inline <head> script generator
└── react/
├── ConsentBootstrap.jsx
├── CookieConsent.jsx
├── GoogleTagManager.jsx
└── FacebookPixel.jsx
API reference
Configuration
| Function | Description |
|---|---|
configureConsent(config) |
Set storage key, wait time, region defaults |
getConsentConfig() |
Read active configuration |
User consent
| Function | Description |
|---|---|
getConsent() |
Read stored preferences |
setConsent({ analytics, marketing }) |
Save custom choice |
acceptAll() |
Grant all categories |
rejectAll() |
Deny optional categories |
hasAnalyticsConsent() |
Check analytics opt-in |
hasMarketingConsent() |
Check marketing opt-in |
openPreferences() |
Re-open banner panel |
syncConsentFromStorage() |
Re-apply stored consent after GTM loads |
Google Consent Mode
| Function | Description |
|---|---|
getConsentBootstrapScript() |
Inline script for vanilla HTML |
applyConsentDefaults() |
Set denied defaults programmatically |
applyConsentUpdate(consent) |
Push user choice to gtag |
buildGoogleConsentState(consent) |
Get signal object |
Events
| Constant | Fired when |
|---|---|
EVENT_CONSENT_UPDATED |
User saves a choice |
EVENT_OPEN_PREFERENCES |
Preferences panel should open |
GTM_CONSENT_EVENT |
Pushed to dataLayer (cookie_consent_update) |
Legacy aliases (getCookieConsent, acceptAllCookies, …) remain available.
Vanilla HTML (no React)
<head>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('consent', 'default', {
ad_storage: 'denied',
analytics_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied',
functionality_storage: 'denied',
personalization_storage: 'denied',
security_storage: 'granted',
wait_for_update: 500
});
</script>
<!-- GTM snippet here -->
</head>
Or generate the script programmatically:
import { getConsentBootstrapScript } from "@pdntechnology/cookie-consent";
console.log(getConsentBootstrapScript());
GTM integration checklist
- Enable Consent Mode in your GTM container settings
- Configure GA4 / Google Ads tags to require appropriate consent signals
- Optional: create a trigger on custom event
cookie_consent_update - Test with Tag Assistant
Regional defaults (EEA example)
configureConsent({
regionDefaults: [
{
regions: ["AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR",
"DE", "GR", "HU", "IE", "IT", "LV", "LT", "LU", "MT", "NL",
"PL", "PT", "RO", "SK", "SI", "ES", "SE", "IS", "LI", "NO"],
ad_storage: "denied",
analytics_storage: "denied",
ad_user_data: "denied",
ad_personalization: "denied",
},
],
});
Local development (link to another project)
# In this repo
cd cookie-consent
npm link
# In your Next.js app
npm link @pdntechnology/cookie-consent
Or use a file dependency:
{
"dependencies": {
"@pdntechnology/cookie-consent": "file:../cookie-consent"
}
}
Publishing to npm
npm login
npm publish --access public
Contributing
Contributions are welcome. Please open an issue before large changes.
- Fork the repository
- Create a feature branch
- Submit a pull request