@c15t/browser 3.0.0-alpha.1 → 3.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/AGENTS.md +2 -0
  2. package/CHANGELOG.md +10 -0
  3. package/dist/861.js +1 -1
  4. package/dist/925.js +20 -13
  5. package/dist/c15t.css +6 -3
  6. package/dist/c15t.devtools.js +1 -1
  7. package/dist/c15t.headless.js +1 -1
  8. package/dist/c15t.iab.js +4 -4
  9. package/dist/c15t.js +3 -3
  10. package/dist-types/auto-init.d.ts +1 -1
  11. package/dist-types/client.d.ts +1 -1
  12. package/dist-types/devtools.d.ts +1 -1
  13. package/dist-types/gated-scripts.d.ts +3 -2
  14. package/dist-types/global.d.ts +4 -4
  15. package/dist-types/headless.d.ts +11 -11
  16. package/dist-types/iab/mount.d.ts +1 -1
  17. package/dist-types/iab/preferences.d.ts +1 -1
  18. package/dist-types/iab/surface.d.ts +2 -2
  19. package/dist-types/iab/vendor-disclosures.d.ts +1 -1
  20. package/dist-types/iab.d.ts +7 -7
  21. package/dist-types/index.d.ts +12 -12
  22. package/dist-types/ui/banner.d.ts +2 -2
  23. package/dist-types/ui/dialog.d.ts +2 -2
  24. package/dist-types/ui/mount.d.ts +2 -2
  25. package/dist-types/ui/surface.d.ts +1 -1
  26. package/dist-types/ui/trigger.d.ts +2 -2
  27. package/dist-types/ui/widget.d.ts +1 -1
  28. package/dist-types/version.d.ts +1 -1
  29. package/docs/README.md +2 -0
  30. package/docs/frameworks/javascript/script-loader.md +40 -0
  31. package/docs/integrations/building-integrations.md +5 -0
  32. package/docs/integrations/cloudflare-zaraz.md +399 -0
  33. package/docs/integrations/google-maps.md +20 -20
  34. package/docs/integrations/granular-consent.md +208 -0
  35. package/docs/integrations/overview.md +5 -4
  36. package/docs/integrations/youtube.md +26 -21
  37. package/package.json +7 -7
  38. package/readme.json +0 -44
@@ -1,4 +1,4 @@
1
- import type { ConsentClientOptions } from './types';
1
+ import type { ConsentClientOptions } from './types.js';
2
2
  /** Attribute that turns auto-init off so the page calls `c15t.init()`. */
3
3
  export declare const MANUAL_ATTRIBUTE = "data-manual";
4
4
  /**
@@ -1,7 +1,7 @@
1
1
  import { custom, hosted } from '@c15t/core';
2
2
  import type { PolicyRule, Unsubscribe } from '@c15t/core';
3
3
  import type { ConsentRuntimeIABFactory } from '@c15t/core/runtime';
4
- import type { ConsentClient, ConsentClientOptions, ConsentUIMounter } from './types';
4
+ import type { ConsentClient, ConsentClientOptions, ConsentUIMounter } from './types.js';
5
5
  export { custom, hosted };
6
6
  /** Attribute a page element can carry to drive the client on click. */
7
7
  export declare const ACTION_ATTRIBUTE = "data-c15t-action";
@@ -18,7 +18,7 @@
18
18
  * ```
19
19
  */
20
20
  import type { DevToolsInstance, DevToolsOptions } from '@c15t/dev-tools';
21
- import type { ConsentClient } from './types';
21
+ import type { ConsentClient } from './types.js';
22
22
  /** Presentation options; the kernel and categories come from the client. */
23
23
  export type BrowserDevToolsOptions = Omit<DevToolsOptions, 'getConsentCategories' | 'kernel'>;
24
24
  /**
@@ -1,4 +1,4 @@
1
- import type { ConsentSnapshot } from '@c15t/core';
1
+ import type { AllConsentNames, ConsentSnapshot } from '@c15t/core';
2
2
  /** Attribute that names the category an inert `<script>` waits on. */
3
3
  export declare const CATEGORY_ATTRIBUTE = "data-c15t-category";
4
4
  /** Set once a gated script has been activated (or rejected as invalid). */
@@ -13,10 +13,11 @@ interface GatedScriptActivator {
13
13
  *
14
14
  * @param getSnapshot - Read current consent before each activation.
15
15
  * @param root - Where to look. Defaults to the document when scanning.
16
+ * @param registerCategories - Add discovered categories before evaluating gates.
16
17
  * @returns A scanner and its disposal function.
17
18
  * @internal
18
19
  */
19
- export declare const createGatedScriptActivator: (getSnapshot: () => ConsentSnapshot, root?: ParentNode) => GatedScriptActivator;
20
+ export declare const createGatedScriptActivator: (getSnapshot: () => ConsentSnapshot, root?: ParentNode, registerCategories?: (categories: AllConsentNames[]) => void) => GatedScriptActivator;
20
21
  /**
21
22
  * Run inert `<script type="text/plain" data-c15t-category="…">` tags whose
22
23
  * categories the snapshot grants. Non-async scripts run in document order,
@@ -1,10 +1,10 @@
1
1
  import { custom, hosted } from '@c15t/core';
2
2
  import type { AllConsentNames, ConsentSnapshot, HasCondition, KernelUser, Unsubscribe } from '@c15t/core';
3
3
  import type { DevToolsInstance } from '@c15t/dev-tools';
4
- import type { CreateConsentClientContext } from './client';
5
- import { manifest } from './transports/manifest';
6
- import { offline } from './transports/offline';
7
- import type { ConsentClient, ConsentClientEventMap, ConsentClientOptions, ConsentUIHandle, ConsentUIOptions } from './types';
4
+ import type { CreateConsentClientContext } from './client.js';
5
+ import { manifest } from './transports/manifest.js';
6
+ import { offline } from './transports/offline.js';
7
+ import type { ConsentClient, ConsentClientEventMap, ConsentClientOptions, ConsentUIHandle, ConsentUIOptions } from './types.js';
8
8
  /** The name the script-tag build installs itself under. */
9
9
  export declare const GLOBAL_NAME = "c15t";
10
10
  /** A call queued before the script loaded: `[method, ...args]`. */
@@ -13,7 +13,7 @@
13
13
  * c15t.on('ui', (surface) => banner.hidden = surface !== 'banner');
14
14
  * ```
15
15
  */
16
- import type { ConsentClient, ConsentClientOptions } from './types';
16
+ import type { ConsentClient, ConsentClientOptions } from './types.js';
17
17
  /**
18
18
  * Create the page's client without starting it. `mountUI()` throws.
19
19
  *
@@ -28,14 +28,14 @@ export declare const createConsentClient: (options?: ConsentClientOptions) => Co
28
28
  * @returns The started client.
29
29
  */
30
30
  export declare const init: (options?: ConsentClientOptions) => ConsentClient;
31
- export { ACTION_ATTRIBUTE, custom, hosted, PREFERENCES_HASH } from './client';
32
- export type { PageAction } from './client';
33
- export { resolveRules } from './client';
34
- export { ACTIVATED_ATTRIBUTE, activateGatedScripts, CATEGORY_ATTRIBUTE, } from './gated-scripts';
35
- export { manifest, manifestNeedsLocation } from './transports/manifest';
36
- export type { ManifestModeOptions } from './transports/manifest';
37
- export { offline } from './transports/offline';
38
- export type { OfflineModeOptions } from './transports/offline';
39
- export type { ConsentClient, ConsentClientEventMap, ConsentClientOptions, ConsentModeName, PolicyPresetName, } from './types';
40
- export { version } from './version';
31
+ export { ACTION_ATTRIBUTE, custom, hosted, PREFERENCES_HASH } from './client.js';
32
+ export type { PageAction } from './client.js';
33
+ export { resolveRules } from './client.js';
34
+ export { ACTIVATED_ATTRIBUTE, activateGatedScripts, CATEGORY_ATTRIBUTE, } from './gated-scripts.js';
35
+ export { manifest, manifestNeedsLocation } from './transports/manifest.js';
36
+ export type { ManifestModeOptions } from './transports/manifest.js';
37
+ export { offline } from './transports/offline.js';
38
+ export type { OfflineModeOptions } from './transports/offline.js';
39
+ export type { ConsentClient, ConsentClientEventMap, ConsentClientOptions, ConsentModeName, PolicyPresetName, } from './types.js';
40
+ export { version } from './version.js';
41
41
  export type { ConsentSnapshot, ConsentState } from '@c15t/core';
@@ -1,4 +1,4 @@
1
- import type { ConsentClient, ConsentUIHandle, ConsentUIOptions } from '../types';
1
+ import type { ConsentClient, ConsentUIHandle, ConsentUIOptions } from '../types.js';
2
2
  /**
3
3
  * Mount IAB UI alongside the ordinary UI for non-IAB policy regions.
4
4
  * @param client - The IAB-capable client to render.
@@ -1,5 +1,5 @@
1
1
  import type { ConsentSnapshot } from '@c15t/core';
2
- import type { SurfaceContext } from '../ui/surface';
2
+ import type { SurfaceContext } from '../ui/surface.js';
3
3
  /** Preference content preserves focused controls while the IAB draft changes. */
4
4
  export interface IABPreferences {
5
5
  element: HTMLElement;
@@ -1,4 +1,4 @@
1
- import type { ConsentUIOptions } from '../types';
2
- import type { Surface, SurfaceContext } from '../ui/surface';
1
+ import type { ConsentUIOptions } from '../types.js';
2
+ import type { Surface, SurfaceContext } from '../ui/surface.js';
3
3
  /** One IAB banner/dialog lifecycle on the client's existing kernel. */
4
4
  export declare const createIABSurface: (ctx: SurfaceContext, options: ConsentUIOptions) => Surface;
@@ -1,5 +1,5 @@
1
1
  import type { ConsentSnapshot, GlobalVendorList, NonIABVendor } from '@c15t/core';
2
- import type { SurfaceCopy } from '../ui/copy';
2
+ import type { SurfaceCopy } from '../ui/copy.js';
3
3
  type Vendor = GlobalVendorList['vendors'][number] | NonIABVendor;
4
4
  /**
5
5
  * Render the vendor's declared policies, data use, storage, and retention.
@@ -1,4 +1,4 @@
1
- import type { ConsentClient, ConsentClientOptions } from './types';
1
+ import type { ConsentClient, ConsentClientOptions } from './types.js';
2
2
  /**
3
3
  * Create an IAB-capable browser client without starting it.
4
4
  * @param options - Transport, CMP, and presentation settings.
@@ -11,10 +11,10 @@ export declare const createConsentClient: (options?: ConsentClientOptions) => Co
11
11
  * @returns The started client. CMP controls are on `client.runtime.iab`.
12
12
  */
13
13
  export declare const init: (options?: ConsentClientOptions) => ConsentClient;
14
- export { custom, hosted } from './client';
15
- export { offline } from './transports/offline';
16
- export { manifest } from './transports/manifest';
17
- export { mountIABConsentUI } from './iab/mount';
18
- export type { ConsentClient, ConsentClientOptions, ConsentUIOptions, } from './types';
14
+ export { custom, hosted } from './client.js';
15
+ export { offline } from './transports/offline.js';
16
+ export { manifest } from './transports/manifest.js';
17
+ export { mountIABConsentUI } from './iab/mount.js';
18
+ export type { ConsentClient, ConsentClientOptions, ConsentUIOptions, } from './types.js';
19
19
  export { iab } from '@c15t/iab';
20
- export { version } from './version';
20
+ export { version } from './version.js';
@@ -14,7 +14,7 @@
14
14
  * c15t.on('consent', (snapshot) => console.log(snapshot.effectivePermissions));
15
15
  * ```
16
16
  */
17
- import type { ConsentClient, ConsentClientOptions } from './types';
17
+ import type { ConsentClient, ConsentClientOptions } from './types.js';
18
18
  /**
19
19
  * Create the page's client without starting it.
20
20
  *
@@ -29,15 +29,15 @@ export declare const createConsentClient: (options?: ConsentClientOptions) => Co
29
29
  * @returns The started client.
30
30
  */
31
31
  export declare const init: (options?: ConsentClientOptions) => ConsentClient;
32
- export { ACTION_ATTRIBUTE, custom, hosted, PREFERENCES_HASH } from './client';
33
- export type { PageAction } from './client';
34
- export { resolveRules } from './client';
35
- export { ACTIVATED_ATTRIBUTE, activateGatedScripts, CATEGORY_ATTRIBUTE, } from './gated-scripts';
36
- export { manifest, manifestNeedsLocation } from './transports/manifest';
37
- export type { ManifestModeOptions } from './transports/manifest';
38
- export { offline } from './transports/offline';
39
- export type { OfflineModeOptions } from './transports/offline';
40
- export type { ConsentBannerOptions, ConsentClient, ConsentClientEventMap, ConsentClientOptions, ConsentDialogOptions, ConsentModeName, PolicyPresetName, ConsentTriggerOptions, ConsentUIHandle, ConsentUIOptions, TriggerPosition, } from './types';
41
- export { mountConsentUI } from './ui/mount';
42
- export { version } from './version';
32
+ export { ACTION_ATTRIBUTE, custom, hosted, PREFERENCES_HASH } from './client.js';
33
+ export type { PageAction } from './client.js';
34
+ export { resolveRules } from './client.js';
35
+ export { ACTIVATED_ATTRIBUTE, activateGatedScripts, CATEGORY_ATTRIBUTE, } from './gated-scripts.js';
36
+ export { manifest, manifestNeedsLocation } from './transports/manifest.js';
37
+ export type { ManifestModeOptions } from './transports/manifest.js';
38
+ export { offline } from './transports/offline.js';
39
+ export type { OfflineModeOptions } from './transports/offline.js';
40
+ export type { ConsentBannerOptions, ConsentClient, ConsentClientEventMap, ConsentClientOptions, ConsentDialogOptions, ConsentModeName, PolicyPresetName, ConsentTriggerOptions, ConsentUIHandle, ConsentUIOptions, TriggerPosition, } from './types.js';
41
+ export { mountConsentUI } from './ui/mount.js';
42
+ export { version } from './version.js';
43
43
  export type { ConsentSnapshot, ConsentState } from '@c15t/core';
@@ -1,5 +1,5 @@
1
- import type { ConsentBannerOptions } from '../types';
2
- import type { Surface, SurfaceContext } from './surface';
1
+ import type { ConsentBannerOptions } from '../types.js';
2
+ import type { Surface, SurfaceContext } from './surface.js';
3
3
  /**
4
4
  * The cookie banner.
5
5
  *
@@ -1,5 +1,5 @@
1
- import type { ConsentDialogOptions } from '../types';
2
- import type { Surface, SurfaceContext } from './surface';
1
+ import type { ConsentDialogOptions } from '../types.js';
2
+ import type { Surface, SurfaceContext } from './surface.js';
3
3
  /**
4
4
  * The preference centre dialog.
5
5
  *
@@ -1,5 +1,5 @@
1
- import type { ConsentClient, ConsentUIHandle, ConsentUIOptions } from '../types';
2
- import type { Surface, SurfaceContext } from './surface';
1
+ import type { ConsentClient, ConsentUIHandle, ConsentUIOptions } from '../types.js';
2
+ import type { Surface, SurfaceContext } from './surface.js';
3
3
  /**
4
4
  * Mount the banner, preference centre and trigger for a client.
5
5
  *
@@ -1,6 +1,6 @@
1
1
  import type { ConsentSnapshot, LegalLinks } from '@c15t/core';
2
2
  import type { LegalLinksTranslations } from '@c15t/translations';
3
- import type { ConsentClient } from '../types';
3
+ import type { ConsentClient } from '../types.js';
4
4
  /** What every surface renders against. */
5
5
  export interface SurfaceContext {
6
6
  /** The client whose kernel drives the surface. */
@@ -1,5 +1,5 @@
1
- import type { ConsentTriggerOptions } from '../types';
2
- import type { Surface, SurfaceContext } from './surface';
1
+ import type { ConsentTriggerOptions } from '../types.js';
2
+ import type { Surface, SurfaceContext } from './surface.js';
3
3
  /**
4
4
  * The floating button that reopens the preference centre.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  import type { ConsentSnapshot } from '@c15t/core';
2
- import type { SurfaceContext } from './surface';
2
+ import type { SurfaceContext } from './surface.js';
3
3
  /** The preference list plus its footer. */
4
4
  export interface Widget {
5
5
  /** The widget root. */
@@ -1 +1 @@
1
- export declare const version = "3.0.0-alpha.1";
1
+ export declare const version = "3.0.0-alpha.2";
package/docs/README.md CHANGED
@@ -30,12 +30,14 @@ These docs describe v3. Start with Inth hosted setup, identify the framework, ro
30
30
  - [Clear on revocation](./integrations/clear-on-revocation.md): Remove configured first-party cookies and Web Storage keys when their consent category is denied.
31
31
  - [Clearbit](./integrations/clearbit.md): Configure Clearbit with c15t v3, understand marketing permission and verify loading and revocation.
32
32
  - [Cloudflare Web Analytics](./integrations/cloudflare-web-analytics.md): Configure Cloudflare Web Analytics with c15t v3, understand measurement permission and verify loading and revocation.
33
+ - [Cloudflare Zaraz](./integrations/cloudflare-zaraz.md): Synchronize c15t permissions with Zaraz purposes while Cloudflare manages your tools.
33
34
  - [Crisp](./integrations/crisp.md): Configure Crisp with c15t v3, understand functionality permission and verify loading and revocation.
34
35
  - [Databuddy](./integrations/databuddy.md): Configure Databuddy's initial and updated consent state with c15t v3.
35
36
  - [Fathom Analytics](./integrations/fathom-analytics.md): Configure Fathom Analytics with c15t v3, understand measurement permission and verify loading and revocation.
36
37
  - [Google Maps](./integrations/google-maps.md): Prevent a map iframe from mounting before the required permission.
37
38
  - [Google Tag](./integrations/google-tag.md): Configure gtag with c15t Consent Mode signals and understand its loading behavior.
38
39
  - [Google Tag Manager](./integrations/google-tag-manager.md): Load GTM with c15t consent signals and verify the tags inside your container.
40
+ - [Granular consent](./integrations/granular-consent.md): Let visitors grant a category and still turn one vendor off, without adopting IAB TCF.
39
41
  - [Heap](./integrations/heap.md): Configure Heap with c15t v3, understand measurement permission and verify loading and revocation.
40
42
  - [Hightouch](./integrations/hightouch.md): Configure Hightouch with c15t v3, understand measurement permission and verify loading and revocation.
41
43
  - [Hotjar](./integrations/hotjar.md): Configure Hotjar with c15t v3, understand measurement permission and verify loading and revocation.
@@ -46,6 +46,46 @@ The loader exposes `updateScripts`, `getLoadedScriptIds` and `dispose`.
46
46
  Unloading an element cannot reverse requests or code that already ran. Test
47
47
  revocation and vendor cleanup with [verification](https://c15t.com/docs/guides/verify-consent).
48
48
 
49
+ ## Dispose integration resources
50
+
51
+ Ordinary scripts keep their mounted resource when `updateScripts` receives a
52
+ fresh object with the same ID and unchanged element configuration. New callback
53
+ functions alone do not reload the vendor or send a temporary denial. Changing
54
+ the source, inline code or element attributes starts a new loading lifecycle.
55
+ Consent conditions are reevaluated on every configuration update. Pending
56
+ load and error events use the latest registered callbacks and consent state.
57
+ Setting `persistAfterConsentRevoked` to `false` removes an owned retained element
58
+ when the script no longer has consent.
59
+
60
+ Custom script configurations can use `onDispose(info)` to release event
61
+ listeners or other resources. Adding this hook opts the configuration into an
62
+ object-owned lifecycle: replacing the object disposes its resources and starts
63
+ again, even with the same ID. Keep these objects stable across framework
64
+ rerenders. The loader also calls the hook when the configuration is removed or
65
+ the loader is disposed, including configurations that never loaded.
66
+ `info.element` contains the last loaded or retained element when available,
67
+ even when configuration removal has already detached it.
68
+
69
+ Duplicate references receive one cleanup per registration. Re-registering a
70
+ removed object starts a new lifecycle. Updates requested from lifecycle
71
+ callbacks run after the current pass; if several are requested, the latest
72
+ configuration wins. Disposal stops further reconciliation. A callback feedback
73
+ loop exceeding 100 consecutive passes disposes the loader and reports an
74
+ `error` debug event. Avoid callbacks that keep changing consent or replacing
75
+ their own configuration.
76
+
77
+ `onBeforeLoad` prepares a loading attempt. If a callback changes consent or
78
+ replaces configurations, the loader cancels that attempt before loading and
79
+ reevaluates the latest state. A still-eligible script can retry preparation
80
+ with a new element and updated consent. Make `onBeforeLoad` safe to repeat;
81
+ use `onLoad` for initialization that requires a completed load. This also
82
+ applies to callback-only scripts, whose `onLoad` is skipped when preparation
83
+ invalidates the current pass.
84
+
85
+ Consent revocation alone does not call `onDispose`. Use `onConsentChange` for
86
+ vendor opt-out commands. Cleanup errors are reported through the loader's debug
87
+ events and do not prevent other configurations from being cleaned up.
88
+
49
89
  ## Clear stored tracking data
50
90
 
51
91
  Script gating does not remove cookies or Web Storage entries that a script
@@ -31,6 +31,11 @@ Replace the example URL and implement the vendor's initialization. This is a
31
31
  loader template, not a functioning analytics SDK. The script stays blocked
32
32
  while measurement permission is denied.
33
33
 
34
+ Add `vendor: 'example-analytics'` and declare the vendor in the runtime's
35
+ `vendors` option or in the backend manifest when visitors should be able to
36
+ turn this vendor off inside a granted category. See
37
+ [granular consent](./granular-consent.md).
38
+
34
39
  ## Define revocation deliberately
35
40
 
36
41
  `onConsentChange` receives current permission information. Use it to update the