---
url: https://docs.consentpro.com/changelog/core/v2.md
---
# consentpro-v2

## 2.6.8

### Patch Changes

* Updated dependencies \[e7b804d]
  * consentpro-utils@2.1.5
  * consentpro-dictionary@0.1.15

## 2.6.7

### Patch Changes

* f58f0bd: Prevent inactive Webflow consent forms from reaching delegated form handlers through jQuery events dispatched directly on the document. Preserve active preferences saving, ordinary site forms, and existing event hooks without adding a runtime dependency.
* Updated dependencies \[e73fae1]
  * consentpro-utils@2.1.4
  * consentpro-dictionary@0.1.14

## 2.6.6

### Patch Changes

* consentpro-dictionary@0.1.13
* consentpro-utils@2.1.3

## 2.6.5

### Patch Changes

* consentpro-dictionary@0.1.12
* consentpro-utils@2.1.3

## 2.6.4

### Patch Changes

* consentpro-dictionary@0.1.11
* consentpro-utils@2.1.3

## 2.6.3

### Patch Changes

* 8e14120: Debugger and preview links on Webflow (v2) installs now boot from a freshly fetched config instead of the inlined one, which can be a browser-cached copy from before the latest publish. A Webflow app debugger link shows the latest published config; a web-app preview link shows the saved config and stays in preview for the rest of the tab session, as it already did on core installs.
* bfd469d: Prevent native and jQuery-generated submissions from host-page consent preferences forms, including inactive banner instances, from reaching Webflow's delegated submission handler after the Webflow banner initializes. Keep active preferences saving through Consent Pro and leave ordinary Webflow forms unchanged.

## 2.6.2

### Patch Changes

* a8ee5ce: Generate unique IDs for category and provider accordion panels so each preferences trigger references its own panel through aria-controls.

## 2.6.1

### Patch Changes

* Updated dependencies \[3dc13a0]
  * consentpro-dictionary@0.1.10
  * consentpro-utils@2.1.3

## 2.6.0

### Minor Changes

* 9518dbb: Add Cookie Manager locale purposes and overlay them on preferences and cookie declaration after publish.

  Draft translations live in D1 (`config_tracker_translations`) and are not live on save. Publish writes a per-hostname R2 sibling at `translations/v2/...` and purges it with the runtime cache. Visitors fetch `GET /v3/cdn/translations/:siteId.json` only when opening preferences or hydrating the cookie declaration; banner blocking still uses the inlined purpose.

  **Production:** apply D1 migration `0049_flat_leper_queen` (`wrangler d1 migrations apply DB --env production --remote`) and confirm it with `wrangler d1 migrations list DB --env production --remote` before this Designer UI ships. `GET /v3/projects/:id/languages` has no fallback if `supported_languages` is missing.

### Patch Changes

* bb844a5: Add a **Corner style** option to banner styling for custom sites, switching the banner between its default, rounded and square corners.

  The web app's banner style step gains a Corner style picker, stored per banner as `corner_style` and published to the runtime as `style.cornerStyle`. The runtime maps it to the banner's radius tokens:

  | Corner style | Buttons & badges (`--consentpro-radius-sm`) | Surfaces (`--consentpro-radius-md`) |
  | ------------ | ------------------------------------------- | ----------------------------------- |
  | Default      | SDK default                                 | SDK default                         |
  | Rounded      | `999px` (pill)                              | `0.75rem`                           |
  | Square       | `0`                                         | `0`                                 |

  The field is optional. Banners without it, and every Webflow site, keep the SDK's own radii.

* bb844a5: Refetch the preview config when the visitor refreshes a preview page, so the latest unpublished changes show up. The debugger's own same-token navigations still reuse the loaded preview.

* Updated dependencies \[bb844a5]

* Updated dependencies \[c3fe401]
  * consentpro-utils@2.1.3
  * consentpro-dictionary@0.1.9

## 2.5.4

### Patch Changes

* bad22ee: Send the Google Consent Mode `update` when the site scanner asks for a consent mode.

  Separating defaults from updates in 2.5.3 made the `update` conditional on a stored choice or a GPC
  signal. A scan has neither: it carries no consent cookie and sends no GPC. The runtime therefore sent
  no Consent Mode signal at all, the container kept the template's denied `default`, and every
  consent-gated tag was withheld for the whole scan. Sites with a correct installation were reported as
  having no analytics cookies, because the scanner never saw the trackers it exists to find.

  The scanner announces itself with `consentpro-scannercontext`, which now counts as a consent signal
  in its own right. The runtime sends the state the scan asks for, extending the 2.5.3 table:

  | Situation                                                  | Runtime behaviour                                            |
  | ---------------------------------------------------------- | ------------------------------------------------------------ |
  | Scan with `consentpro-scannercontext=opt-out` (accept all) | `update` granting every category, so all tags are observable |
  | Scan with `consentpro-scannercontext=opt-in`               | `update` denying every non-essential category                |

  This also removes an older branch that skipped the update outright in `opt-in` scanner context. It
  predated the defaults and updates split and would have kept the public scanner silent rather than
  sending the denied state it asks for.

  Visitor behaviour is unchanged. A page without the scanner parameters follows exactly the lifecycles
  2.5.3 defines, so an opt-in visitor still receives nothing before choosing.

  * consentpro-dictionary@0.1.8
  * consentpro-utils@2.1.2

## 2.5.3

### Patch Changes

* 9e01f4e: Stop sending a Google Consent Mode `update` before a visitor has made a consent choice, unless GPC applies.

  The runtime initialized `consentChoices` from `defaultChoices` and pushed that straight to GTM, so a
  first-time visitor received an `update` built from defaults they never chose. The Consent Pro GTM
  template already declares that state during Consent Initialization, so the runtime was duplicating
  the `default` as a choice.

  Consent Mode updates and activation events now follow separate lifecycles:

  | Situation                                                     | Runtime behaviour                                                |
  | ------------------------------------------------------------- | ---------------------------------------------------------------- |
  | Opt-in banner, no stored choice                               | No `update` or activation events. The template owns the default. |
  | Opt-out, Don't Sell or Informational banner, no stored choice | No `update`; emit activation events for permitted tags.          |
  | GPC signal on an Opt-out or Don't Sell banner                 | `update` with the opt-out the signal asks for.                   |
  | Visitor accepts, rejects or changes preferences               | `update` with the new choices and emit activation events.        |
  | Returning visitor with a stored choice                        | `update` restoring the stored choices and emit events.           |

  Opt-out, Don't Sell and Informational banners allow tracking until the visitor opts out. Their
  granted baseline remains a GTM `default`, while the runtime still emits `consent-updated` and
  `<category>-activated` data layer events for permitted marketing and non-Google tags.

  This assumes the Consent Pro Init tag is installed on the Consent Initialization trigger, as the GTM
  setup guide requires. Without it nothing declares the denied `default`, and an unset Consent Mode
  state behaves as granted.

  References:

  * https://developers.google.com/tag-platform/security/guides/consent-debugging
  * https://developers.google.com/tag-platform/tag-manager/templates/consent-apis

## 2.5.2

### Patch Changes

* d369b9f: Keep Banner Type and Geolocation aligned, and skip a second reload when the same preview token is already loaded.
* Updated dependencies \[36435b2]
  * consentpro-utils@2.1.2
  * consentpro-dictionary@0.1.7

## 2.5.1

### Patch Changes

* fecdc78: Drive the custom-site "Powered by Consent Pro" mark from the project's own config.

  The mark was decided entirely by plan tier: the served script inlined `window.fs_consent_pro_attribution = true` for free-tier sites and nothing else ever set it, so a paid custom site never showed it and the app's "Hide Consent Pro logo" toggle changed nothing outside the in-app preview. Preview links were worse — `applyStored` reassigns the global from the fetched payload, which never carries `attribution`, so a preview dropped the mark even on the free tier.

  **consentpro-types**

  * `ConsentProV2RuntimeConfiguration` gains `hideBranding`, carried through to the sanitized client config.

  **server**

  * `projectConfigToRuntime` maps `banner_settings.hide_branding` onto it, so it ships with every publish and with the preview config.

  **consentpro-v2**

  * Custom sites resolve `showAttribution` from that config, defaulting to showing the mark. The free tier's license-derived global still wins, so a free site cannot switch it off.

* 9a490af: Pick the "Powered by Consent Pro" logo colour from the banner background.

  **consentpro-utils**

  * New `relativeLuminance` and `contrastingMonochrome` helpers: WCAG 2.1 relative luminance, and a black/white pick by contrast ratio against a background.

  **web-components**

  * `ConsentBanner`'s wordmark now reads `--consentpro-color-attribution`, falling back to the banner's own text colour. The wordmark is already `currentColor`, so the variable flips it; the "Powered by" label keeps the banner's text colour.

  **consentpro-v2 / web-app**

  * Both set `--consentpro-color-attribution` from the banner background, so the live banner and the style preview render the same logo.

* fecdc78: Fix the custom-site opt-in banner rendering without its reject button.

  The button set only ever reached the runtime through the CDN copy fetch, so any failed fetch left `<consentpro-banner>` on its own defaults, which show preferences and accept but default `showDenyButton` to `false`. An opt-in banner rendered accept-only, silently, which is a consent-compliance failure rather than a cosmetic one. One way to trigger it: `instanceConfig` writes the `consentpro-mode` query param into `bannerType`, but that param can carry an **instance key** rather than a banner type (the debugger's keys are region-derived), and the copy request for `us-or` 400s.

  **consentpro-dictionary**

  * `BANNER_STRUCTURE` and its `BannerStructure` type move to their own module and are exported from `consentpro-dictionary/consent-copy`. The record is unchanged; it was already locale-independent, so nothing about the served copy changes.
  * New `getBannerStructure(method)` resolves an unvalidated banner type, falling back to the `opt-in` structure — the only one that always offers a deny button — rather than returning `undefined`.

  **consentpro-v2**

  * The custom-site banner resolves its button structure locally from `bannerType` and layers the fetched copy's strings on top, so the button set no longer depends on the network. `showGpcNotice` is now derived from the same local structure gated on the visitor's GPC signal, instead of from the fetched copy.
  * `instanceConfig`'s handling of `consentpro-mode` is left alone deliberately: it is shared with Webflow sites, and the local structure fallback already keeps the banner compliant for the unvalidated types it produces.
  * A failed copy fetch warns to the console instead of being swallowed, so a banner falling back to English defaults is diagnosable.

* 8384efa: Show a placeholder overlay on iframes blocked for want of consent on custom (non-Webflow) sites.

  Custom sites have no pasted `fs-consent-element="placeholder"` markup, so a blocked embed simply lost its `src` and rendered as a blank box. The overlay now ships as a web component that `core/v2` swaps into the blocked iframe itself.

  **web-components**

  * New `<consentpro-placeholder>` custom element, built as its own `placeholder.js` CDN bundle. Like every other component in this package, its props are plain JS properties observed as no attribute, and its buttons dispatch bubbling, composed `consentpro:open-preferences` / `consentpro:allow` events.

  **consentpro-dictionary**

  * `getConsentCopy` returns a `placeholder` block (`message`, `preferencesText`, `acceptAllText`), so the overlay is localized like every other component.

  **server**

  * `GET /v2/cdn/web-components/placeholder.js` serves the new bundle, and `copy.json` carries the `placeholder` strings.

  **consentpro-v2**

  * `new/custom-site/placeholder.ts` builds the blocked iframe's document as a string, which the existing blob path swaps into the iframe's `src`. It is self-contained: the CDN module that registers the element, plus the script that waits for that registration, creates the element and assigns the copy as JS properties. No markup is parsed, mutated or serialized on the way, and the copy is escaped into the script rather than interpolated into HTML.
  * That script tag is pinned with the build-time `sha384` hash, so `placeholder.js` is now SRI-checked like the other component bundles.
  * Blocked iframes wire the overlay's events through `custom-site/events.ts`: the document is a same-origin `blob:`, so the component's `consentpro:*` events reach the consent-state layer directly.
  * A blocked iframe's own `sandbox` is stashed and dropped while the placeholder is shown, then restored verbatim before the original URL loads again. It applies to the untrusted embed, not to our placeholder, and without `allow-scripts` it kept the overlay from ever rendering.
  * `iframe-blocked` now fires once per blocked iframe, carrying the embed's URL. Re-rendering a placeholder whose copy arrived late no longer emits a second event whose `src` had already been replaced.

* d3e426d: Link the custom-site banner to the project's own privacy policy, or show no link at all.

  The custom-platform banner always rendered a dead `<a href="#">Privacy Policy</a>`: the project's privacy-policy URL never reached the runtime.

  **consentpro-dictionary**

  * `getConsentCopy` returns `messageHtmlWithoutPrivacyLink` alongside `messageHtml` — the same message with the whole privacy sentence removed, cut from the tokenized template so every locale ends on its own sentence terminator. `messageHtml` is unchanged.

  **server / consentpro-types**

  * `privacy_page_url` maps to `legal.privacyPolicyUrl`, and `sanitizeConfigForClient` publishes that one field. `cookiePolicyUrl` and `contactEmail` stay server-side.

  **consentpro-v2**

  * The custom-site banner points the anchor at the configured URL (normalized through `new URL()` and restricted to http(s), opened in a new tab), and drops the privacy sentence when no URL is configured.

* 8eefb34: Withdraw the GPC notice on custom sites the moment a visitor consents.

  The notice was resolved once while the elements were built and never revisited, so a visitor who knowingly accepted while a GPC signal was active kept seeing the honored notice for the rest of the page load, in both the banner and the preferences panel. It now tracks the same `GPC.honored` state the Webflow elements do, which § 7025(c)(6) requires from 1 January 2026.

* d7331e4: Style the preferences toggle and the dialog backdrop from the web app.

  **web-app**

  * The Open preferences colours card now carries Toggle Inactive Track, Toggle Active Track (the former "Preferences Checkbox"), Toggle Circular Handle and Preferences Overlay. Left on their defaults the columns stay `null`, so an existing banner looks exactly as before.
  * `ColorField` takes an `alpha` prop: an opacity track under the hue slider, a checkerboard behind every swatch, and a hex field that accepts `#rrggbbaa`. Only the overlay opts in — a colour that paints a surface has nothing to be translucent over.
  * The overlay starts at no backdrop (`#00000000`). Choosing a colour on a transparent field lands at 20% opacity rather than staying invisible; the opacity track can still take it back to nothing.

  **web-components**

  * `ConsentPreferencesDialog`'s backdrop default drops from 10% black to `transparent`: a dialog washes the page only where a site asks for it. The backdrop box is unchanged otherwise, so click-to-close still works, and any site setting `--consentpro-color-overlay` is unaffected.

  **server / consentpro-types**

  * `checkbox_inactive_color`, `checkbox_handle_color` and `preferences_overlay_color` are read, validated and saved on `banner_settings` and `banner_instances`, and published as `checkboxInactive`, `checkboxHandle` and `preferencesOverlay`. The overlay column validates `#rrggbb` or `#rrggbbaa`; the rest stay six digits.

  **consentpro-v2**

  * Maps those to `--consentpro-color-toggle-off`, `--consentpro-color-toggle-thumb` and `--consentpro-color-overlay`. The handle keeps whatever colour is picked in both switch states — nothing recolours it from the track any more.

* Updated dependencies \[9a490af]

* Updated dependencies \[fecdc78]

* Updated dependencies \[8384efa]

* Updated dependencies \[d3e426d]
  * consentpro-utils@2.1.1
  * consentpro-dictionary@0.1.6

## 2.5.0

### Minor Changes

* 6757be6: Honor a GPC signal that post-dates a visitor's stored consent.

  Previously the GPC signal only decided the *defaults*, so a visitor who consented first and enabled GPC afterwards kept their old consent indefinitely — while the banner still claimed the signal had been honored. The signal is now treated as a live opt-out request that wins over consent saved before it arrived, and a consent given knowingly after the signal was honored wins in turn (CCPA § 7025(c)(3)). The most recent expression of the visitor's preference governs.

  **consentpro-v2**

  * The consent cookie gains `gpcHonoredAt`: when the runtime first observed the signal that was still active as of that write. It is stamped on every write made while the signal is present and cleared on writes made while it is absent, which is what distinguishes consent given before the signal from consent given knowingly after it. Browsers expose no "enabled at" timestamp, so this is the only recency information available.
  * On page load, a stored consent that still grants a non-essential category and predates the signal is revoked before blocking, trackers and analytics initialize — so no tracker ever sees the stale consent, and cookies set under the revoked categories are cleaned up on the same load. A consent record is written with `action: 'reject_all'` and `source: 'gpc'`, and is never collapsed into a consent the visitor gives in the second that follows: a processed opt-out request is a compliance event in its own right, not an intermediate state.
  * The revocation runs only on pages the resolved instance is configured for. On an excluded page nothing can block a tracker or clean up a cookie, so recording an opt-out there would claim an enforcement that never happened; the stored consent is left untouched until the visitor reaches a managed page.
  * Consent records now carry the id, action and source captured when the write happened, instead of reading them from the stores when the debounced request fires. Previously any two writes inside a second could hand the first record the second one's attribution.
  * The banner is re-shown once on the page load where a category was actually revoked, so the visitor is told their saved preferences changed and gets the chance to consent knowingly instead.
  * `fs-consent-gpc` now reflects whether the signal is being **processed**, not merely present, and updates live: it flips to `"false"` the moment a visitor accepts while a signal is active, hiding `[fs-consent-element="gpc-honored"]` rather than leaving a claim in place that is no longer true. This matters for § 7025(c)(6), which as of 1 January 2026 *requires* displaying whether the signal was processed.
  * Scope is unchanged: only Opt-Out and Do Not Sell instances. Opt-In consent is never revoked, and `fs-consent-gpc` stays `"false"` on those instances: the attribute now tracks the same condition the behavior does, so it never claims a signal was processed where nothing acts on one.
  * A stored consent whose `gpcHonoredAt` equals its own `timestamp` counts as a knowing override rather than a consent the signal outranks. The two can only match when they were written together, which a consent predating the signal never is — and a custom integration writing the cookie by hand can land both in the same millisecond.
  * `FinsweetConsentPro.consents.set()` now stamps `action: 'submit'` and `source: 'api'`, like every other write path. Previously it inherited whatever wrote the consent before it, which with GPC in play would have recorded a site's own API call as a GPC-driven opt-out. It also means API-driven consent is recorded at all, where before the missing action caused the record to be dropped.

  Existing GPC visitors who had granted consent are opted out once, on their next page view, and see the banner that one time.

  **documentation**

  * `developer/custom-integration.md` documents `gpcHonoredAt` and shows how to carry it forward when writing the cookie by hand. A custom integration that omits the stamp while a signal is active writes a consent that Consent Pro cannot distinguish from one given before the signal, and revokes on the visitor's next Webflow page view.

  **consentpro-types** / **server**

  * `ConsentSource` and `ConsentRecordSchema.source` accept `'gpc'`. The consents endpoint validates against that enum, so without this the GPC records would be rejected and silently dropped.

### Patch Changes

* consentpro-dictionary@0.1.5
* consentpro-utils@2.1.0

## 2.4.2

### Patch Changes

* Updated dependencies \[f528b4f]
  * consentpro-dictionary@0.1.4
  * consentpro-utils@2.1.0

## 2.4.1

### Patch Changes

* 2836963: fix: send only a Google Consent Mode `update` from the runtime and leave the baseline `default` to the Consent Pro GTM template, which declares it at container initialization

## 2.4.0

### Minor Changes

* 55656ae: Add optional public hostname and path prefix so reverse-proxied sites publish a hostname.json for the visitor host and expose the site information the runtime uses to compose public URLs.

  The Webflow domain is unchanged. Custom-domain sites publish `publicHostname` and, when mounted under a prefix, `pathPrefix`. The runtime composes these with locale subdirectories and page slugs. Sites without these settings are unaffected.

### Patch Changes

* Updated dependencies \[55656ae]
  * consentpro-utils@2.1.0
  * consentpro-dictionary@0.1.3

## 2.3.6

### Patch Changes

* f4354d3: fix: do not block Google Tag Manager container scripts (`gtm.js?id=GTM-*`)

## 2.3.5

### Patch Changes

* 03bd744: chore(deps): resolve open Dependabot PRs and clear the `pnpm audit` backlog

  Direct dependency updates:

  * `app`: axios 1.16.0 → 1.18.0, posthog-js 1.336.1 → 1.417.0
  * `consentpro-v1`: nanoid 5.1.6 → 5.1.16, esbuild 0.27.3 → 0.28.1
  * `consentpro-v2`: esbuild 0.27.3 → 0.28.1
  * `server`: hono 4.12.21 → 4.12.34
  * `consentpro-debugger`: vite 7.3.2 → 7.3.6

  Transitive advisories are pinned to patched versions via `pnpm.overrides` (tar,
  undici, brace-expansion, js-yaml, protobufjs, fast-uri, ip-address, postcss,
  nanoid, form-data, ws, adm-zip, shell-quote, sharp, dompurify, esbuild), taking
  `pnpm audit` from 89 findings (1 critical, 41 high, 35 moderate, 12 low) to 0.

  The posthog-js bump also removes the `@opentelemetry/*` and `protobufjs`
  subtrees, which were never reachable from the shipped extension bundle.
  Telemetry configuration is unchanged and the pinned `defaults: '2025-05-24'`
  still applies, so capture behaviour is identical.

  Two advisories have no published fix and are recorded in
  `pnpm.auditConfig.ignoreCves` rather than resolved — CVE-2026-56876
  (extract-zip, via `@cloudflare/puppeteer`) and CVE-2025-14505 (elliptic, via
  `@webflow/webflow-cli`). Neither is reachable from a shipped artifact.

## 2.3.4

### Patch Changes

* Updated dependencies \[4d7fcb3]
  * consentpro-dictionary@0.1.2
  * consentpro-utils@2.0.3

## 2.3.3

### Patch Changes

* 3ea0afe: Ensure a project record per site, and dual-write core config to D1.

  **server**

  * New `services/v2/projects`: `ensureProject`, `getProjectUuidBySiteId`, `linkSiteAuthorizationProject`. Project creation is idempotent and race-safe, and revives a soft-deleted project on re-authorization.
  * The Webflow OAuth callback creates the project and stamps it onto the site authorization on first authorization. Failures are logged and never block authorization.
  * Temporary R2 → D1 dual-write (`configurator/temporary-d1-mirror`): `saveCoreConfig` and site migration mirror the core runtime config into `project_configs`, `webflow_project_configs`, `banner_instances`, `config_providers` and `config_trackers`. **R2 stays the source of truth** and the mirror soft-fails, so a D1 error can never fail a publish. Sites only begin mirroring once they have a project row, so existing sites stay unmirrored until they re-authorize.
  * `project_uuid` is stamped on scans, scan schedules, action item resolutions, policy profiles and policy documents, without overwriting a value that is already set.
  * Schema: `project_uuid` foreign keys move from `ON DELETE set null` to `ON DELETE cascade`, and `project_configs` gains `locales`.
  * Migrations `0038` (adds `project_configs.locales`) and `0039` (the foreign key change). `0039` is hand-written rather than drizzle-generated: the generated table rebuild issues `DROP TABLE`, which on D1 fires the pre-existing `policy_documents` → `policy_profiles` cascade and empties the table, because D1 runs each migration inside a transaction where `PRAGMA foreign_keys=OFF` is silently ignored. It uses `ALTER TABLE DROP COLUMN` / `ADD COLUMN` instead, so no table is ever dropped. Side effect: `project_uuid` becomes the last column on the six affected tables.

  **consentpro-v2**

  * The consent cookie is now always written with `sameSite: 'lax'`, and `secure` is derived from `location.protocol` instead of configuration. `storage.sameSite` and `storage.secure` are no longer read by the v2 runtime.

  **consentpro-types**

  * `ConsentV2TrackerDefinition` gains an optional `name` for `cookie` trackers and an optional `key` for `local-storage` / `session-storage` trackers.

* 34c5fc6: fix: invalidate stored consent cookie when the user changes region
  * consentpro-dictionary@0.1.1
  * consentpro-utils@2.0.3

## 2.3.2

### Patch Changes

* Updated dependencies \[a0173e0]
* Updated dependencies \[81c0689]
* Updated dependencies \[3fb6710]
* Updated dependencies \[9d4c732]
  * consentpro-dictionary@0.1.0
  * consentpro-utils@2.0.3

## 2.3.1

### Patch Changes

* cb1d15a: chore: cleanup runtime bundle to remove non-prod strings and ensure proper treeshake

* 2487ddd: feat: runtime unblocking for manually blocked images
  * Added `blocking/images.ts` to the v2 runtime: images holding their URL in `fs-consent-src` with `fs-consent-categories` are loaded automatically once the visitor accepts the required categories, and unloaded again when consent is revoked. Unblock-only by design — a live image `src` fires its request immediately and cannot be intercepted.
  * Emit `image-blocked` / `image-unblocked` events, mirroring iframes.
  * Simplified the Consent Manager image instructions and docs: the manual consent-callback snippet is no longer needed, only the attribute swap.

* Updated dependencies \[cb1d15a]
  * consentpro-utils@2.0.2
  * consentpro-dictionary@0.0.11

## 2.3.0

### Minor Changes

* f4ab509: feat: debugger auth
* 4435f7e: feat: same-origin library imports

### Patch Changes

* 46a579b: chore: do not include license in CDN response
* 20a5755: fix: only load debugger in staging webflow.io
* 1f19ea2: fix: allow no animations
* 5407450: fix cookie declaration hydration
* fa75381: Enhance policy generator
* Updated dependencies \[494b74c]
* Updated dependencies \[73a3472]
* Updated dependencies \[5407450]
  * consentpro-dictionary@0.0.10
  * consentpro-utils@2.0.1

## 2.2.9

### Patch Changes

* Updated dependencies \[e5d2aad]
  * consentpro-dictionary@0.0.9
  * consentpro-utils@2.0.1

## 2.2.8

### Patch Changes

* Updated dependencies \[353af98]
  * consentpro-dictionary@0.0.8
  * consentpro-utils@2.0.1

## 2.2.7

### Patch Changes

* 023a021: fix(v2): apply overflow lock on iOS when disabling scroll
* 4edff91: fix: update show function to display banner when preferences element is absent; add test for re-showing banner without preferences element

## 2.2.6

### Patch Changes

* ded7f80: update namings in usages of `consent-pro-**` to `consentpro-**`
* 73aa49f: feat: consent pro debugger
* Updated dependencies \[ded7f80]
* Updated dependencies \[73aa49f]
  * consentpro-dictionary@0.0.7
  * consentpro-utils@2.0.1

## 2.2.5

### Patch Changes

* Updated dependencies \[ef22755]
* Updated dependencies \[9cf51bd]
  * consentpro-utils@2.0.1
  * consentpro-dictionary@0.0.6

## 2.2.4

### Patch Changes

* 9309ade: fix: preserve scroll on scrollable children

## 2.2.3

### Patch Changes

* 9f95405: fix: make GPC flexible to anyone with GPC enabled, not just specific regions
* Updated dependencies \[1a79dde]
  * consentpro-dictionary@0.0.5
  * consentpro-utils@2.0.0

## 2.2.2

### Patch Changes

* ba3df41: fix: respect original script `type` after unblocking
* Updated dependencies \[1a79dde]
  * consentpro-dictionary@0.0.4
  * consentpro-utils@2.0.0

## 2.2.1

### Patch Changes

* 02e434b: fix: prevent race conditions when interacting with third party libraries
* c1bc061: fix: correct event listener target from window to document in waitDOMReady function

## 2.2.0

### Minor Changes

* 6509630: feat: disable scroll behavior controls

### Patch Changes

* consentpro-dictionary@0.0.3
* consentpro-utils@2.0.0

## 2.1.2

### Patch Changes

* 683eeb0: chore: Update dependencies to latest versions across all packages and fix pnpm audit issues

## 2.1.1

### Patch Changes

* ef4a3e5: fix(core-v2): remove double URL-encoding of fs-consent cookie
  * js-cookie already calls handles encoding and decoding
  * add test for it and for backward compatible encoded versions

## 2.1.0

### Minor Changes

* 7cd69e6: feat: support clicks in blocked iframes
* 171ba65: feat: support blocking iframes inside Webflow lightboxes
* 0f15342: feat: support GPC signal

### Patch Changes

* 3beee94: fix: unblock essential scripts marked with type="fs-consent"
* 171ba65: fix: don't process application/json scripts
* 7caea86: fix: flash of unstyled content when elements exist visible on the current page
* 7e10aef: fix: ensure that elements outside the shadow root are hidden
* 171ba65: fix: remove false positives in `iframe-blocked` API events
* f083ccd: improvement: no longer store provider & tracker metadata in each consent log
* 171ba65: fix: recursively process deeply nested nodes with the mutation observer
* 2a279e8: fix: only load consent pro when there is a matching region
* 9ad2133: fix: allow clicks outside preferences when focus-trap is activated
* Updated dependencies \[e9bd587]
* Updated dependencies \[6029a6c]
  * consentpro-utils@2.0.0
  * consentpro-dictionary@0.0.2
