cookieowl

The key ring

cookieowl API reference

Every option, attribute, method and event of the cookie consent script, with Consent Mode, auto blocking, styling and the React and Vue helpers. One key for every door in town.

Quick start

Two ways in. The script tag defines a global cookieowl and starts on its own; the npm package exports the same instance.

index.html
<script src="https://cdn.jsdelivr.net/npm/cookieowl@0.1.0/dist/cookieowl.js"
  data-lang="auto" data-policy-url="/privacy"></script>
consent.js
import { cookieowl } from 'cookieowl';

cookieowl.init({
  lang: 'auto',
  policyUrl: '/privacy',
  version: '2026-10',
  consentMode: true,
  autoBlock: true,
  onConsent(record) {
    navigator.sendBeacon('/api/consent', JSON.stringify(record));
  },
});

if (cookieowl.accepted('analytics')) startAnalytics();
cookieowl.on('change', ({ accepted }) => console.log(accepted));

Options

Pass them to cookieowl.init(), or set window.cookieowlConfig before the script tag.

OptionTypeDefaultWhat it does
categories(string | Category)[]['necessary', 'preferences', 'analytics', 'marketing']Category ids or objects with label, description, required and services. necessary is always added and always on.
langstring'auto'Banner language: pt-BR, en, es, fr or de. auto reads <html lang>, then the browser.
template'lgpd' | 'gdpr'lgpd for Portuguese, gdpr otherwiseLegal wording of the banner and the preferences dialog.
policyUrlstringnoneLink to your privacy or cookie policy, shown in the banner and the dialog.
versionstring | number1Your policy version. Changing it shows the banner to everyone again.
expiresDaysnumber365Days until a choice expires and the banner asks again.
storage'cookie' | 'localStorage' | 'memory''cookie'Where the record is kept. memory forgets on reload (handy for demos and tests).
cookie{ name, domain, path, sameSite }{ name: 'cookieowl', path: '/', sameSite: 'Lax' }Cookie options. Set domain to share consent across subdomains.
layout'box' | 'bar' | 'modal''box'Corner box, full width bar or centered modal with a focus trap.
position'bottom' | 'top' | 'bottom-left' | 'bottom-right''bottom-right' (box), 'bottom' (bar)Where the banner sits.
theme'auto' | 'light' | 'dark''auto'auto follows data-theme or a .dark class on the page, then the system setting.
dir'auto' | 'ltr' | 'rtl''auto'Text direction; auto follows <html dir>.
reopenButtonboolean | 'left' | 'right'true (left)The floating owl button that reopens the preferences.
containerHTMLElement | stringdocument.bodyMount inside an element; the UI is then positioned inside it.
textPartial<Texts>built inOverride any text, as a string or one string per language.
consentModeboolean | ConsentModeConfigfalseGoogle Consent Mode v2: waitForUpdate, mapping, regions, adsDataRedaction, urlPassthrough, advanced.
autoBlockboolean | AutoBlockConfigfalseHold known trackers by URL: patterns, categories, ignore.
respectGPCbooleantrueTreat Global Privacy Control as a refusal of optional categories.
respectDNTbooleanfalseTreat Do Not Track the same way.
clearCookiesbooleantrueErase the cookies of withdrawn categories.
reloadOnWithdrawboolean | (categories) => voidtrueReload when a category whose scripts already ran is withdrawn, or handle it yourself.
autoShowbooleantrueShow the banner on init when there is no valid choice.
onConsent(record) => voidnoneCalled with the record on every choice. Send it to your audit log.

Script tag attributes

The most common options also work as data attributes on the script tag. They win over window.cookieowlConfig.

AttributeSame as
data-langlang
data-templatetemplate
data-policy-urlpolicyUrl
data-versionversion
data-categoriescategories, comma separated
data-layoutlayout
data-positionposition
data-themetheme
data-dirdir
data-storagestorage
data-expires-daysexpiresDays
data-containercontainer (a selector)
data-consent-modeconsentMode: true, or "advanced"
data-auto-blockautoBlock: true
data-gpc="false"respectGPC: false
data-dntrespectDNT: true
data-reopenreopenButton: "false", "left" or "right"
data-manualSkip the automatic init and call cookieowl.init() yourself

Blocking markup

Any element with data-cookieowl waits for its categories. List several to require all of them.

markup.html
<script type="text/plain" data-cookieowl="analytics" src="/stats.js"></script>
<script type="text/plain" data-cookieowl="analytics marketing">trackBoth();</script>
<script type="text/plain" data-cookieowl="analytics" data-cookieowl-type="module" src="/app-stats.mjs"></script>
<iframe data-cookieowl="marketing" data-cookieowl-name="YouTube"
  data-cookieowl-src="https://www.youtube-nocookie.com/embed/ID" width="560" height="315"></iframe>
<img data-cookieowl="marketing" data-cookieowl-src="https://ads.example.com/pixel.gif" alt="">
<a href="#" data-cookieowl-open>Cookie settings</a>
  • type="text/plain" keeps a script inert; the original type goes in data-cookieowl-type (for example module).
  • data-cookieowl-src holds the URL of an iframe, image or script until consent.
  • data-cookieowl-name names an embed in its placeholder.
  • data-cookieowl-open on any element opens the preferences on click.

Methods

MethodWhat it does
init(config)Starts cookieowl and returns the instance. Consent Mode defaults and the blocker are installed at once, the UI when the DOM is ready. Calling it again replaces the configuration.
accepted(category)True when the category (or every category in an array) is accepted. Required categories are always true.
acceptAll()Accepts every category and records method accept-all.
rejectAll()Keeps only required categories and records method reject-all.
save(choices)Saves a map like { analytics: true } or a list of accepted ids.
getConsent()A copy of the stored record, or null before a choice.
categories()The configured categories with their labels in the current language.
show() / hide()Shows or hides the banner without recording a choice.
showPreferences() / hidePreferences()Opens or closes the preferences dialog.
reset()Forgets the choice, turns optional categories off and shows the banner again.
on(event, fn)Listens to an event and returns a function that stops listening.
off(event, fn)Stops listening.
destroy()Removes the UI, the observers and the createElement hook.

Events

Listen with cookieowl.on(), or on document as cookieowl:change, cookieowl:consent and so on. With a dataLayer on the page, each choice also pushes a cookieowl_consent event for Tag Manager.

EventDetailWhen
change{ categories, accepted, changed, record }A category was accepted or withdrawn.
consentConsentRecordThe visitor made a choice (also when nothing changed).
ready{ categories, accepted, changed, record }init finished; the state comes from a stored choice or the defaults.
show / hide'banner' | 'preferences'The banner or the dialog opened or closed.
resetundefinedreset() was called.
events.js
const off = cookieowl.on('change', ({ categories, changed }) => {
  if (changed.includes('marketing') && !categories.marketing) removeAdSlots();
});

document.addEventListener('cookieowl:consent', (e) => console.log(e.detail.method));

Auto blocking

Known trackers and their default categories. Add your own with autoBlock.patterns.

IdNameCategory
gtagGoogle Analyticsanalytics
gtmGoogle Tag Manageranalytics
google-adsGoogle Adsmarketing
meta-pixelMeta Pixelmarketing
clarityMicrosoft Clarityanalytics
hotjarHotjaranalytics
linkedin-insightLinkedIn Insight Tagmarketing
tiktok-pixelTikTok Pixelmarketing
youtubeYouTubemarketing
youtube-apiYouTubemarketing
vimeoVimeomarketing
auto-block.js
cookieowl.init({
  autoBlock: {
    patterns: [{ id: 'chat', name: 'Support chat', category: 'preferences', match: /widget\.chat\.example/ }],
    categories: { gtm: 'marketing' },
    ignore: ['hotjar'],
  },
});

The consent record

types.ts
interface ConsentRecord {
  id: string;          // random, kept across updates
  version: string;     // your policy version
  timestamp: string;   // ISO 8601
  expires: string;     // ISO 8601
  categories: Record<string, boolean>;
  method: 'accept-all' | 'reject-all' | 'custom' | 'signal';
  signal?: 'gpc' | 'dnt';
  lang: string;
  page: string;
}

Styling

The stylesheet is scoped under .cko and injected once. Override the tokens on .cko or set --seed on :root.

VariableUse
--seedAccent color of the buttons and switches (amber by default). The same variable themes Monsoon, so one color can theme both.
--cko-fontFont family of the banner and dialog.
--cko-bg, --cko-fg, --cko-mutedSurface, text and secondary text colors.
--cko-line, --cko-softBorders and subtle backgrounds.
--cko-primary, --cko-on-primaryButton color and the text on it (contrast picked automatically).
--cko-ringFocus ring color.
theme.css
:root { --seed: #2f6fed; }
.cko { --cko-font: Inter, sans-serif; }
.cko-btn { border-radius: 999px; }

React and Next.js

cookieowl/react exports useConsent(category?), ConsentGate and useCookieOwl().

Footer.tsx
import { ConsentGate, useConsent, useCookieOwl } from 'cookieowl/react';

function Footer() {
  const owl = useCookieOwl();
  const all = useConsent(); // { necessary: true, analytics: false, ... }
  return <button onClick={() => owl.showPreferences()}>Cookie settings</button>;
}

Vue

cookieowl/vue exports CookieOwlPlugin, useConsent(category) and ConsentGate with a fallback slot.

Video.vue
<script setup>
import { useConsent } from 'cookieowl/vue';
const analytics = useConsent('analytics');
</script>

<template>
  <ConsentGate category="marketing">
    <iframe src="https://player.vimeo.com/video/123" title="Video" />
    <template #fallback>Video hidden until marketing cookies are allowed.</template>
  </ConsentGate>
  <p v-if="analytics">Thanks for helping us improve the site.</p>
</template>

Hoot suggests

Nothing here. Hoot looked under every cookie jar.