npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

consent-mode-v2-adapter

v0.1.0

Published

Tiny wiring helper for Google Consent Mode v2: default-denied gtag with EEA region filter, granular update from your banner of choice. Works with vanilla-cookieconsent, Klaro, Cookiebot, custom UI, or no UI at all. Apache 2.0.

Downloads

126

Readme

consent-mode-v2-adapter

Tiny wiring helper for Google Consent Mode v2: default-denied gtag with EEA region filter, granular update from your banner of choice. Works with vanilla-cookieconsent, Klaro, Cookiebot CMP, custom UI, or no UI at all (e.g. server-rendered preferences page).

Banner-agnostic. Pure data + 4 functions. No DOM, no CSS, no a11y burden.

Apache 2.0. ~250 LOC. Zero required dependencies.

Why this exists

Google made Consent Mode v2 mandatory for AdSense + Ads measurement in March 2024. The contract is two-step:

  1. Push gtag('consent', 'default', { ad_storage: 'denied', ... }) before any tag fires.
  2. Push gtag('consent', 'update', { ... }) with granular state when the user accepts.

Most cookie banner libraries handle step 0 (the UI) but skip the wiring. This package does only the wiring. Pair it with the banner you already use, or call directly from a preferences form.

60-second wiring

With any banner library (vanilla pattern)

npm install consent-mode-v2-adapter
import { setDefaultConsent, updateConsent } from 'consent-mode-v2-adapter';

// On page load, before GTM/GA4 fires any tag:
setDefaultConsent();

// When the user accepts categories (from your banner's onAccept callback,
// or from a preferences form submit):
updateConsent({
  analytics: true,        // grants analytics_storage
  marketing: true,        // grants ad_storage + ad_user_data + ad_personalization
  functionality: false,   // denies functionality_storage
  personalization: false, // denies personalization_storage
});

That's it. Default state is denied for the 6 user-driven *_storage signals (security_storage stays granted per Google policy). EEA + UK + EFTA region filter applied by default; pass null to apply globally.

With vanilla-cookieconsent (orestbida)

npm install consent-mode-v2-adapter vanilla-cookieconsent
import * as CookieConsent from 'vanilla-cookieconsent';
import 'vanilla-cookieconsent/dist/cookieconsent.css';
import { setDefaultConsent, defaultCategories, translations } from 'consent-mode-v2-adapter';
import { wireVanillaCookieConsent } from 'consent-mode-v2-adapter/adapters/vanilla-cookieconsent';

setDefaultConsent();

const update = () => wireVanillaCookieConsent(CookieConsent);

CookieConsent.run({
  categories: defaultCategories,
  language: { default: 'it', translations },
  onConsent: update,
  onChange: update,
});

defaultCategories ships GDPR-aligned 4-category preset (necessary, analytics, marketing, preferences) with autoClear patterns for GA4 (_ga*, _gid), Google Ads (_gcl_*), Meta (_fbp, _fbc, IDE). Override per stack as needed.

translations.it and translations.en provide ready text for the consent + preferences modals.

With Klaro / Cookiebot CMP / custom UI

Same shape: call setDefaultConsent() on load, call updateConsent({ analytics, marketing, ... }) when your banner reports the user's choice. The library doesn't care which banner emitted the event.

Public API

import {
  setDefaultConsent,
  updateConsent,
  buildConsentUpdatePayload,
  EEA_REGIONS,
  defaultCategories,
  buildCategories,
  translations,
} from 'consent-mode-v2-adapter';

| Export | Purpose | |---|---| | setDefaultConsent({ regions?, waitForUpdate? }) | Push gtag('consent','default', ...). Call once on page load before GTM. | | updateConsent({ analytics, marketing, functionality, personalization }) | Push gtag('consent','update', ...) with granular state. | | buildConsentUpdatePayload(accepted) | Pure function; build the payload without pushing. Useful for server-rendered preferences pages that need to emit the same shape elsewhere. | | EEA_REGIONS | string[] of 32 ISO codes (EU + UK + Switzerland + EFTA). Default region filter for setDefaultConsent. | | defaultCategories | GDPR-aligned 4-category preset (data only). | | buildCategories(overrides) | Merge overrides onto the preset. | | translations | { en: {...}, it: {...} } ready text packs. |

Adapter subpath:

import { wireVanillaCookieConsent } from 'consent-mode-v2-adapter/adapters/vanilla-cookieconsent';

What this is NOT

  • Not a cookie banner. Bring your own UI.
  • Not a CMP. No IAB TCF v2.2 signal. Use vanilla-cookieconsent's IAB plugin alongside if you need TCF.
  • Not opinionated about your tracker. No GTM/GA4 IDs in the package. Configure your own container.
  • Not a fork of vanilla-cookieconsent. The adapter is a 60-LOC bridge to its API; install it as a peer dep if you use the bridge.

Templates (compliance copy)

Pre-written GDPR + ePrivacy text in templates/:

  • cookie-policy-it.md | Italian cookie notice (Garante 2021 aligned), placeholder-driven
  • cookie-policy-en.md | English cookie notice (GDPR + ePrivacy)
  • privacy-policy-snippet-it.md | Cookie section to paste into existing privacy policy
  • privacy-policy-snippet-en.md | same in English

Always validate with privacy counsel for your specific case.

Region filter

Default behavior of setDefaultConsent(): deny all *_storage signals only for traffic from EEA + UK + Switzerland + EFTA (32 ISO codes in EEA_REGIONS). Non-EU traffic falls back to whatever defaults your tag server-side has configured. This avoids breaking attribution for global campaigns where consent rules differ.

// Default: EEA-only denial
setDefaultConsent();

// Apply globally (no region filter)
setDefaultConsent({ regions: null });

// Custom subset (e.g. US states with consent laws)
setDefaultConsent({ regions: ['CA', 'CO', 'CT', 'VA'] });

gtag stub for delayed-load GTM

If window.gtag is not defined when setDefaultConsent() runs (common when GTM is loaded after first user interaction to keep it off the LCP critical path), the library installs a tiny stub that pushes args onto window.dataLayer. The real gtag drains the queue on load, so consent signals are replayed in order. No special configuration needed.

Maintenance scope

Single-maintainer secondary asset, scoped intentionally. See SECURITY.md for vulnerability disclosure and CONTRIBUTING.md for PR process + commit-message contract.

License

Apache License 2.0. See NOTICE for third-party attributions (only the optional vanilla-cookieconsent adapter; the core library has zero runtime deps).