@c15t/nextjs 2.2.0 → 3.0.0-alpha.0

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 (220) hide show
  1. package/AGENTS.md +102 -142
  2. package/README.md +4 -4
  3. package/dist/api.js +1 -0
  4. package/dist/config.js +1 -0
  5. package/dist/devtools.js +2 -0
  6. package/dist/headers.js +1 -0
  7. package/dist/iab/styles.css +1 -1
  8. package/dist/iab/styles.tw3.css +133 -19
  9. package/dist/index.js +1 -1
  10. package/dist/middleware.js +1 -0
  11. package/dist/node-bridge.js +1 -0
  12. package/dist/pages.js +1 -0
  13. package/dist/proxy.js +1 -0
  14. package/dist/root.js +2 -0
  15. package/dist/server.js +1 -0
  16. package/dist/static.js +1 -0
  17. package/dist/styles.css +1 -1
  18. package/dist/styles.tw3.css +173 -29
  19. package/dist/version.js +1 -1
  20. package/dist-types/api.d.ts +88 -0
  21. package/dist-types/config.d.ts +110 -0
  22. package/dist-types/devtools.d.ts +1 -0
  23. package/dist-types/headers.d.ts +4 -0
  24. package/dist-types/index.d.ts +28 -10
  25. package/dist-types/middleware.d.ts +15 -0
  26. package/dist-types/node-bridge.d.ts +57 -0
  27. package/dist-types/pages.d.ts +88 -0
  28. package/dist-types/proxy.d.ts +34 -0
  29. package/dist-types/root.d.ts +86 -0
  30. package/dist-types/server.d.ts +164 -0
  31. package/dist-types/static.d.ts +42 -0
  32. package/dist-types/types.d.ts +5 -36
  33. package/dist-types/version.d.ts +1 -1
  34. package/docs/README.md +102 -142
  35. package/docs/assets/v3/brand-bar.png +0 -0
  36. package/docs/assets/v3/brand-card.png +0 -0
  37. package/docs/assets/v3/choice-wall.png +0 -0
  38. package/docs/assets/v3/mobile-card.png +0 -0
  39. package/docs/assets/v3/preferences.png +0 -0
  40. package/docs/customization/overview.md +45 -0
  41. package/docs/customization/recipes.md +79 -0
  42. package/docs/customization/slots.md +55 -0
  43. package/docs/customization/tokens.md +76 -0
  44. package/docs/customization/translations.md +49 -0
  45. package/docs/frameworks/next/api-reference/data-fetching.md +416 -0
  46. package/docs/frameworks/next/app-router.md +403 -0
  47. package/docs/frameworks/next/client-side.md +118 -0
  48. package/docs/frameworks/next/components/consent-banner.md +251 -211
  49. package/docs/frameworks/next/components/consent-dialog-link.md +96 -35
  50. package/docs/frameworks/next/components/consent-dialog-trigger.md +74 -149
  51. package/docs/frameworks/next/components/consent-dialog.md +189 -134
  52. package/docs/frameworks/next/components/consent-manager-provider.md +60 -318
  53. package/docs/frameworks/next/components/consent-widget.md +172 -114
  54. package/docs/frameworks/next/components/dev-tools.md +199 -40
  55. package/docs/frameworks/next/components/frame.md +137 -42
  56. package/docs/frameworks/next/concepts/consent-categories.md +24 -89
  57. package/docs/frameworks/next/concepts/policy-presets.md +142 -0
  58. package/docs/frameworks/next/content-security-policy.md +189 -0
  59. package/docs/frameworks/next/data-fetching.md +74 -0
  60. package/docs/frameworks/next/geography-headers.md +251 -0
  61. package/docs/frameworks/next/headless.md +95 -185
  62. package/docs/frameworks/next/hooks/use-consent-manager/overview.md +42 -163
  63. package/docs/frameworks/next/iab/overview.md +37 -107
  64. package/docs/frameworks/next/optimization.md +158 -194
  65. package/docs/frameworks/next/pages-router.md +296 -0
  66. package/docs/frameworks/next/quickstart.md +31 -132
  67. package/docs/frameworks/next/script-loader.md +134 -467
  68. package/docs/frameworks/next/server-side.md +97 -130
  69. package/docs/frameworks/next/static-export.md +164 -0
  70. package/docs/frameworks/next/styling/overview.md +166 -250
  71. package/docs/frameworks/next/troubleshooting.md +134 -144
  72. package/docs/guides/consent-state.md +60 -0
  73. package/docs/guides/data-fetching.md +163 -0
  74. package/docs/guides/deployment-modes.md +63 -0
  75. package/docs/guides/troubleshooting.md +68 -0
  76. package/docs/guides/verify-consent.md +62 -0
  77. package/docs/integrations/adobe-analytics.md +239 -105
  78. package/docs/integrations/ahrefs-analytics.md +238 -104
  79. package/docs/integrations/amplitude.md +219 -157
  80. package/docs/integrations/building-integrations.md +32 -224
  81. package/docs/integrations/clearbit.md +247 -86
  82. package/docs/integrations/cloudflare-web-analytics.md +250 -84
  83. package/docs/integrations/crisp.md +251 -97
  84. package/docs/integrations/databuddy.md +259 -153
  85. package/docs/integrations/fathom-analytics.md +239 -96
  86. package/docs/integrations/google-maps.md +328 -207
  87. package/docs/integrations/google-tag-manager.md +248 -96
  88. package/docs/integrations/google-tag.md +261 -90
  89. package/docs/integrations/heap.md +222 -149
  90. package/docs/integrations/hightouch.md +225 -131
  91. package/docs/integrations/hotjar.md +239 -90
  92. package/docs/integrations/intercom.md +239 -98
  93. package/docs/integrations/linkedin-insights.md +243 -113
  94. package/docs/integrations/logrocket.md +241 -123
  95. package/docs/integrations/matomo-analytics.md +256 -111
  96. package/docs/integrations/meta-pixel.md +197 -324
  97. package/docs/integrations/microsoft-clarity.md +233 -114
  98. package/docs/integrations/microsoft-uet.md +245 -110
  99. package/docs/integrations/mixpanel-analytics.md +252 -87
  100. package/docs/integrations/openai-pixel.md +441 -0
  101. package/docs/integrations/overview.md +95 -133
  102. package/docs/integrations/pirsch.md +249 -96
  103. package/docs/integrations/plausible-analytics.md +241 -100
  104. package/docs/integrations/posthog.md +353 -214
  105. package/docs/integrations/promptwatch.md +251 -81
  106. package/docs/integrations/reddit-pixel.md +226 -173
  107. package/docs/integrations/rudderstack.md +244 -187
  108. package/docs/integrations/rybbit-analytics.md +244 -91
  109. package/docs/integrations/segment.md +238 -92
  110. package/docs/integrations/snapchat-pixel.md +240 -110
  111. package/docs/integrations/tiktok-pixel.md +249 -81
  112. package/docs/integrations/umami-analytics.md +242 -95
  113. package/docs/integrations/vercel-analytics.md +242 -90
  114. package/docs/integrations/x-pixel.md +238 -104
  115. package/docs/integrations/youtube.md +354 -142
  116. package/docs/upgrade-v3.md +334 -0
  117. package/iab/styles.css +1 -1
  118. package/iab/styles.tw3.css +1 -1
  119. package/package.json +106 -65
  120. package/readme.json +3 -3
  121. package/src/iab/styles.css +1 -1
  122. package/src/iab/styles.tw3.css +1 -1
  123. package/src/styles.css +1 -1
  124. package/src/styles.tw3.css +1 -1
  125. package/styles.css +1 -1
  126. package/styles.tw3.css +1 -1
  127. package/client/components/consent-dialog-link.js +0 -3
  128. package/client/components/integrations.js +0 -3
  129. package/dist/components/integrations/index.cjs +0 -1
  130. package/dist/components/integrations/index.js +0 -1
  131. package/dist/headless.cjs +0 -1
  132. package/dist/index.cjs +0 -1
  133. package/dist/libs/browser-initial-data.cjs +0 -1
  134. package/dist/libs/browser-initial-data.js +0 -1
  135. package/dist/libs/initial-data.cjs +0 -1
  136. package/dist/libs/initial-data.js +0 -1
  137. package/dist/types.cjs +0 -1
  138. package/dist/version.cjs +0 -1
  139. package/dist-types/components/integrations/index.d.ts +0 -1
  140. package/dist-types/libs/browser-initial-data.d.ts +0 -9
  141. package/dist-types/libs/initial-data.d.ts +0 -33
  142. package/docs/frameworks/next/building-headless-components.md +0 -379
  143. package/docs/frameworks/next/callbacks.md +0 -186
  144. package/docs/frameworks/next/concepts/client-modes.md +0 -177
  145. package/docs/frameworks/next/concepts/consent-models.md +0 -117
  146. package/docs/frameworks/next/concepts/cookie-management.md +0 -122
  147. package/docs/frameworks/next/concepts/glossary.md +0 -24
  148. package/docs/frameworks/next/concepts/initialization-flow.md +0 -149
  149. package/docs/frameworks/next/concepts/policy-packs.md +0 -230
  150. package/docs/frameworks/next/hooks/use-color-scheme.md +0 -41
  151. package/docs/frameworks/next/hooks/use-consent-manager/checking-consent.md +0 -96
  152. package/docs/frameworks/next/hooks/use-consent-manager/location-info.md +0 -97
  153. package/docs/frameworks/next/hooks/use-consent-manager/setting-consent.md +0 -94
  154. package/docs/frameworks/next/hooks/use-draggable.md +0 -59
  155. package/docs/frameworks/next/hooks/use-focus-trap.md +0 -42
  156. package/docs/frameworks/next/hooks/use-reduced-motion.md +0 -37
  157. package/docs/frameworks/next/hooks/use-ssr-status.md +0 -32
  158. package/docs/frameworks/next/hooks/use-text-direction.md +0 -50
  159. package/docs/frameworks/next/hooks/use-translations.md +0 -55
  160. package/docs/frameworks/next/iab/consent-banner.md +0 -91
  161. package/docs/frameworks/next/iab/consent-dialog.md +0 -129
  162. package/docs/frameworks/next/iab/use-gvl-data.md +0 -21
  163. package/docs/frameworks/next/iframe-blocking.md +0 -106
  164. package/docs/frameworks/next/internationalization.md +0 -207
  165. package/docs/frameworks/next/network-blocker.md +0 -140
  166. package/docs/frameworks/next/policy-packs.md +0 -248
  167. package/docs/frameworks/next/styling/classnames.md +0 -94
  168. package/docs/frameworks/next/styling/color-scheme.md +0 -84
  169. package/docs/frameworks/next/styling/css-variables.md +0 -53
  170. package/docs/frameworks/next/styling/slots.md +0 -94
  171. package/docs/frameworks/next/styling/tailwind.md +0 -137
  172. package/docs/frameworks/next/styling/tokens.md +0 -156
  173. package/docs/shared/concepts/client-modes.md +0 -103
  174. package/docs/shared/concepts/consent-categories.md +0 -41
  175. package/docs/shared/concepts/consent-models.md +0 -72
  176. package/docs/shared/concepts/cookie-management.md +0 -88
  177. package/docs/shared/concepts/glossary.md +0 -24
  178. package/docs/shared/concepts/initialization-flow.md +0 -105
  179. package/docs/shared/concepts/policy-packs.md +0 -225
  180. package/docs/shared/react/components/consent-banner.md +0 -242
  181. package/docs/shared/react/components/consent-dialog-link.md +0 -45
  182. package/docs/shared/react/components/consent-dialog-trigger.md +0 -185
  183. package/docs/shared/react/components/consent-dialog.md +0 -119
  184. package/docs/shared/react/components/consent-manager-provider.md +0 -225
  185. package/docs/shared/react/components/consent-widget.md +0 -121
  186. package/docs/shared/react/components/dev-tools.md +0 -81
  187. package/docs/shared/react/components/frame.md +0 -52
  188. package/docs/shared/react/guides/building-headless-components.md +0 -110
  189. package/docs/shared/react/guides/callbacks.md +0 -89
  190. package/docs/shared/react/guides/headless.md +0 -31
  191. package/docs/shared/react/guides/iframe-blocking.md +0 -65
  192. package/docs/shared/react/guides/internationalization.md +0 -123
  193. package/docs/shared/react/guides/network-blocker.md +0 -72
  194. package/docs/shared/react/guides/optimization.md +0 -44
  195. package/docs/shared/react/guides/policy-packs.md +0 -173
  196. package/docs/shared/react/guides/script-loader.md +0 -311
  197. package/docs/shared/react/hooks/use-color-scheme.md +0 -31
  198. package/docs/shared/react/hooks/use-consent-manager/checking-consent.md +0 -95
  199. package/docs/shared/react/hooks/use-consent-manager/location-info.md +0 -96
  200. package/docs/shared/react/hooks/use-consent-manager/overview.md +0 -74
  201. package/docs/shared/react/hooks/use-consent-manager/setting-consent.md +0 -93
  202. package/docs/shared/react/hooks/use-draggable.md +0 -30
  203. package/docs/shared/react/hooks/use-focus-trap.md +0 -20
  204. package/docs/shared/react/hooks/use-reduced-motion.md +0 -33
  205. package/docs/shared/react/hooks/use-ssr-status.md +0 -16
  206. package/docs/shared/react/hooks/use-text-direction.md +0 -38
  207. package/docs/shared/react/hooks/use-translations.md +0 -15
  208. package/docs/shared/react/iab/consent-banner.md +0 -60
  209. package/docs/shared/react/iab/consent-dialog.md +0 -76
  210. package/docs/shared/react/iab/overview.md +0 -80
  211. package/docs/shared/react/iab/use-gvl-data.md +0 -21
  212. package/docs/shared/react/styling/classnames.md +0 -93
  213. package/docs/shared/react/styling/color-scheme.md +0 -35
  214. package/docs/shared/react/styling/css-variables.md +0 -53
  215. package/docs/shared/react/styling/overview.md +0 -261
  216. package/docs/shared/react/styling/slots.md +0 -93
  217. package/docs/shared/react/styling/stylesheet-entrypoint.md +0 -8
  218. package/docs/shared/react/styling/tailwind.md +0 -88
  219. package/docs/shared/react/styling/tokens.md +0 -155
  220. package/docs/shared/troubleshooting.md +0 -82
@@ -0,0 +1,62 @@
1
+ ---
2
+ title: Verify consent before shipping
3
+ description: Test requests, policy resolution, persistence, navigation and
4
+ preference changes in a production build.
5
+ group: guides
6
+ ---
7
+
8
+ ## Establish the policy under test
9
+
10
+ Use a fresh browser profile and a known policy. For an opt-in choice policy,
11
+ optional requests should be absent before a choice. Opt-out and notice policies
12
+ have different defaults; inspect the resolved rule rather than expecting every
13
+ region to show the same banner. Keep test geography overrides out of production.
14
+
15
+ Inventory scripts in your HTML, application code, tag manager, plugins and
16
+ embeds. A c15t provider cannot make an independently loaded vendor wait for a
17
+ choice. Remove duplicate loaders before interpreting the result.
18
+
19
+ ## Run the visitor flow
20
+
21
+ | Action | Check |
22
+ | ------------------------------------------ | ---------------------------------------------------------------------------------------- |
23
+ | Load without a stored choice | Correct policy and prompt; category-gated vendors stay blocked when permission is denied |
24
+ | Reject optional categories | Prompt closes; denied vendors remain blocked |
25
+ | Reload | Valid rejection persists; no new choice event is emitted by hydration |
26
+ | Reopen preferences | Settings remain reachable after the banner closes |
27
+ | Save one category | Only that category gets a new confirmation time |
28
+ | Navigate without reloading | One runtime remains active; no duplicate vendor initialization |
29
+ | Revoke a grant | Future gated work stops and configured cleanup runs |
30
+ | Load with an expired or incompatible grant | It does not silently restore optional permissions |
31
+ | Block the consent backend | Failed resolution is observable; absence of a banner does not grant permission |
32
+ | Block browser storage | Interaction still works where supported; verify whether the choice survives reload |
33
+
34
+ Inspect Network before the page starts loading, with cache disabled for the test.
35
+ Filter by the vendor's script and collection domains. Hiding an iframe after it
36
+ loads is too late to prevent the initial request.
37
+
38
+ Google Consent Mode integrations intentionally load their scripts and send
39
+ consent signals. Test their default and update commands separately from a
40
+ zero-request gate. See [Google Tag Manager](../integrations/google-tag-manager.md)
41
+ and [Google Tag](../integrations/google-tag.md).
42
+
43
+ ## Test the production hosting shape
44
+
45
+ For static sites, serve the generated files. Confirm no request depends on an
46
+ API route or rewrite that only exists in development. For SSR, inspect the
47
+ initial HTML and check that hydration does not change a valid stored choice.
48
+ Test a direct visit as well as client navigation.
49
+
50
+ For a cross-origin backend, check allowed origins, protocol and reachable URLs.
51
+ A public backend URL is not an API secret. Keep credentials out of client props
52
+ and public environment variables.
53
+
54
+ ## Check the interface
55
+
56
+ Use a narrow viewport, long translated labels and keyboard-only navigation.
57
+ Check that blocking dialogs trap focus, return it to the trigger when closed,
58
+ and do not leave scrolling locked. Non-blocking notices should allow interaction
59
+ with the page. Test contrast and focus indicators after applying a theme.
60
+
61
+ Record the policy, framework, deployment and observed request behavior with the
62
+ test result. "The banner appears" is only one assertion.
@@ -1,160 +1,294 @@
1
1
  ---
2
2
  title: Adobe Analytics
3
- description: Adobe Analytics loaded through an Adobe Experience Platform Data
4
- Collection Tags embed URL.
3
+ description: Configure Adobe Analytics with c15t v3, understand measurement
4
+ permission and verify loading and revocation.
5
5
  group: integrations
6
- icon: adobe-analytics
7
6
  ---
8
- [Adobe Analytics](https://business.adobe.com/products/analytics/adobe-analytics.html) is commonly deployed through an Adobe Experience Platform Data Collection web property. Data Collection generates a property-specific Tags embed script, often hosted on `assets.adobedtm.com`, and that script can load Adobe Analytics, Web SDK, or other configured extensions and rules.
9
7
 
10
- ## Integrate with c15t
8
+ ## Configure Adobe Analytics
11
9
 
12
- **React**
10
+ Copy the full HTTPS embed URL for your Adobe Data Collection property environment. Replace the example URL; Adobe does not have a shared Analytics loader that only needs an account ID.
13
11
 
14
- ```tsx
15
- import { type ReactNode } from 'react';
16
- import { ConsentManagerProvider } from '@c15t/react';
17
- import { adobeAnalytics } from '@c15t/scripts/adobe-analytics';
12
+ | Package manager | Command |
13
+ | :-------------- | :-------------------------- |
14
+ | npm | `npm install @c15t/scripts` |
15
+ | pnpm | `pnpm add @c15t/scripts` |
16
+ | yarn | `yarn add @c15t/scripts` |
17
+ | bun | `bun add @c15t/scripts` |
18
18
 
19
- const scripts = [
20
- adobeAnalytics({
21
- scriptUrl:
22
- 'https://assets.adobedtm.com/YOUR_ORG/YOUR_PROPERTY/launch-production.min.js',
23
- }),
24
- ];
19
+ ```ts title="src/consent-scripts.ts"
20
+ import { adobeAnalytics } from '@c15t/scripts/adobe-analytics';
25
21
 
26
- export function ConsentProvider({ children }: { children: ReactNode }) {
27
- return (
28
- <ConsentManagerProvider
29
- options={{
30
- mode: 'hosted',
31
- backendURL: 'https://your-instance.c15t.dev',
32
- scripts,
33
- }}
34
- >
35
- {children}
36
- </ConsentManagerProvider>
37
- );
38
- }
22
+ export const scripts = [adobeAnalytics({
23
+ scriptUrl: 'https://assets.adobedtm.com/YOUR_ORG/YOUR_PROPERTY/launch-production.min.js',
24
+ })];
39
25
  ```
40
26
 
27
+ ## Register the scripts
28
+
29
+ Complete your [framework quickstart](https://c15t.com/docs/frameworks) first. Keep its Inth
30
+ endpoint, policy, styles and consent UI. Remove the vendor's original script,
31
+ SDK initializer or tag-manager entry so c15t owns loading once.
32
+
33
+ The `scripts` export in `src/consent-scripts.ts` is a configuration, not an
34
+ initializer. Add it to your existing consent owner using the registration point
35
+ below. These are partial edits to that owner, not additional providers.
36
+
41
37
  **Next.js**
42
38
 
39
+ Import the configuration into the client boundary from your router guide:
40
+
41
+ ```ts
42
+ import { ConsentRoot } from 'c15t/next';
43
+ import { scripts } from './consent-scripts';
44
+ ```
45
+
46
+ Keep the server-resolved `state` and shared `consentConfig` from your
47
+ router guide. Its manifest, init and save URLs stay in effect. Add
48
+ `scripts` as a top-level prop on the existing root:
49
+
43
50
  ```tsx
44
- 'use client';
51
+ <ConsentRoot state={state} config={consentConfig} scripts={scripts}>
52
+ {children}
53
+ </ConsentRoot>
54
+ ```
45
55
 
46
- import { type ReactNode } from 'react';
47
- import { ConsentManagerProvider } from '@c15t/nextjs';
48
- import { adobeAnalytics } from '@c15t/scripts/adobe-analytics';
56
+ For a Pages Router or static-export setup using `ConsentProvider`, add
57
+ `scripts` to its existing `options` instead. Keep the router-specific setup
58
+ from [Next.js script loading](../frameworks/next/script-loader.md).
59
+
60
+ **TanStack Start**
49
61
 
50
- const scripts = [
51
- adobeAnalytics({
52
- scriptUrl:
53
- 'https://assets.adobedtm.com/YOUR_ORG/YOUR_PROPERTY/launch-production.min.js',
54
- }),
55
- ];
62
+ In your existing root route component, import the scripts alongside
63
+ `ConsentRoot`. Keep the server loader from the [TanStack Start quickstart](https://c15t.com/docs/frameworks/tanstack-start/quickstart).
64
+
65
+ ```tsx
66
+ import { Outlet } from '@tanstack/react-router';
67
+ import { ConsentRoot } from 'c15t/tanstack-start';
68
+ import { scripts } from '../consent-scripts';
56
69
 
57
- export function ConsentProvider({ children }: { children: ReactNode }) {
70
+ function Root() {
71
+ const state = Route.useLoaderData();
58
72
  return (
59
- <ConsentManagerProvider
60
- options={{
61
- mode: 'hosted',
62
- backendURL: '/api/c15t',
63
- scripts,
64
- }}
65
- >
66
- {children}
67
- </ConsentManagerProvider>
73
+ <ConsentRoot state={state} backendURL={backendURL} initRoute={false} scripts={scripts}>
74
+ <Outlet />
75
+ {/* Keep your consent banner, dialog and preferences link here. */}
76
+ </ConsentRoot>
68
77
  );
69
78
  }
70
79
  ```
71
80
 
72
- **JavaScript**
81
+ This edits the existing route. `Route` and `backendURL` come from its setup;
82
+ keep the document shell and head components if they are part of your root.
83
+ `initRoute={false}` keeps the quickstart's direct-backend initialization.
84
+ If your app mounts a consent server route, retain its existing `initRoute`
85
+ instead. Do not return script callbacks from a server function or route loader.
86
+
87
+ **React**
88
+
89
+ Import the scripts into your existing provider component:
73
90
 
74
91
  ```ts
75
- import { getOrCreateConsentRuntime } from 'c15t';
76
- import { adobeAnalytics } from '@c15t/scripts/adobe-analytics';
92
+ import { ConsentProvider } from 'c15t/react';
93
+ import { scripts } from './consent-scripts';
94
+ ```
95
+
96
+ Keep the existing options and add `scripts`:
97
+
98
+ ```tsx
99
+ <ConsentProvider options={{ ...consentOptions, scripts }}>
100
+ {children}
101
+ </ConsentProvider>
102
+ ```
103
+
104
+ Here `consentOptions` is your existing configuration, including
105
+ `mode: hosted({ url: backendURL })`. Keep the banner, dialog and preferences
106
+ link inside the provider. See [React script loading](https://c15t.com/docs/frameworks/react/script-loader).
107
+
108
+ **Nuxt**
77
109
 
78
- getOrCreateConsentRuntime({
79
- mode: 'hosted',
80
- backendURL: 'https://your-instance.c15t.dev',
81
- scripts: [
82
- adobeAnalytics({
83
- scriptUrl:
84
- 'https://assets.adobedtm.com/YOUR_ORG/YOUR_PROPERTY/launch-production.min.js',
85
- }),
86
- ],
110
+ Attach one loader from the root `app.vue`, after the Nuxt module has
111
+ started its browser runtime. This keeps vendor callbacks in application code rather
112
+ than serialized `nuxt.config.ts` runtime configuration.
113
+
114
+ ```vue title="app/app.vue"
115
+ <script setup lang="ts">
116
+ import { onUnmounted } from 'vue';
117
+ import { createScriptLoader } from 'c15t/modules/script-loader';
118
+ import { scripts } from '../src/consent-scripts';
119
+
120
+ const nuxtApp = useNuxtApp();
121
+ const kernel = useConsentKernel();
122
+ let loader: ReturnType<typeof createScriptLoader> | undefined;
123
+
124
+ const removeMountedHook = nuxtApp.hook('app:mounted', () => {
125
+ loader = createScriptLoader({ kernel, scripts });
126
+ });
127
+ onUnmounted(() => {
128
+ removeMountedHook();
129
+ loader?.dispose();
87
130
  });
131
+ </script>
132
+
133
+ <template>
134
+ <ConsentRoot />
135
+ <NuxtPage />
136
+ </template>
88
137
  ```
89
138
 
90
- ## Find Your Embed URL
139
+ Merge the setup code into your root and retain its footer and preferences
140
+ link. `useConsentKernel` is auto-imported by the c15t Nuxt module. Adjust the
141
+ relative script import if your `app.vue` is at the project root. This loader
142
+ waits until the module has applied browser persistence and privacy signals,
143
+ then reads the current snapshot and observes future changes. Do not also register these scripts
144
+ in another loader. See the [Nuxt quickstart](https://c15t.com/docs/frameworks/nuxt/quickstart).
145
+
146
+ **Vue**
147
+
148
+ Use the kernel already provided by the Vue plugin. Merge this setup into
149
+ `App.vue`, whose lifetime covers the application:
150
+
151
+ ```vue title="src/App.vue"
152
+ <script setup lang="ts">
153
+ import { onMounted, onUnmounted } from 'vue';
154
+ import { createScriptLoader } from 'c15t/modules/script-loader';
155
+ import { useConsentKernel } from 'c15t/vue/vue-plugin';
156
+ import ConsentRoot from 'c15t/vue/consent-root';
157
+ import { scripts } from './consent-scripts';
91
158
 
92
- Open Adobe Data Collection, choose your Tags property, then open **Environments**. Select the install action for the environment you want to deploy and copy the web property embed script URL from the generated code.
159
+ const kernel = useConsentKernel();
160
+ let loader: ReturnType<typeof createScriptLoader> | undefined;
93
161
 
94
- Each Adobe environment has its own embed code. Use the production URL in production, and keep development or staging URLs limited to test environments. The URL is typically shaped like:
162
+ onMounted(() => {
163
+ loader = createScriptLoader({ kernel, scripts });
164
+ });
165
+ onUnmounted(() => loader?.dispose());
166
+ </script>
95
167
 
96
- ```txt
97
- https://assets.adobedtm.com/{org}/{property}/launch-{env}.min.js
168
+ <template>
169
+ <ConsentRoot />
170
+ <main>Your application</main>
171
+ </template>
98
172
  ```
99
173
 
100
- Self-hosted Data Collection builds are supported too. c15t only requires a full `https:` URL.
174
+ Keep your existing page content and preferences link. The plugin still owns
175
+ the kernel and persistence; this component owns only the vendor loader.
176
+ Do not register the same scripts in plugin configuration as well. See the
177
+ [Vue quickstart](https://c15t.com/docs/frameworks/vue/quickstart).
101
178
 
102
- ## How c15t loads it
179
+ **Astro**
103
180
 
104
- * **Category:** `measurement` (Analytics)
105
- * **Loads when:** measurement consent is granted
106
- * **On revocation:** unloaded - c15t removes the Adobe Tags script element from the DOM.
181
+ Point the existing Astro integration at a client module. Keep its `mode`,
182
+ `ui` and framework integration from the [Astro quickstart](https://c15t.com/docs/frameworks/astro/quickstart).
183
+ Import `fileURLToPath` in your Astro configuration:
107
184
 
108
- The helper blocks the Adobe Tags library until measurement consent is granted. When measurement consent is revoked, c15t unloads the script element. Adobe rules, extensions, cookies, and downstream tags that already ran may have their own state, so configure Data Collection rules and extensions to respect your consent model as well.
185
+ ```js title="astro.config.mjs"
186
+ import { fileURLToPath } from 'node:url';
187
+ ```
109
188
 
110
- This is the same caveat as tag managers: a Tags property can load more than Adobe Analytics. Keep non-measurement tags behind Adobe-side rule conditions, consent checks, or separate properties so they do not run from a measurement-only grant.
189
+ Add this option to the existing `c15t({ ... })` call. Resolve the path from
190
+ the configuration file because Astro injects the import into a virtual module:
111
191
 
112
- By default, c15t also seeds the Adobe Client Data Layer queue before loading:
192
+ ```js
193
+ clientEntrypoint: fileURLToPath(new URL('./src/c15t.client.ts', import.meta.url)),
194
+ ```
113
195
 
114
- ```ts
115
- adobeAnalytics({
116
- scriptUrl:
117
- 'https://assets.adobedtm.com/YOUR_ORG/YOUR_PROPERTY/launch-production.min.js',
118
- seedAdobeDataLayer: true,
119
- })
196
+ Export the scripts from that module:
197
+
198
+ ```ts title="src/c15t.client.ts"
199
+ import type { C15tClientOptionsExtension } from '@c15t/astro';
200
+ import { scripts } from './consent-scripts';
201
+
202
+ export default { scripts } satisfies C15tClientOptionsExtension;
120
203
  ```
121
204
 
122
- This creates `window.adobeDataLayer = []` only when it is still undefined. Adobe's Client Data Layer extension uses `adobeDataLayer` as the default object name, and the pre-seed is harmless for properties that do not use that extension.
205
+ The integration passes this extension to its shared browser runtime. Vendor
206
+ helpers contain callbacks, so do not put them in the serialized `scripts`
207
+ option in `astro.config.mjs`. Keep one runtime across consent islands and
208
+ `ClientRouter` navigation.
123
209
 
124
- Adobe's `_satellite` object becomes available after the Tags library loads:
210
+ **Svelte**
125
211
 
126
- ```ts
127
- if (window._satellite) {
128
- // Adobe Tags runtime is available.
129
- }
212
+ Import the scripts in the component that owns your existing provider and
213
+ pass them as a top-level prop:
214
+
215
+ ```svelte title="src/App.svelte"
216
+ <script lang="ts">
217
+ import { ConsentManagerProvider, hosted } from '@c15t/svelte';
218
+ import { scripts } from './consent-scripts';
219
+
220
+ const backendURL = import.meta.env.VITE_C15T_BACKEND_URL;
221
+ if (!backendURL) throw new Error('Set VITE_C15T_BACKEND_URL');
222
+ const mode = hosted({ url: backendURL });
223
+ </script>
224
+
225
+ <ConsentManagerProvider {mode} {scripts}>
226
+ <!-- Keep your application, consent UI and preferences link here. -->
227
+ </ConsentManagerProvider>
130
228
  ```
131
229
 
132
- Use synchronous deployment only when a legacy Tags setup requires it:
230
+ Retain the styles and consent UI from the [Svelte quickstart](https://c15t.com/docs/frameworks/svelte/quickstart).
231
+ The provider owns the loader and disposes it on unmount.
232
+
233
+ **SvelteKit**
234
+
235
+ Add the scripts to the existing root layout provider. Keep the server load
236
+ and its serializable prefetch data from the [SvelteKit quickstart](https://c15t.com/docs/frameworks/sveltekit/quickstart).
237
+
238
+ ```svelte title="src/routes/+layout.svelte"
239
+ <script lang="ts">
240
+ import { ConsentManagerProvider, hosted } from '@c15t/svelte';
241
+ import { scripts } from '../consent-scripts';
242
+
243
+ let { children, data } = $props();
244
+ const mode = hosted({ url: data.backendURL });
245
+ </script>
246
+
247
+ <ConsentManagerProvider {mode} {scripts} prefetch={data.prefetch}>
248
+ {@render children()}
249
+ <!-- Keep your consent UI and preferences link here. -->
250
+ </ConsentManagerProvider>
251
+ ```
252
+
253
+ Import vendor helpers in the layout component, not in `+layout.server.ts`.
254
+ For static hosting, keep your browser-only `mode` setup and omit request
255
+ prefetch; the `scripts` prop stays the same. If you pass an externally owned
256
+ `runtime` to the provider, register scripts when creating that runtime instead.
257
+
258
+ **JavaScript**
259
+
260
+ Attach the loader to your existing kernel before calling
261
+ `kernel.commands.init()`:
133
262
 
134
263
  ```ts
135
- adobeAnalytics({
136
- scriptUrl:
137
- 'https://assets.adobedtm.com/YOUR_ORG/YOUR_PROPERTY/launch-production.min.js',
138
- async: false,
139
- })
264
+ import { createScriptLoader } from 'c15t/modules/script-loader';
265
+ import { scripts } from './consent-scripts';
266
+
267
+ const loader = createScriptLoader({ kernel, scripts });
140
268
  ```
141
269
 
142
- ## Types
270
+ Call `loader.dispose()` when that application instance is destroyed.
271
+ `kernel` is the hosted kernel from your quickstart. A provider-owned kernel
272
+ already has a loader; do not attach a second one. See
273
+ [JavaScript script loading](https://c15t.com/docs/frameworks/javascript/script-loader).
274
+
275
+ ## Options
143
276
 
144
- ### AdobeAnalyticsOptions
277
+ | Option | Behavior |
278
+ | -------------------- | ------------------------------------------------------------------------ |
279
+ | `scriptUrl` | Required full HTTPS property embed URL. Invalid or non-HTTPS URLs throw. |
280
+ | `async` | Defaults to `true`. |
281
+ | `seedAdobeDataLayer` | Defaults to `true`. Creates `window.adobeDataLayer` only if absent. |
145
282
 
146
- |Property|Value|
147
- |:--|:--|
148
- |Type Name|\`AdobeAnalyticsOptions\`|
149
- |Source Path|\`./packages/scripts/src/vendors/analytics/adobe-analytics.ts\`|
283
+ ## Consent behavior
150
284
 
151
- \*ExtractedTypeTable: Could not extract "AdobeAnalyticsOptions" from "./packages/scripts/src/vendors/analytics/adobe-analytics.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
285
+ Measurement permission gates the property loader. Rules and extensions inside the Adobe property may load other services. Review those destinations and their purposes too; this helper does not assign separate consent categories to individual Adobe rules.
152
286
 
153
- ### Script
287
+ ## Verify the integration
154
288
 
155
- |Property|Value|
156
- |:--|:--|
157
- |Type Name|\`Script\`|
158
- |Source Path|\`./packages/core/src/libs/script-loader/types.ts\`|
289
+ Confirm the environment URL is correct and inspect requests from every enabled extension. Check that revoking permission stops application data-layer events; the helper does not call an Adobe shutdown API.
159
290
 
160
- \*ExtractedTypeTable: Could not extract "Script" from "./packages/core/src/libs/script-loader/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
291
+ Use a fresh session with an opt-in policy to check initial denial. Then grant
292
+ `measurement`, revoke it, and reload. Inspect both network requests and future
293
+ application events. Removing a script cannot undo code or requests that already
294
+ ran. Follow the [consent verification guide](../guides/verify-consent.md).