@c15t/svelte 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.
- package/AGENTS.md +2 -0
- package/dist/components/{frame.svelte.d.ts → consent-gate.svelte.d.ts} +3 -3
- package/dist/components/iab-purpose-item.svelte +3 -1
- package/dist/components/iab-stack-item.svelte +1 -1
- package/dist/components/iab-vendor-list.svelte +2 -0
- package/dist/components/manager-provider.svelte +207 -34
- package/dist/components/preferences.svelte +10 -10
- package/dist/components/vendor-list.svelte +190 -0
- package/dist/components/vendor-list.svelte.d.ts +18 -0
- package/dist/context.svelte.d.ts +36 -2
- package/dist/context.svelte.js +19 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/kit/routes.js +26 -1
- package/dist/kit/types.d.ts +10 -0
- package/dist/primitives/preference-item/index.d.ts +1 -0
- package/dist/primitives/preference-item/preference-item-content.svelte +17 -3
- package/dist/primitives/preference-item/preference-item-content.svelte.d.ts +10 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/README.md +2 -0
- package/docs/frameworks/sveltekit/quickstart.md +4 -0
- package/docs/guides/deployment-modes.md +12 -0
- package/docs/integrations/building-integrations.md +5 -0
- package/docs/integrations/cloudflare-zaraz.md +399 -0
- package/docs/integrations/google-maps.md +20 -20
- package/docs/integrations/granular-consent.md +208 -0
- package/docs/integrations/overview.md +5 -4
- package/docs/integrations/youtube.md +26 -21
- package/docs/upgrade-v3.md +47 -0
- package/package.json +7 -7
- package/readme.json +0 -36
- /package/dist/components/{frame.svelte → consent-gate.svelte} +0 -0
package/dist/context.svelte.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ActiveUI, AllConsentNames, ConsentKernel, ConsentPresentation, ResolvedConsentPresentation, ConsentSnapshot, ConsentState, ConsentType, HasCondition, KernelIABState, Model, TranslationConfig } from '@c15t/core';
|
|
1
|
+
import type { ActiveUI, AllConsentNames, ConsentKernel, ConsentPresentation, ResolvedConsentPresentation, ConsentSnapshot, ConsentState, ConsentType, HasCondition, KernelIABState, Model, ResolvedVendor, TranslationConfig } from '@c15t/core';
|
|
2
2
|
import type { Theme, UIOptions } from '@c15t/ui/theme';
|
|
3
3
|
import type { ConsentManagerOptions } from './types';
|
|
4
4
|
export type SaveType = 'all' | 'custom' | 'necessary';
|
|
@@ -22,16 +22,34 @@ export interface SvelteIABState extends KernelIABState {
|
|
|
22
22
|
}
|
|
23
23
|
export interface ConsentDraftState {
|
|
24
24
|
readonly values: Partial<ConsentState>;
|
|
25
|
+
/**
|
|
26
|
+
* Granted flag per declared vendor. Seeded from the denials the gate
|
|
27
|
+
* honors, so a vendor declared `disabled` reads `true` whatever an older
|
|
28
|
+
* record says; every vendor not denied is `true`. Empty under an `iab`
|
|
29
|
+
* policy.
|
|
30
|
+
*/
|
|
31
|
+
readonly vendors: Readonly<Record<string, boolean>>;
|
|
25
32
|
readonly isStale: boolean;
|
|
26
33
|
set: (name: AllConsentNames, value: boolean) => void;
|
|
34
|
+
/**
|
|
35
|
+
* Stage one vendor's grant. Recorded by the next save. Ignored for a
|
|
36
|
+
* vendor that is not declared or is declared `disabled`, since the kernel
|
|
37
|
+
* would drop the grant on save.
|
|
38
|
+
*
|
|
39
|
+
* @param vendorId - Vendor slug as declared in `vendors` or on a script.
|
|
40
|
+
* @param granted - Whether the vendor may load once the draft is saved.
|
|
41
|
+
*/
|
|
42
|
+
setVendor: (vendorId: string, granted: boolean) => void;
|
|
27
43
|
reset: () => void;
|
|
28
44
|
save: (categories: readonly AllConsentNames[]) => Promise<void>;
|
|
29
45
|
}
|
|
30
|
-
export interface ConsentManagerState extends Pick<ConsentSnapshot, 'explicitChoice' | 'effectivePermissions' | 'promptRequirement' | 'noticeDismissal' | 'privacySignals' | 'optOutDirectives' | 'resolution' | 'policyRule' | 'restrictions' | 'nextDeadline' | 'subject' | 'evaluatedAt' | 'evaluationPolicy' | 'policyPending' | 'location' | 'overrides' | 'revision' | 'translations' | 'user'> {
|
|
46
|
+
export interface ConsentManagerState extends Pick<ConsentSnapshot, 'explicitChoice' | 'effectivePermissions' | 'promptRequirement' | 'noticeDismissal' | 'privacySignals' | 'optOutDirectives' | 'resolution' | 'policyRule' | 'restrictions' | 'nextDeadline' | 'subject' | 'evaluatedAt' | 'evaluationPolicy' | 'policyPending' | 'location' | 'overrides' | 'revision' | 'translations' | 'user' | 'vendors' | 'vendorChoice'> {
|
|
31
47
|
activeUI: ActiveUI;
|
|
32
48
|
branding: NonNullable<ConsentSnapshot['branding']>;
|
|
33
49
|
selectedConsents: Partial<ConsentState>;
|
|
34
50
|
selectedConsentTypes: Partial<ConsentState>;
|
|
51
|
+
/** Granted flag per declared vendor in the draft. */
|
|
52
|
+
selectedVendors: Readonly<Record<string, boolean>>;
|
|
35
53
|
presentation?: ConsentPresentation;
|
|
36
54
|
readonly draft: ConsentDraftState;
|
|
37
55
|
consentCategories: AllConsentNames[];
|
|
@@ -56,6 +74,15 @@ export interface ConsentManagerState extends Pick<ConsentSnapshot, 'explicitChoi
|
|
|
56
74
|
legalLinks: ConsentManagerOptions['legalLinks'];
|
|
57
75
|
translationConfig: TranslationConfig;
|
|
58
76
|
getDisplayedConsents: () => ConsentType[];
|
|
77
|
+
/**
|
|
78
|
+
* The vendors listed under one category: presentable, naming that
|
|
79
|
+
* category, without a negation. Empty under an `iab` policy, where the
|
|
80
|
+
* TC string decides and vendor rows are not shown.
|
|
81
|
+
*
|
|
82
|
+
* @param category - The category row being rendered.
|
|
83
|
+
* @returns The vendors to list, in declared order.
|
|
84
|
+
*/
|
|
85
|
+
getDisplayedVendors: (category: AllConsentNames) => ResolvedVendor[];
|
|
59
86
|
has: (condition: HasCondition<AllConsentNames>) => boolean;
|
|
60
87
|
dismissNotice: () => Promise<unknown>;
|
|
61
88
|
saveConsents: (type: SaveType) => Promise<void>;
|
|
@@ -65,6 +92,13 @@ export interface ConsentManagerState extends Pick<ConsentSnapshot, 'explicitChoi
|
|
|
65
92
|
setConsent: (name: AllConsentNames, value: boolean) => void;
|
|
66
93
|
setLanguage: (code: string) => void;
|
|
67
94
|
setSelectedConsent: (name: AllConsentNames, value: boolean) => void;
|
|
95
|
+
/**
|
|
96
|
+
* Stage one vendor's grant on the draft. Recorded by the next save.
|
|
97
|
+
*
|
|
98
|
+
* @param vendorId - Vendor slug as declared in `vendors` or on a script.
|
|
99
|
+
* @param granted - Whether the vendor may load once the draft is saved.
|
|
100
|
+
*/
|
|
101
|
+
setSelectedVendor: (vendorId: string, granted: boolean) => void;
|
|
68
102
|
subscribeToConsentChanges: (listener: (state: ConsentState) => void) => () => void;
|
|
69
103
|
}
|
|
70
104
|
export interface ConsentContextValue {
|
package/dist/context.svelte.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { allConsentNames, consentTypes as defaultConsentTypes, defaultTranslationConfig, has as evaluateHas, resolveConsentPresentation, } from '@c15t/core';
|
|
1
|
+
import { allConsentNames, consentTypes as defaultConsentTypes, defaultTranslationConfig, has as evaluateHas, resolveConsentPresentation, vendorsListedUnder, } from '@c15t/core';
|
|
2
2
|
import { getContext, setContext } from 'svelte';
|
|
3
3
|
const CONSENT_CONTEXT_KEY = Symbol('c15t-v3-consent');
|
|
4
4
|
const THEME_CONTEXT_KEY = Symbol('c15t-v3-theme');
|
|
@@ -64,6 +64,12 @@ const createConsentState = function createConsentState(kernel, options) {
|
|
|
64
64
|
getDisplayedConsents() {
|
|
65
65
|
return displayedConsentTypes(controller.consentCategories);
|
|
66
66
|
},
|
|
67
|
+
getDisplayedVendors(category) {
|
|
68
|
+
const snapshot = getSnapshotLocal();
|
|
69
|
+
return snapshot.model === 'iab'
|
|
70
|
+
? []
|
|
71
|
+
: vendorsListedUnder(snapshot.vendors?.declared ?? [], category);
|
|
72
|
+
},
|
|
67
73
|
has(condition) {
|
|
68
74
|
const snapshot = getSnapshotLocal();
|
|
69
75
|
return evaluateHas(condition, snapshot.effectivePermissions);
|
|
@@ -200,6 +206,9 @@ const createConsentState = function createConsentState(kernel, options) {
|
|
|
200
206
|
get selectedConsentTypes() {
|
|
201
207
|
return options.getDraft().values;
|
|
202
208
|
},
|
|
209
|
+
get selectedVendors() {
|
|
210
|
+
return options.getDraft().vendors;
|
|
211
|
+
},
|
|
203
212
|
setActiveUI(ui) {
|
|
204
213
|
actionSequence += 1;
|
|
205
214
|
kernel.set.activeUI(ui);
|
|
@@ -214,6 +223,9 @@ const createConsentState = function createConsentState(kernel, options) {
|
|
|
214
223
|
setSelectedConsent(name, value) {
|
|
215
224
|
options.getDraft().set(name, value);
|
|
216
225
|
},
|
|
226
|
+
setSelectedVendor(vendorId, granted) {
|
|
227
|
+
options.getDraft().setVendor(vendorId, granted);
|
|
228
|
+
},
|
|
217
229
|
subscribeToConsentChanges(listener) {
|
|
218
230
|
return kernel.subscribe((snapshot) => listener(snapshot.effectivePermissions));
|
|
219
231
|
},
|
|
@@ -223,6 +235,12 @@ const createConsentState = function createConsentState(kernel, options) {
|
|
|
223
235
|
get translations() {
|
|
224
236
|
return getSnapshotLocal().translations;
|
|
225
237
|
},
|
|
238
|
+
get vendorChoice() {
|
|
239
|
+
return getSnapshotLocal().vendorChoice;
|
|
240
|
+
},
|
|
241
|
+
get vendors() {
|
|
242
|
+
return getSnapshotLocal().vendors;
|
|
243
|
+
},
|
|
226
244
|
get user() {
|
|
227
245
|
return getSnapshotLocal().user;
|
|
228
246
|
},
|
package/dist/index.d.ts
CHANGED
|
@@ -15,7 +15,9 @@ export { default as ConsentDialogLink } from './components/panel-link.svelte';
|
|
|
15
15
|
export { default as ConsentDialogTrigger } from './components/panel-trigger.svelte';
|
|
16
16
|
export { default as ConsentManagerProvider } from './components/manager-provider.svelte';
|
|
17
17
|
export { default as ConsentWidget } from './components/preferences.svelte';
|
|
18
|
-
export { default as
|
|
18
|
+
export { default as ConsentGate } from './components/consent-gate.svelte';
|
|
19
|
+
/** @deprecated Renamed to `ConsentGate`. */
|
|
20
|
+
export { default as Frame } from './components/consent-gate.svelte';
|
|
19
21
|
export { default as IABConsentBanner } from './components/iab-prompt.svelte';
|
|
20
22
|
export { default as IABConsentDialog } from './components/iab-panel.svelte';
|
|
21
23
|
export { getConsentKernel, getConsentManager, getHeadlessConsent, getIAB, getSnapshot, type HeadlessConsentSurfaceState, type SvelteIABState, } from './context.svelte';
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,9 @@ export { default as ConsentDialogLink } from './components/panel-link.svelte';
|
|
|
12
12
|
export { default as ConsentDialogTrigger } from './components/panel-trigger.svelte';
|
|
13
13
|
export { default as ConsentManagerProvider } from './components/manager-provider.svelte';
|
|
14
14
|
export { default as ConsentWidget } from './components/preferences.svelte';
|
|
15
|
-
export { default as
|
|
15
|
+
export { default as ConsentGate } from './components/consent-gate.svelte';
|
|
16
|
+
/** @deprecated Renamed to `ConsentGate`. */
|
|
17
|
+
export { default as Frame } from './components/consent-gate.svelte';
|
|
16
18
|
export { default as IABConsentBanner } from './components/iab-prompt.svelte';
|
|
17
19
|
export { default as IABConsentDialog } from './components/iab-panel.svelte';
|
|
18
20
|
export { getConsentKernel, getConsentManager, getHeadlessConsent, getIAB, getSnapshot, } from './context.svelte';
|
package/dist/kit/routes.js
CHANGED
|
@@ -15,7 +15,7 @@ import { deferInitGvlToRoute, serveGvlReference } from '@c15t/core';
|
|
|
15
15
|
* - The init route is per-request (geo, language, GPC) and therefore
|
|
16
16
|
* `private, no-store`.
|
|
17
17
|
*/
|
|
18
|
-
import { fetchCachedManifest, getManifestAge, MANIFEST_PASSTHROUGH_HEADERS, } from '@c15t/core/server';
|
|
18
|
+
import { fetchCachedManifest, getManifestAge, MANIFEST_PASSTHROUGH_HEADERS, reportConsentSession, resolveSessionReportBackendURL, } from '@c15t/core/server';
|
|
19
19
|
import { consentInputsToOverrides, extractConsentRequestInputs, resolveBackendURL, resolveInitFromManifest, } from '@c15t/schema/types';
|
|
20
20
|
import { baseTranslations } from '@c15t/translations/all';
|
|
21
21
|
const INIT_CACHE_CONTROL = 'private, no-store';
|
|
@@ -84,6 +84,17 @@ const resolveManifestSource = function resolveManifestSource(event, options) {
|
|
|
84
84
|
}
|
|
85
85
|
return { manifestURL: `${resolved}${MANIFEST_ROUTE_SUFFIX}` };
|
|
86
86
|
};
|
|
87
|
+
/**
|
|
88
|
+
* Where the init route reports sessions, when it can: an absolute backend,
|
|
89
|
+
* read as configured rather than resolved against the request. A relative
|
|
90
|
+
* backend resolved to this app's origin is its own route, not a backend,
|
|
91
|
+
* and means no report; nothing is inferred from a manifest URL.
|
|
92
|
+
*/
|
|
93
|
+
const resolveReportBackendURL = function resolveReportBackendURL(options) {
|
|
94
|
+
return resolveSessionReportBackendURL({
|
|
95
|
+
backendURL: options.backendURL ?? getEnv('C15T_BACKEND_URL'),
|
|
96
|
+
});
|
|
97
|
+
};
|
|
87
98
|
const shouldFetchGvl = function shouldFetchGvl(manifest, payload) {
|
|
88
99
|
return (manifest.iab?.enabled === true &&
|
|
89
100
|
manifest.iab.gvl !== undefined &&
|
|
@@ -156,6 +167,20 @@ export const createSvelteKitConsentRouteHandlers = function createSvelteKitConse
|
|
|
156
167
|
reference: manifest.iab.gvl,
|
|
157
168
|
});
|
|
158
169
|
}
|
|
170
|
+
if (options.reportSessions !== false) {
|
|
171
|
+
reportConsentSession({
|
|
172
|
+
adapter: '@c15t/svelte',
|
|
173
|
+
backendURL: resolveReportBackendURL(options),
|
|
174
|
+
fetch: options.fetch,
|
|
175
|
+
headers: event.request.headers,
|
|
176
|
+
init: payload,
|
|
177
|
+
inputs,
|
|
178
|
+
manifest,
|
|
179
|
+
method: event.request.method,
|
|
180
|
+
source: 'route',
|
|
181
|
+
waitUntil: bindBackgroundRevalidate(options, event),
|
|
182
|
+
});
|
|
183
|
+
}
|
|
159
184
|
// The resolver's inputs are the only place GPC survives on the SSR
|
|
160
185
|
// path — the browser never sends `Sec-GPC` to this route when the
|
|
161
186
|
// page was server-rendered. Echo them back so the kernel folds the
|
package/dist/kit/types.d.ts
CHANGED
|
@@ -53,4 +53,14 @@ export interface ConsentManifestOptions extends ManifestSourceConfig {
|
|
|
53
53
|
* manifest is fresh or the request itself waits on the upstream.
|
|
54
54
|
*/
|
|
55
55
|
onBackgroundRevalidate?: (revalidation: Promise<void>, event: RequestEvent) => void;
|
|
56
|
+
/**
|
|
57
|
+
* Report each init the route resolves to the backend's `POST /sessions`,
|
|
58
|
+
* server-to-server and detached from the response, so the backend still
|
|
59
|
+
* counts visitors it never served `/init` to. The report is handed to
|
|
60
|
+
* `onBackgroundRevalidate` like a manifest refresh. Set `false` to send
|
|
61
|
+
* none.
|
|
62
|
+
*
|
|
63
|
+
* @default true
|
|
64
|
+
*/
|
|
65
|
+
reportSessions?: boolean;
|
|
56
66
|
}
|
|
@@ -16,6 +16,7 @@ export declare const PreferenceItem: {
|
|
|
16
16
|
children?: import("svelte").Snippet;
|
|
17
17
|
class?: string;
|
|
18
18
|
innerClassName?: string;
|
|
19
|
+
noStyle?: boolean;
|
|
19
20
|
viewportClassName?: string;
|
|
20
21
|
}, {}, "">;
|
|
21
22
|
Control: import("svelte").Component<import("svelte/elements").HTMLAttributes<HTMLDivElement> & {
|
|
@@ -17,12 +17,23 @@
|
|
|
17
17
|
children,
|
|
18
18
|
class: localClassName,
|
|
19
19
|
innerClassName,
|
|
20
|
+
noStyle: localNoStyle,
|
|
20
21
|
viewportClassName,
|
|
21
22
|
...restProps
|
|
22
23
|
}: HTMLAttributes<HTMLDivElement> & {
|
|
23
24
|
children?: Snippet;
|
|
24
25
|
class?: string;
|
|
25
26
|
innerClassName?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Drop the primitive's built-in classes. Falls back to the root's
|
|
29
|
+
* `noStyle`, like the React primitive and the sibling trigger, so a
|
|
30
|
+
* headless root strips the whole item. The IAB items set `noStyle`
|
|
31
|
+
* on their root only to own the item class and pass an explicit
|
|
32
|
+
* `false` here to keep the collapse rules; the consent widget
|
|
33
|
+
* inherits the root's `noStyle` and supplies the accordion classes
|
|
34
|
+
* itself, as React's does.
|
|
35
|
+
*/
|
|
36
|
+
noStyle?: boolean;
|
|
26
37
|
/** Presentation class for the consent widget viewport.
|
|
27
38
|
* @internal
|
|
28
39
|
*/
|
|
@@ -33,14 +44,17 @@
|
|
|
33
44
|
const triggerId = $derived(context.triggerId);
|
|
34
45
|
const contentId = $derived(context.contentId);
|
|
35
46
|
const dataState = $derived(getPreferenceItemState(open));
|
|
47
|
+
const noStyle = $derived(localNoStyle ?? context.noStyle);
|
|
36
48
|
const contentClassName = $derived.by(() =>
|
|
37
|
-
variants.content({ class: localClassName })
|
|
49
|
+
noStyle ? localClassName : variants.content({ class: localClassName })
|
|
38
50
|
);
|
|
39
51
|
const viewportClassNameValue = $derived.by(() =>
|
|
40
|
-
|
|
52
|
+
noStyle
|
|
53
|
+
? viewportClassName
|
|
54
|
+
: variants.contentViewport({ class: viewportClassName })
|
|
41
55
|
);
|
|
42
56
|
const innerClassNameValue = $derived.by(() =>
|
|
43
|
-
variants.contentInner({ class: innerClassName })
|
|
57
|
+
noStyle ? innerClassName : variants.contentInner({ class: innerClassName })
|
|
44
58
|
);
|
|
45
59
|
</script>
|
|
46
60
|
|
|
@@ -4,6 +4,16 @@ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
|
|
|
4
4
|
children?: Snippet;
|
|
5
5
|
class?: string;
|
|
6
6
|
innerClassName?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Drop the primitive's built-in classes. Falls back to the root's
|
|
9
|
+
* `noStyle`, like the React primitive and the sibling trigger, so a
|
|
10
|
+
* headless root strips the whole item. The IAB items set `noStyle`
|
|
11
|
+
* on their root only to own the item class and pass an explicit
|
|
12
|
+
* `false` here to keep the collapse rules; the consent widget
|
|
13
|
+
* inherits the root's `noStyle` and supplies the accordion classes
|
|
14
|
+
* itself, as React's does.
|
|
15
|
+
*/
|
|
16
|
+
noStyle?: boolean;
|
|
7
17
|
/** Presentation class for the consent widget viewport.
|
|
8
18
|
* @internal
|
|
9
19
|
*/
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "3.0.0-alpha.
|
|
1
|
+
export declare const version = "3.0.0-alpha.2";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '3.0.0-alpha.
|
|
2
|
+
export const version = '3.0.0-alpha.2';
|
package/docs/README.md
CHANGED
|
@@ -50,12 +50,14 @@ These docs describe v3. Start with Inth hosted setup, identify the framework, ro
|
|
|
50
50
|
- [Clear on revocation](./integrations/clear-on-revocation.md): Remove configured first-party cookies and Web Storage keys when their consent category is denied.
|
|
51
51
|
- [Clearbit](./integrations/clearbit.md): Configure Clearbit with c15t v3, understand marketing permission and verify loading and revocation.
|
|
52
52
|
- [Cloudflare Web Analytics](./integrations/cloudflare-web-analytics.md): Configure Cloudflare Web Analytics with c15t v3, understand measurement permission and verify loading and revocation.
|
|
53
|
+
- [Cloudflare Zaraz](./integrations/cloudflare-zaraz.md): Synchronize c15t permissions with Zaraz purposes while Cloudflare manages your tools.
|
|
53
54
|
- [Crisp](./integrations/crisp.md): Configure Crisp with c15t v3, understand functionality permission and verify loading and revocation.
|
|
54
55
|
- [Databuddy](./integrations/databuddy.md): Configure Databuddy's initial and updated consent state with c15t v3.
|
|
55
56
|
- [Fathom Analytics](./integrations/fathom-analytics.md): Configure Fathom Analytics with c15t v3, understand measurement permission and verify loading and revocation.
|
|
56
57
|
- [Google Maps](./integrations/google-maps.md): Prevent a map iframe from mounting before the required permission.
|
|
57
58
|
- [Google Tag](./integrations/google-tag.md): Configure gtag with c15t Consent Mode signals and understand its loading behavior.
|
|
58
59
|
- [Google Tag Manager](./integrations/google-tag-manager.md): Load GTM with c15t consent signals and verify the tags inside your container.
|
|
60
|
+
- [Granular consent](./integrations/granular-consent.md): Let visitors grant a category and still turn one vendor off, without adopting IAB TCF.
|
|
59
61
|
- [Heap](./integrations/heap.md): Configure Heap with c15t v3, understand measurement permission and verify loading and revocation.
|
|
60
62
|
- [Hightouch](./integrations/hightouch.md): Configure Hightouch with c15t v3, understand measurement permission and verify loading and revocation.
|
|
61
63
|
- [Hotjar](./integrations/hotjar.md): Configure Hotjar with c15t v3, understand measurement permission and verify loading and revocation.
|
|
@@ -116,6 +116,10 @@ the background. On adapters that expose `event.platform.context.waitUntil`
|
|
|
116
116
|
(Cloudflare, Vercel edge) the handlers hand the refresh to it so it is not cut
|
|
117
117
|
short when the response is sent; nothing is needed from you. For another
|
|
118
118
|
lifetime API, pass `onBackgroundRevalidate(refresh, event)` to the handlers.
|
|
119
|
+
The init route hands its session report to the same hook: after each
|
|
120
|
+
resolution it posts a small report to the backend's `POST /sessions`,
|
|
121
|
+
server-to-server, so the backend still counts visitors it never served
|
|
122
|
+
`/init` to. Pass `reportSessions: false` to send none.
|
|
119
123
|
|
|
120
124
|
## Use static hosting
|
|
121
125
|
|
|
@@ -30,6 +30,18 @@ in your application while consent writes still go to Inth. Regular backend
|
|
|
30
30
|
browser setup. See [data fetching and transports](./data-fetching.md) for
|
|
31
31
|
the comparison, including custom transports and offline mode.
|
|
32
32
|
|
|
33
|
+
Manifest resolution removes the per-visitor `/init` request, and with it the
|
|
34
|
+
backend's only count of visitors. The server adapters replace it with a session
|
|
35
|
+
report: after each resolution, on a server-rendered page or the same-origin
|
|
36
|
+
init route, the host posts a small report to the backend's `POST /sessions`,
|
|
37
|
+
server-to-server and detached from the response. The browser makes no request
|
|
38
|
+
and the report stores no identity; the visitor's IP and user agent travel as
|
|
39
|
+
forwarded headers under the backend's usual IP handling. Each report is one
|
|
40
|
+
resolution; a page view can produce a `render` and a `route` report, and the
|
|
41
|
+
consuming side groups them into sessions by address and user agent within a
|
|
42
|
+
window. Static output resolves in the browser and sends none. Set `reportSessions: false` on an adapter to turn
|
|
43
|
+
it off.
|
|
44
|
+
|
|
33
45
|
## Match initialization to your application output
|
|
34
46
|
|
|
35
47
|
| Application output | Initial state | Required setup |
|
|
@@ -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
|