Releases: ConsentTheater/playbill
v0.5.0
The catalogue grows to 10,550 entries (4,160 cookies + 6,390 domains, 2,998 unique companies) from a live-scan gap-filling pass over major SaaS, martech, e-commerce, and consumer sites. This release adds 39 new cookie/domain signatures, removes one dangerously over-broad pattern, and corrects two corrupted attributions.
Added
B2B visitor identification / lead scoring
snitcher_device_id— Snitchermkjs_user_id/mkjs_group_id/mkjs_anonymous_id— MadKuduwc_visitor/wc_client/wc_client_current/wc_swap— WhatConverts
Marketing attribution
flaretrk— Attributer__ps_r/__ps_sr/__ps_lu/__ps_slu/__ps_fva/__ps_did— Podscribe (podcast-ad attribution)partnero_*— Partnero (affiliate / referral)
Advertising
_uetmsclkid— Microsoft Ads UET click ID_twpid— X / Twitter PixelIR_*— Impact.com_yjsu_yjad— Yahoo Japan Ads
Analytics / experimentation
optimizelySession— Optimizelysc_is_visitor_unique— StatCountertk_ai_explat/explat_*— Automattic ExPlat
Session recording
QuantumMetricSessionID/QuantumMetricUserID— Quantum Metric
Security
aws-waf-token— AWS WAF bot-control challenge token
Consent / CMP & functional
- TrustArc cookies:
TAsessionID,notice_preferences,notice_gdpr_prefs,cmapi_gtm_bl,cmapi_cookie_privacy ccpa_applies,sensitive_pixel_option(s)_wixUIDX— Wix
Data-leak
avatars.githubusercontent.com— GitHub/Microsoft avatar CDN (exposes viewer IP; Gravatar analog)
Changed
- Repository references now point to Codeberg — active development moved there; GitHub is a read-only mirror.
- Minimum Node version raised to 24.
Fixed
- Corrected two corrupted Awin attributions (
AwinChannelCookie,lantern) where thecompanyandlifetimefields had been swapped during an earlier import (companyread"29 days",lifetimeread"Awin").
Removed
- Over-broad
aw*cookie pattern that matched any cookie beginning withawand mislabelled it as Awin advertising (required_strict). It was swallowing unrelated AWS cookies such asaws-waf-token. The legitimate Awin click cookieawcretains its own exact-match entry, so no real coverage is lost.
Install: npm install @consenttheater/playbill@0.5.0
Full changelog: https://codeberg.org/ConsentTheater/playbill/compare/v0.4.0...v0.5.0
v0.4.0
Highlights
Catalogue grew from 8,664 to 10,504 entries (+21%, +1,842). Cookies nearly
doubled (2,340 → 4,119, +76%). 71 long-standing cross-file company-mismatch
attributions reported by normalize.js are zeroed out. A focused re-
classification moved 413 confident ad-tech entries (DSPs, SSPs, DMPs,
retargeting networks) from marketing to advertising with consent_burden
upgraded to required_strict.
Data — new entries
- 1,794 new cookies + 131 new domains across
analytics,marketing,
functional, andsecurity. See Acknowledgements below for the
upstream community source we want to credit. - ShortPixel image-optimisation CDN:
shortpixel.ai,cdn.shortpixel.ai,
shortpixel.io,shortpixel.com,api.shortpixel.com
(functional/minimal).
Data — cross-file company-mismatch cleanup
71 cases of the same cookie/domain key attributed to different companies
across actor files resolved across four root causes:
- 4 self-name-vs-domain — entries had
companyset to a domain string
(e.g.Branch.io,Split.io) instead of the proper company name.
Domain-named entries removed. - 8 known-related — subsidiary / parent / rebrand pairs (Salesforce
DMP/Krux, Atlassian/Loom, Block/Afterpay, etc.). Canonical attribution
kept; redundant entries removed. - 40 name-format-diff — same company under slightly different formats
(HeapvsHeap (Contentsquare),AdjustvsAdjust (AppLovin),
OpenStreetMapvsOpenStreetMap Foundation, etc.). Pure category
disputes — kept the entry in the most accurate category. - 19 distinct-company — real attribution conflicts including
misattributed cookies:_fs_uidwas attributed to "FullSession" but is
actually FullStory;_lr_env_src_atsto LogRocket but is actually
LiveRamp ATS;csrftokento Meta but is actually Django;match.prod .bidr.ioto RhythmOne but is actually Beeswax (Comcast);_lr_env_src _atsto LogRocket but is LiveRamp ATS;prebid.adnxs.comre-attributed
to advertising/Xandr (Microsoft) instead of fingerprinting;top.mail .rure-attributed to analytics/MyTracker;addtl_consentand
usprivacyre-attributed to consent (IAB-managed signals) rather than
generic functional.
Data — ad-tech re-routing
413 entries moved from marketing.json → advertising.json with
consent_burden upgraded to required_strict. Affected vendors include
Nexx360, Epsilon, Outbrain, Adform, Yieldmo, Equativ (formerly Smart
AdServer), Adhese, Sonobi, Groovinads, Magnite (formerly Rubicon Project),
Smaato, Perfect Audience, Teads, ID5, PubMatic, Platform161, Ortec,
Seedtag, Lotame, Zeotap, MediaMath, OpenX, Admatic, MediaVine, Audrte,
Acuity, Emetric, 33Across, Atlas, Tappx, Xandr, richAudience, LiveRamp,
JustPremium, LiveIntent, Underdog Media, TripleLift, plus single-entry
confident-ad-tech entries (Snapchat ads, RTB House, Pangle, Vidoomy,
Roku ad-sync, Demandbase, Tapad, ComScore, etc.).
Mixed-type companies (Adobe, Microsoft, Google, Meta, Facebook, LinkedIn,
HubSpot/Clearbit) deliberately NOT included — their entries span both
categories and need entry-by-entry review in a future pass.
Compatibility
No API changes. Two semantic shifts that downstream consumers will
notice:
- 413 entries that previously appeared in
marketingrollups now appear
inadvertising. Consumers filtering bycategory === 'marketing'will
see fewer results;advertisinggrows by the same amount. The new
marketingset is closer to its label — email/SMS/push, CRM
automation, lead capture, loyalty programmes — without the ad-tech
noise. - Those same 413 entries had
consent_burden: 'required'and now have
consent_burden: 'required_strict'. UIs that bucket consent burden
into display levels will see those entries shift up one level. The new
burden reflects the GDPR posture of these vendors more accurately —
the old categorisation was a default applied during earlier bulk
import passes, not editorial intent.
Acknowledgements
Catalogue informed by
jkwakman/Open-Cookie-Database
(Apache-2.0 — with thanks). Their community-maintained cookie catalogue
contributed 1,794 new cookie + 131 new domain entries to our database in
this release. Their 5-category schema was mapped into our 11-category +
consent_burden model, descriptions were retained where accurate, and
941 entries already in our DB were deduplicated. Open-Cookie-Database is
a separate project under different governance — we recommend it directly
to anyone who wants the raw upstream catalogue. Without that work, this
release would have been substantially smaller.
Full Changelog: v0.3.0...v0.4.0
v0.3.0
Highlights
This release is a data-quality pass driven by ten end-to-end scans of major B2B
SaaS sites (HubSpot, Salesforce, Adobe, 6sense, Demandbase, ZoomInfo, Clearbit,
Notion, Linear, Airtable, monday.com, ClickUp, Loom, Gong, Mutiny). Every change
below is a real misattribution or omission observed in production traffic, not
speculative cleanup.
Tooling
scripts/normalize.jsnow detects cross-file collisions. When the same
cookie name or domain key appears in two or more actor files, the script
reports each occurrence with file name, attributed company, category, and
consent burden — and explicitly marksCOMPANY MISMATCHcases as bugs. The
alphabetical merge order inloadPlaybill()means later files silently
overwrite earlier ones, which had been hiding wrong attributions for
high-traffic vendors. The check ran on the existing data and surfaced 109
cookie + 344 domain collisions as a backlog for future passes.
Data — wrong attributions corrected
_dd_s→ Datadog Browser SDK (was DataDome bot protection). Two
different vendors with confusingly similar_dd_*prefixes._dd_sis the
primary session cookie of the Datadog RUM agent; DataDome's persistent cookie
isdatadomeand its test cookies use_dd_cookie_test_*. Category moves
fromsecurity/contestedtoanalytics/required— every site running
Datadog RUM was previously mis-audited as running bot protection._gd_session/_gd_svisitor/_gd_visitor→ 6sense Visitor ID (was
"Google Analytics Debug" /minimal). Confirmed across 6sense's own site,
Airtable, Gong, and others — the cookie value matches thesvisitor=
parameter onb.6sc.cobeacons in the same scan window. New burden:
required_strict. The_gd_visitorshort variant added._ttp→ TikTok Pixel (was Kakao Pixel)._ttpis TikTok's primary
pixel cookie; Kakao uses_kp_clk/_kawlt. Burden upgraded to
required_strict.cb_user_id/cb_group_id/cb_anonymous_id→ HubSpot (Clearbit)
Reveal (was Cxense via an over-greedycb_*pattern). The pattern is
deleted; explicit Clearbit entries take its place. Cxense (Piano DMP) uses
cX_*(capital X), notcb_.ar_debug→ Pinterest Conversion Tag (was Google). The Chrome
Attribution Reporting API debug cookie is set per-advertiser by their pixel,
not by Google directly; the canonical setter is Pinterest's tag.cg_uuid,greencolumnart.com→ CHEQ AI Technologies (was
"GreenColumnArt", categoryadvertising).greencolumnart.comis a CHEQ
cloak domain (thech=cheq4ppcURL marker is the tell). Category moved to
fingerprinting/required_strict. CHEQ rotates per-tenant cloak domains
(obs.<random>,ob.<random>) explicitly to evade tracker blocklists, so
the entry includes a note about path signatures (/ct,/mon,
/tracker/tc_imp.gif,/i/<hex>.js) for matcher-side detection.a.usbrowserspeed.com,usbrowserspeed.com→ Experian (Tapad)
Cross-Device Identity (was New Relic Browser Speed Test, plus a separate
USBrowserSpeed cookie attribution). Same cloak pattern as CHEQ — the URL
itself containspurpose=Retargeting + ID Resolution, which New Relic
doesn't do. Tapad was acquired by Experian in 2020. Category moved to
fingerprinting/required_strict.px.ads.linkedin.com→ LinkedIn (Microsoft) Insight Tag (was Roku /
DataXu / Roku OneView). DataXu's real domains arew55c.netand
dxlive.com; this entry was simply wrong.laboratory-anonymous-id→ HubSpot Laboratory (was "Various / Lab/Testing
Tools"). HubSpot's internal A/B testing framework.bb_*over-greedy Blackboard pattern removed. It was matching every
cookie starting withbb_as Blackboard LMS, including monday.com's
internal cookies. No replacement — the correct fix for the surfacing
cookies needs site-by-site investigation, and a wrong attribution is worse
than no attribution.
Data — cross-file duplicates resolved
The losing entry was deleted in each pair so the merger picks the better
attribution. Notable cases:
snap.licdn.com(kept advertising / "LinkedIn Insight Tag", deleted social)alb.reddit.com(added bare hostname under advertising / Reddit Pixel —
was previously only matched associal/contestedvia a wrong entry that
understated the consent burden of conversion pixels)fast.wistia.com(3-way collision: kept data_leak, deleted analytics + social)tag.demandbase.com(kept analytics / "Demandbase ABM" with reverse-IP note,
deleted marketing)secure.adnxs.com(kept fingerprinting, deleted advertising)js-agent.newrelic.com(default agent reclassified asanalytics/required
RUM, notsession_recording/contested— replay is a separately-licensed
feature using/replay/paths which retain their entry)
Data — new entries
Cookies (previously unmatched in production scans):
_dd_s,dd_anonymous_id(Datadog Browser SDK)_biz_uid,_biz_nA,_biz_pendingA,_biz_flagsA(Adobe / Bizible / Marketo Measure)pxcts,_pxde(HUMAN / PerimeterX bot defense — extends the existing family)_zitok(ZoomInfo WebSights first-party visitor token)ttcsid,ttcsid_*(TikTok Conversion Source ID)dicbo_id(Outbrain click ID)__q_state_*(Qualified Conversational Sales — pattern with workspace hash)Indr*(Unify base64-encoded workspace-prefixed cookie variants)mutiny.user.*(Mutiny B2B website personalization — reverse-IP firmographic)tracking-preferences(Twilio Segment consent storage)g_state(Google Sign-In / GSI state)tcm(Transcend Consent Manager)cookiehub(CookieHub CMP)hubspot_id_sent(HubSpot internal flag)cloudfront_viewer_country(AWS CloudFront geo header echoed to cookie)sequelUserId,sequelSessionId,sequel-consent(Sequel.io B2B virtual events)atlCohort,atl_session,atl_xid.current,atl_xid.ts,atlUserHash,
__Host-psifi.*(Atlassian cross-product tracking — covers Loom, Trello,
and other Atlassian-acquired properties)_otPreferencesSynced,ovtc_*(OneTrust virtual tag capture for SPA
navigation re-evaluation)
Domains:
www.google.com/ccm/collect,/rmkt/collect,/pagead/1p-user-list,
/pagead/1p-conversion,/gmp/conversion— Google Ads first-party endpoints
used as consent-mode workarounds. Each carries a note explaining the
1p-naming and the role in the Privacy Sandbox transition.pagead2.googlesyndication.com/ccm/collect— Google Customer Match Connect
(correctly distinguished from AdSense, which is the bare-hostname entry).fls.doubleclick.net— Floodlight conversion tracking (subdomain match
catches per-advertiser hosts like14611606.fls.doubleclick.net).sgtm-amer.hubspot.com,sgtm-emea.hubspot.com,sgtm-apac.hubspot.com—
HubSpot's hosted server-side GTM proxies, used to tunnel GA4 hits through
HubSpot's first-party domain.
Notes
- The
munchkin.marketo.netentry now documents that Marketo's bundled JS
ships JavaScript errors (which can include form values, URL params, and
DOM content) to Adobe's Sentry tenanto209747.ingest.us.sentry.io—
observed across multiple Marketo customer sites including Adobe's own
business.adobe.com, Airtable, and Gong. This is invisible to most
privacy reviews and worth surfacing in audit reports. - Several reverse-IP firmographic vendors (6sense, Demandbase, ZoomInfo,
Clearbit, Mutiny, Leadfeeder/Dealfront) carry notes about their legal
posture: company-level identification from IP creates GDPR-personal data
even on sites with no consent banner. - The matcher itself was not changed in this release. A separate
urlParamPatternmatching feature (for detecting enrichment vendors via
GA4up.db_*/up.*_6siuser-property leaks) is on the backlog.
Compatibility
No breaking API changes. Two semantic changes that downstream consumers may
notice:
_dd_s-using sites will now appear inanalytics/requiredrollups instead
ofsecurity/contested. If you bucket consent-burden levels into UI bands,
this will shift Datadog deployments from "minimal concern" toward "consent
required" — which matches reality.- The
bb_*andcb_*pattern removals mean cookies that previously matched
via these patterns will now returnnullfrommatchCookie(). If any
consumer relied on the old (wrong) attributions, those calls now correctly
surface as unmatched. Affected real-world cookies were re-attributed where
the actual vendor was identifiable (Clearbit'scb_*family), or left
unmatched where it wasn't (bb_visitor_id).
Full Changelog: v0.2.0...v0.3.0
v0.2.0 — Reframed around consent burden, scorer
Breaking changes
This release reframes Playbill from a judgement library into an evidence library. Two renames and one removal — see
CHANGELOG.md for the full migration recipe.
severity → consent_burden
Every cookie and domain entry now carries a consent_burden field describing what the tracker actually demands under GDPR /
ePrivacy, instead of a school-grade severity label.
Old (severity) |
New (consent_burden) |
|---|---|
critical |
required_strict |
high |
required |
medium |
contested |
low |
minimal |
Same shape, same number of levels — only the names change. Migration is a search-and-replace.
scorer module removed
computeScore(), bandForScore(), SEVERITY_WEIGHTS, BANDS, and the related types (ScoreInput, ObservedItem,
ObservedBanner, ScoreResult, Violation, Band, BandKey) are gone. The ./scorer subpath export is removed from
package.json.
Whether a site complies with GDPR is the work of supervisory authorities and courts — not a library. Compute presentation
hierarchies (red/amber/green, "high risk" badges, etc.) in your own UI layer from consent_burden and category. A few lines is
all it takes.
Type exports
- Removed:
Severity,Band,BandKey,Violation,ScoreResult,ScoreInput,ObservedItem,ObservedBanner - Added:
ConsentBurden - Unchanged:
Playbill,CookieActor,DomainActor,CookieMatch,DomainMatch,Tier,Category
Migration
- import { computeScore, bandForScore } from '@consenttheater/playbill';
+ // Compute your own ranking from match.consent_burden / match.category
- if (match.severity === 'critical') ...
+ if (match.consent_burden === 'required_strict') ...
- type S = Severity;
+ type S = ConsentBurden;If you previously used computeScore() for a banner-style verdict, the simplest replacement is a one-off function in your own
codebase that takes the array of matches and returns whatever shape your UI expects.
Internal
- playbill.version bumped 2 → 3 (in-memory database format, distinct from the package version).
- scripts/normalize.js recognises consent_burden as a meta key when scanning for duplicate entry keys.
Install
npm install @consenttheater/playbill@0.2.0
Full Changelog: https://github.com/ConsentTheater/playbill/compare/v0.1.2...v0.2.0
v0.1.2 — Apollo, Warmly, Vibe + HubSpot regional umbrellas
Adds 8 new entries across 5 actor categories:
Umbrella root domains (catch regional CDN variants via subdomain match):
hs-analytics.net(analytics) — HubSpot analytics.js loader (js-eu1, js-na1, ...)hsforms.com(marketing) — HubSpot Forms embed (forms-na1, perf-na1, ...)apollo.io(analytics) — Apollo.io B2B prospecting subdomains
New actors:
aplo-evnt.com(analytics, high) — Apollo.io event collectorgetwarmly.com(analytics, critical) — Warmly reverse-IP deanonymizationhubspotusercontent-na1.net(functional, low) — HubSpot CMS CDNt.vibe.co(advertising, critical) — Vibe CTV ad trackingwww.google.com(data_leak, medium) — Google cross-site endpoint (reCAPTCHA, Fonts, OAuth, Maps)
Total entries: 8608 → 8615.
v0.1.1 — HubSpot regional CDN coverage
Adds umbrella root-domain entries so regional HubSpot CDNs (eu1, na1, au1, etc.) get caught via subdomain matching:
hs-scripts.com(tag_manager) — catchesjs-eu1.*,js-na1.*, etc.hubspot.com(analytics) — catchestrack-eu1.*,api-eu1.*, including the__ptq.giftracking pixel.hs-banner.com(marketing) — HubSpot cookie banner loader. The loader itself fingerprints visitors (viewport, language, referrer) before the UI renders — this happens pre-consent.
v0.1.0 — initial release
First publish of @consenttheater/playbill — an open-source, tiered knowledge base of GDPR-relevant web trackers, with pure-function matching and risk-scoring utilities.
What's in the box
- 11 actor categories — advertising, analytics, marketing, functional, social, session recording, data leaks, security, consent, fingerprinting, tag managers. 2,800+ companies, tens of thousands of cookie and domain signatures.
loadPlaybill('mini' | 'core' | 'full')— runtime-filtered tiers. No pre-generated tier files; one source of truth.matchCookie/matchDomain— pure matchers with pattern and subdomain support.computeScore()— risk scoring intocompliant/at_risk/non_compliant/violating, aligned with Austrian DPA 2022 and LG München rulings on third-party IP exposure.- Subpath exports — pull only what you need, e.g.
import x from '@consenttheater/playbill/actors/advertising'. - TypeScript types included. Node ≥ 22.
Who it's for
Cookie banner auditors, CMPs, browser extensions, CI compliance scanners, privacy research — anyone who needs "is this a tracker, and how bad is it" as a library, not a closed SaaS.
License
AGPL-3.0-or-later. The whole point is that the tracker knowledge stays open.