326 lines
8.2 KiB
Markdown
326 lines
8.2 KiB
Markdown
# @pdntechnology/cookie-consent
|
|
|
|
[](LICENSE)
|
|
[](https://www.npmjs.com/package/@pdntechnology/cookie-consent)
|
|
|
|
A lightweight, open-source **Consent Management Platform (CMP)** for React and Next.js that implements [Google Consent Mode v2](https://developers.google.com/tag-platform/security/guides/consent) 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:
|
|
|
|
1. Set **denied** defaults **before** any Google tag loads
|
|
2. Load GTM / gtag.js
|
|
3. Show a consent banner
|
|
4. On user choice → `gtag('consent', 'update', …)` + dataLayer event
|
|
5. When ads are denied → enable `ads_data_redaction` and `url_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_passthrough` when 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
|
|
|
|
```bash
|
|
npm install @pdntechnology/cookie-consent
|
|
```
|
|
|
|
### Next.js setup
|
|
|
|
Add to `next.config.mjs`:
|
|
|
|
```js
|
|
const nextConfig = {
|
|
transpilePackages: ["@pdntechnology/cookie-consent"],
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
## Quick start
|
|
|
|
### 1. Configure (optional)
|
|
|
|
```js
|
|
// 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)
|
|
|
|
```jsx
|
|
// 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
|
|
|
|
```jsx
|
|
// 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)
|
|
|
|
```jsx
|
|
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: true`
|
|
- `url_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)
|
|
|
|
```html
|
|
<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:
|
|
|
|
```js
|
|
import { getConsentBootstrapScript } from "@pdntechnology/cookie-consent";
|
|
console.log(getConsentBootstrapScript());
|
|
```
|
|
|
|
---
|
|
|
|
## GTM integration checklist
|
|
|
|
1. Enable **Consent Mode** in your GTM container settings
|
|
2. Configure GA4 / Google Ads tags to require appropriate consent signals
|
|
3. Optional: create a trigger on custom event `cookie_consent_update`
|
|
4. Test with [Tag Assistant](https://tagassistant.google.com/)
|
|
|
|
---
|
|
|
|
## Regional defaults (EEA example)
|
|
|
|
```js
|
|
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)
|
|
|
|
```bash
|
|
# In this repo
|
|
cd cookie-consent
|
|
npm link
|
|
|
|
# In your Next.js app
|
|
npm link @pdntechnology/cookie-consent
|
|
```
|
|
|
|
Or use a file dependency:
|
|
|
|
```json
|
|
{
|
|
"dependencies": {
|
|
"@pdntechnology/cookie-consent": "file:../cookie-consent"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Publishing to npm
|
|
|
|
```bash
|
|
npm login
|
|
npm publish --access public
|
|
```
|
|
|
|
---
|
|
|
|
## Contributing
|
|
|
|
Contributions are welcome. Please open an issue before large changes.
|
|
|
|
1. Fork the repository
|
|
2. Create a feature branch
|
|
3. Submit a pull request
|
|
|
|
---
|
|
|
|
## License
|
|
|
|
[MIT](LICENSE) © [PDN Technology](https://pdntechnology.com)
|