Go to file
Pdn Technology 9a001197e1
Some checks are pending
CI / test (20) (push) Waiting to run
CI / test (22) (push) Waiting to run
Tema ayarları eklendi
2026-06-20 08:58:11 +03:00
.github/workflows Tema ayarları eklendi 2026-06-20 08:58:11 +03:00
examples/next-app Tema ayarları eklendi 2026-06-20 08:58:11 +03:00
src Tema ayarları eklendi 2026-06-20 08:58:11 +03:00
.gitignore Tema ayarları eklendi 2026-06-20 08:58:11 +03:00
.npmignore first commit 2026-06-20 08:47:21 +03:00
CHANGELOG.md Tema ayarları eklendi 2026-06-20 08:58:11 +03:00
CONTRIBUTING.md Tema ayarları eklendi 2026-06-20 08:58:11 +03:00
LICENSE first commit 2026-06-20 08:47:21 +03:00
package-lock.json Tema ayarları eklendi 2026-06-20 08:58:11 +03:00
package.json Tema ayarları eklendi 2026-06-20 08:58:11 +03:00
README.md Tema ayarları eklendi 2026-06-20 08:58:11 +03:00
README.tr.md Tema ayarları eklendi 2026-06-20 08:58:11 +03:00
vitest.config.js Tema ayarları eklendi 2026-06-20 08:58:11 +03:00

@pdntechnology/cookie-consent

License: MIT npm version

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:

  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
  • Customizable banner text, theme colors, and cookie inventory
  • ads_data_redaction + url_passthrough in bootstrap and on update
  • 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 for core API and React components
  • Error callbacks when consent cannot be saved

Turkish documentation: README.tr.md


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.

// app/layout.jsx
import "@pdntechnology/cookie-consent/styles.css";
import "@/lib/consent-config";
import { ConsentBootstrap } from "@pdntechnology/cookie-consent/react";

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" />
    </>
  );
}
import { openPreferences } from "@pdntechnology/cookie-consent";

<button type="button" onClick={openPreferences}>
  Cookie settings
</button>

Customization

Text and policy URL

Every visible string can be overridden via the labels prop. The policy link uses policyHref.

<CookieConsent
  policyHref="/privacy"
  labels={{
    title: "Cookie preferences",
    message: "We use cookies to improve your experience.",
    policyLink: "Privacy policy",
    accept: "Accept all",
    reject: "Reject all",
    manage: "Manage preferences",
    save: "Save preferences",
    necessaryTitle: "Necessary",
    necessaryDescription: "Required for core site functionality.",
    analyticsTitle: "Analytics",
    analyticsDescription: "Google Analytics (_ga, _gid).",
    marketingTitle: "Marketing",
    marketingDescription: "Google Ads and Meta Pixel.",
    alwaysOn: "Always on",
    storageError: "Your preferences could not be saved. Please try again.",
  }}
/>
Label key Default
title Cookie preferences
message We use cookies to improve your experience…
policyLink Privacy policy
accept Accept all
reject Reject all
manage Manage preferences
save Save preferences
necessaryTitle Necessary
necessaryDescription Required for core site functionality…
analyticsTitle Analytics
analyticsDescription Helps us understand how visitors use the site…
marketingTitle Marketing
marketingDescription Used for ads and remarketing…
alwaysOn Always on
cookiesHeading View cookies
cookieName Name
cookiePurpose Purpose
cookieDuration Duration
cookieProvider Provider
storageError Your preferences could not be saved…

Theme colors

Pass a theme object to override CSS variables without writing custom CSS:

<CookieConsent
  theme={{
    background: "rgba(15, 23, 42, 0.97)",
    text: "#f8fafc",
    textMuted: "rgba(248, 250, 252, 0.82)",
    link: "#93c5fd",
    primary: "#2563eb",
    primaryText: "#ffffff",
    secondaryBackground: "rgba(255, 255, 255, 0.1)",
    border: "rgba(255, 255, 255, 0.14)",
    accent: "#2563eb",
  }}
/>

You can also pass className for additional styling hooks.

Provide a cookies array to show an expandable table inside each category in the preferences panel:

<CookieConsent
  cookies={[
    {
      category: "necessary",
      name: "my_site_consent",
      purpose: "Stores your consent choice",
      duration: "1 year",
      provider: "This site",
    },
    {
      category: "analytics",
      name: "_ga",
      purpose: "Visitor statistics",
      duration: "2 years",
      provider: "Google Analytics",
    },
  ]}
/>

If cookies is omitted, the banner keeps the simpler three-category view.

Error handling

Consent write functions return a result object:

const result = acceptAll();
if (!result.ok) {
  console.error(result.reason); // "invalid" | "storage"
}

In React, use callbacks on the banner:

<CookieConsent
  onConsentSaved={(consent) => console.log("saved", consent)}
  onConsentError={({ reason }) => console.warn("failed", reason)}
/>

Enable debug: true in configureConsent() to log warnings to the console, or use onStorageError for global handling.


Example app

See examples/next-app for a working Next.js demo with Turkish labels, custom theme colors, and a cookie inventory table.

cd examples/next-app
npm install
npm run dev

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, …
├── cookie-schema.js         Cookie inventory helpers
├── 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
    ├── CookieList.jsx
    ├── theme.js
    ├── GoogleTagManager.jsx
    └── FacebookPixel.jsx

API reference

Configuration

Function Description
configureConsent(config) Set storage key, wait time, region defaults
getConsentConfig() Read active configuration
Function Description
getConsent() Read stored preferences
setConsent({ analytics, marketing }) Save custom choice; returns { ok, consent | reason }
acceptAll() Grant all categories; returns { ok, consent | reason }
rejectAll() Deny optional categories; returns { ok, consent | reason }
hasAnalyticsConsent() Check analytics opt-in
hasMarketingConsent() Check marketing opt-in
openPreferences() Re-open banner panel
syncConsentFromStorage() Re-apply stored consent after GTM loads
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)

CookieConsent props

Prop Type Description
labels object Override banner text
theme object Override banner colors
cookies CookieEntry[] Optional cookie inventory table
policyHref string Privacy / cookie policy URL
LinkComponent component Custom link component (default: Next.js Link)
className string Extra CSS class on the banner root
onConsentSaved (consent) => void Called after a successful save
onConsentError ({ reason }) => void Called when save fails

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

  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

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",
    },
  ],
});

Troubleshooting

Problem Likely cause Fix
Banner never appears Consent already stored Clear localStorage key or call openPreferences()
GTM fires before consent Bootstrap missing or loaded too late Add <ConsentBootstrap /> with beforeInteractive before GTM
Consent not saved Storage blocked (private mode, Safari ITP) Handle onConsentError; show inline error from banner
Tags still fire after reject GTM tags not using Consent Mode Enable Consent Mode in GTM and set tag consent requirements
TypeScript errors on ./react Missing types path Import from @pdntechnology/cookie-consent/react (types included since v1.1)

# 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

See CONTRIBUTING.md. Bug reports and pull requests are welcome.


License

MIT © PDN Technology