cookie-consent/README.md
Pdn Technology 48cabcf293 first commit
2026-06-20 08:47:21 +03:00

326 lines
8.2 KiB
Markdown

# @pdntechnology/cookie-consent
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![npm version](https://img.shields.io/npm/v/@pdntechnology/cookie-consent.svg)](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)