@c15t/react 2.0.4 → 2.2.0-canary-20260727202135

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 (332) hide show
  1. package/AGENTS.md +155 -0
  2. package/README.md +29 -14
  3. package/client/components/integrations.js +3 -0
  4. package/dist/components/consent-banner/atoms/overlay.cjs +1 -1
  5. package/dist/components/consent-banner/atoms/root.cjs +1 -1
  6. package/dist/components/consent-banner/components.cjs +1 -1
  7. package/dist/components/consent-banner/consent-banner.cjs +1 -1
  8. package/dist/components/consent-banner/error-boundary.cjs +1 -1
  9. package/dist/components/consent-banner/index.cjs +1 -1
  10. package/dist/components/consent-banner/policy-actions.cjs +1 -1
  11. package/dist/components/consent-dialog/atoms/card.cjs +1 -1
  12. package/dist/components/consent-dialog/atoms/overlay.cjs +1 -1
  13. package/dist/components/consent-dialog/atoms/root.cjs +1 -1
  14. package/dist/components/consent-dialog/consent-dialog.cjs +1 -1
  15. package/dist/components/consent-dialog/index.cjs +1 -1
  16. package/dist/components/consent-dialog-link/index.cjs +1 -1
  17. package/dist/components/consent-dialog-trigger/atoms/button.cjs +1 -1
  18. package/dist/components/consent-dialog-trigger/atoms/button.js +1 -1
  19. package/dist/components/consent-dialog-trigger/atoms/icon.cjs +1 -1
  20. package/dist/components/consent-dialog-trigger/atoms/root.cjs +1 -1
  21. package/dist/components/consent-dialog-trigger/atoms/text.cjs +1 -1
  22. package/dist/components/consent-dialog-trigger/atoms/toolbar.cjs +1 -0
  23. package/dist/components/consent-dialog-trigger/atoms/toolbar.js +1 -0
  24. package/dist/components/consent-dialog-trigger/consent-dialog-trigger-toolbar.cjs +1 -0
  25. package/dist/components/consent-dialog-trigger/consent-dialog-trigger-toolbar.js +1 -0
  26. package/dist/components/consent-dialog-trigger/consent-dialog-trigger.cjs +1 -1
  27. package/dist/components/consent-dialog-trigger/index.cjs +1 -1
  28. package/dist/components/consent-dialog-trigger/index.js +1 -1
  29. package/dist/components/consent-dialog-trigger/use-draggable.cjs +1 -1
  30. package/dist/components/consent-preferences-link/consent-preferences-link.cjs +1 -1
  31. package/dist/components/consent-preferences-link/index.cjs +1 -1
  32. package/dist/components/consent-widget/atoms/accordion.cjs +1 -1
  33. package/dist/components/consent-widget/atoms/button.cjs +1 -1
  34. package/dist/components/consent-widget/atoms/footer.cjs +1 -1
  35. package/dist/components/consent-widget/atoms/root.cjs +1 -1
  36. package/dist/components/consent-widget/consent-widget.cjs +1 -1
  37. package/dist/components/consent-widget/index.cjs +1 -1
  38. package/dist/components/consent-widget/policy-actions.cjs +1 -1
  39. package/dist/components/frame/atoms.cjs +1 -1
  40. package/dist/components/frame/atoms.js +1 -1
  41. package/dist/components/frame/frame.cjs +1 -1
  42. package/dist/components/frame/index.cjs +1 -1
  43. package/dist/components/iab-consent-banner/atoms/button-group.cjs +1 -1
  44. package/dist/components/iab-consent-banner/atoms/card.cjs +1 -1
  45. package/dist/components/iab-consent-banner/atoms/description.cjs +1 -1
  46. package/dist/components/iab-consent-banner/atoms/footer.cjs +1 -1
  47. package/dist/components/iab-consent-banner/atoms/header.cjs +1 -1
  48. package/dist/components/iab-consent-banner/atoms/overlay.cjs +1 -1
  49. package/dist/components/iab-consent-banner/atoms/root.cjs +1 -1
  50. package/dist/components/iab-consent-banner/atoms/title.cjs +1 -1
  51. package/dist/components/iab-consent-banner/iab-consent-banner.cjs +1 -1
  52. package/dist/components/iab-consent-banner/iab-consent-banner.js +1 -1
  53. package/dist/components/iab-consent-banner/index.cjs +1 -1
  54. package/dist/components/iab-consent-dialog/atoms/card.cjs +1 -1
  55. package/dist/components/iab-consent-dialog/atoms/content.cjs +1 -1
  56. package/dist/components/iab-consent-dialog/atoms/footer.cjs +1 -1
  57. package/dist/components/iab-consent-dialog/atoms/header.cjs +1 -1
  58. package/dist/components/iab-consent-dialog/atoms/overlay.cjs +1 -1
  59. package/dist/components/iab-consent-dialog/atoms/purpose-item.cjs +1 -1
  60. package/dist/components/iab-consent-dialog/atoms/root.cjs +1 -1
  61. package/dist/components/iab-consent-dialog/atoms/stack-item.cjs +1 -1
  62. package/dist/components/iab-consent-dialog/atoms/tabs.cjs +1 -1
  63. package/dist/components/iab-consent-dialog/atoms/vendor-list.cjs +1 -1
  64. package/dist/components/iab-consent-dialog/hooks/use-gvl-data.cjs +1 -1
  65. package/dist/components/iab-consent-dialog/iab-consent-dialog.cjs +1 -1
  66. package/dist/components/iab-consent-dialog/index.cjs +1 -1
  67. package/dist/components/iab-consent-dialog/use-iab-translations.cjs +1 -1
  68. package/dist/components/integrations/google-map.cjs +1 -0
  69. package/dist/components/integrations/google-map.js +1 -0
  70. package/dist/components/integrations/index.cjs +1 -0
  71. package/dist/components/integrations/index.js +1 -0
  72. package/dist/components/integrations/shared.cjs +1 -0
  73. package/dist/components/integrations/shared.js +1 -0
  74. package/dist/components/integrations/youtube-embed.cjs +1 -0
  75. package/dist/components/integrations/youtube-embed.js +1 -0
  76. package/dist/components/shared/libs/recursive-clone-children.cjs +1 -1
  77. package/dist/components/shared/libs/slot.cjs +1 -1
  78. package/dist/components/shared/libs/use-controllable-state.cjs +1 -1
  79. package/dist/components/shared/policy-actions.cjs +1 -1
  80. package/dist/components/shared/primitives/box.cjs +1 -1
  81. package/dist/components/shared/primitives/button.cjs +1 -1
  82. package/dist/components/shared/primitives/button.js +1 -1
  83. package/dist/components/shared/primitives/legal-links/index.cjs +1 -1
  84. package/dist/components/shared/primitives/legal-links/index.js +1 -1
  85. package/dist/components/shared/ui/accordion/accordion.cjs +1 -1
  86. package/dist/components/shared/ui/accordion/index.cjs +1 -1
  87. package/dist/components/shared/ui/animated-collapse/animated-collapse.cjs +1 -1
  88. package/dist/components/shared/ui/animated-collapse/index.cjs +1 -1
  89. package/dist/components/shared/ui/branding.cjs +1 -1
  90. package/dist/components/shared/ui/button/button.cjs +1 -1
  91. package/dist/components/shared/ui/button/index.cjs +1 -1
  92. package/dist/components/shared/ui/collapsible/collapsible.cjs +1 -1
  93. package/dist/components/shared/ui/collapsible/index.cjs +1 -1
  94. package/dist/components/shared/ui/dialog/dialog.cjs +1 -1
  95. package/dist/components/shared/ui/dialog/index.cjs +1 -1
  96. package/dist/components/shared/ui/icon.cjs +1 -1
  97. package/dist/components/shared/ui/logo.cjs +1 -1
  98. package/dist/components/shared/ui/preference-item/index.cjs +1 -1
  99. package/dist/components/shared/ui/preference-item/preference-item.cjs +1 -1
  100. package/dist/components/shared/ui/switch/index.cjs +1 -1
  101. package/dist/components/shared/ui/switch/switch.cjs +1 -1
  102. package/dist/components/shared/ui/tabs/index.cjs +1 -1
  103. package/dist/components/shared/ui/tabs/tabs.cjs +1 -1
  104. package/dist/context/consent-manager-context.cjs +1 -1
  105. package/dist/context/consent-tracking-context.cjs +1 -1
  106. package/dist/context/theme-context.cjs +1 -1
  107. package/dist/headless.cjs +1 -1
  108. package/dist/headless.js +1 -1
  109. package/dist/hooks/index.cjs +1 -1
  110. package/dist/hooks/index.js +1 -1
  111. package/dist/hooks/use-color-scheme.cjs +1 -1
  112. package/dist/hooks/use-component-config.cjs +1 -1
  113. package/dist/hooks/use-consent-dialog-trigger.cjs +1 -1
  114. package/dist/hooks/use-consent-manager.cjs +1 -1
  115. package/dist/hooks/use-consent-script.cjs +1 -0
  116. package/dist/hooks/use-consent-script.js +1 -0
  117. package/dist/hooks/use-focus-trap.cjs +1 -1
  118. package/dist/hooks/use-headless-consent-ui.cjs +1 -1
  119. package/dist/hooks/use-headless-iab-consent-ui.cjs +1 -1
  120. package/dist/hooks/use-reduced-motion.cjs +1 -1
  121. package/dist/hooks/use-scroll-lock.cjs +1 -1
  122. package/dist/hooks/use-ssr-status.cjs +1 -1
  123. package/dist/hooks/use-styles.cjs +1 -1
  124. package/dist/hooks/use-text-direction.cjs +1 -1
  125. package/dist/hooks/use-theme.cjs +1 -1
  126. package/dist/hooks/use-translations.cjs +1 -1
  127. package/dist/iab.cjs +1 -1
  128. package/dist/index.cjs +1 -1
  129. package/dist/index.js +1 -1
  130. package/dist/primitives/accordion.cjs +1 -1
  131. package/dist/primitives/button.cjs +1 -1
  132. package/dist/primitives/collapsible.cjs +1 -1
  133. package/dist/primitives/dialog.cjs +1 -1
  134. package/dist/primitives/preference-item.cjs +1 -1
  135. package/dist/primitives/switch.cjs +1 -1
  136. package/dist/primitives/tabs.cjs +1 -1
  137. package/dist/primitives.cjs +1 -1
  138. package/dist/providers/consent-manager-provider.cjs +1 -1
  139. package/dist/server/fetch-ssr-data.cjs +1 -1
  140. package/dist/server/fetch-ssr-data.js +1 -1
  141. package/dist/server/headers.cjs +1 -1
  142. package/dist/server/headers.js +1 -1
  143. package/dist/server/index.cjs +1 -1
  144. package/dist/server/init-cache-key.cjs +1 -1
  145. package/dist/server/normalize-url.cjs +1 -1
  146. package/dist/styles.tw3.css +1 -1
  147. package/dist/types/theme/index.cjs +1 -1
  148. package/dist/types/theme/style-types.cjs +1 -1
  149. package/dist/utils/cn.cjs +1 -1
  150. package/dist/utils/merge-styles.cjs +1 -1
  151. package/dist/utils/test-helpers.cjs +1 -1
  152. package/dist/utils/theme-utils.cjs +1 -1
  153. package/dist/version.cjs +1 -1
  154. package/dist/version.js +1 -1
  155. package/dist-types/components/consent-banner/components.d.ts +2 -2
  156. package/dist-types/components/consent-banner/policy-actions.d.ts +1 -1
  157. package/dist-types/components/consent-dialog/atoms/card.d.ts +5 -5
  158. package/dist-types/components/consent-dialog-trigger/atoms/toolbar.d.ts +22 -0
  159. package/dist-types/components/consent-dialog-trigger/consent-dialog-trigger-toolbar.d.ts +35 -0
  160. package/dist-types/components/consent-dialog-trigger/index.d.ts +2 -1
  161. package/dist-types/components/consent-dialog-trigger/types.d.ts +111 -6
  162. package/dist-types/components/consent-widget/atoms/accordion.d.ts +4 -4
  163. package/dist-types/components/consent-widget/consent-widget.d.ts +1 -1
  164. package/dist-types/components/consent-widget/policy-actions.d.ts +1 -1
  165. package/dist-types/components/integrations/google-map.d.ts +82 -0
  166. package/dist-types/components/integrations/index.d.ts +2 -0
  167. package/dist-types/components/integrations/shared.d.ts +12 -0
  168. package/dist-types/components/integrations/youtube-embed.d.ts +95 -0
  169. package/dist-types/components/shared/policy-actions.d.ts +1 -1
  170. package/dist-types/components/shared/primitives/button.d.ts +36 -2
  171. package/dist-types/components/shared/primitives/legal-links/index.d.ts +1 -1
  172. package/dist-types/components/shared/ui/accordion/accordion.d.ts +2 -2
  173. package/dist-types/components/shared/ui/branding.d.ts +3 -3
  174. package/dist-types/components/shared/ui/button/button.d.ts +1 -1
  175. package/dist-types/components/shared/ui/dialog/dialog.d.ts +1 -1
  176. package/dist-types/components/shared/ui/logo.d.ts +8 -8
  177. package/dist-types/headless.d.ts +1 -0
  178. package/dist-types/hooks/index.d.ts +1 -0
  179. package/dist-types/hooks/use-consent-script.d.ts +80 -0
  180. package/dist-types/index.d.ts +3 -1
  181. package/dist-types/providers/consent-manager-provider.d.ts +1 -1
  182. package/dist-types/server/headers.d.ts +1 -1
  183. package/dist-types/utils/theme-utils.d.ts +1 -1
  184. package/dist-types/version.d.ts +1 -1
  185. package/docs/README.md +155 -76
  186. package/docs/{building-headless-components.md → frameworks/react/building-headless-components.md} +3 -1
  187. package/docs/{callbacks.md → frameworks/react/callbacks.md} +3 -1
  188. package/docs/{components → frameworks/react/components}/consent-banner.md +10 -21
  189. package/docs/{components → frameworks/react/components}/consent-dialog-link.md +8 -5
  190. package/docs/frameworks/react/components/consent-dialog-trigger.md +202 -0
  191. package/docs/{components → frameworks/react/components}/consent-dialog.md +7 -15
  192. package/docs/frameworks/react/components/consent-manager-provider.md +228 -0
  193. package/docs/{components → frameworks/react/components}/consent-widget.md +8 -6
  194. package/docs/{components → frameworks/react/components}/dev-tools.md +9 -6
  195. package/docs/{components → frameworks/react/components}/frame.md +8 -9
  196. package/docs/{concepts → frameworks/react/concepts}/client-modes.md +4 -2
  197. package/docs/{concepts → frameworks/react/concepts}/consent-categories.md +1 -0
  198. package/docs/{concepts → frameworks/react/concepts}/consent-models.md +1 -0
  199. package/docs/{concepts → frameworks/react/concepts}/cookie-management.md +3 -3
  200. package/docs/{concepts → frameworks/react/concepts}/glossary.md +1 -0
  201. package/docs/{concepts → frameworks/react/concepts}/initialization-flow.md +1 -0
  202. package/docs/{concepts → frameworks/react/concepts}/policy-packs.md +1 -0
  203. package/docs/{headless.md → frameworks/react/headless.md} +3 -1
  204. package/docs/{hooks → frameworks/react/hooks}/use-color-scheme.md +1 -0
  205. package/docs/{hooks → frameworks/react/hooks}/use-consent-manager/checking-consent.md +3 -1
  206. package/docs/{hooks → frameworks/react/hooks}/use-consent-manager/location-info.md +3 -1
  207. package/docs/frameworks/react/hooks/use-consent-manager/overview.md +172 -0
  208. package/docs/{hooks → frameworks/react/hooks}/use-consent-manager/setting-consent.md +3 -1
  209. package/docs/{hooks → frameworks/react/hooks}/use-draggable.md +3 -1
  210. package/docs/{hooks → frameworks/react/hooks}/use-focus-trap.md +1 -0
  211. package/docs/{hooks → frameworks/react/hooks}/use-reduced-motion.md +3 -1
  212. package/docs/{hooks → frameworks/react/hooks}/use-ssr-status.md +6 -5
  213. package/docs/{hooks → frameworks/react/hooks}/use-text-direction.md +1 -0
  214. package/docs/frameworks/react/hooks/use-translations.md +55 -0
  215. package/docs/{iab → frameworks/react/iab}/consent-banner.md +9 -12
  216. package/docs/{iab → frameworks/react/iab}/consent-dialog.md +9 -14
  217. package/docs/{iab → frameworks/react/iab}/overview.md +4 -2
  218. package/docs/{iab → frameworks/react/iab}/use-gvl-data.md +3 -2
  219. package/docs/{iframe-blocking.md → frameworks/react/iframe-blocking.md} +8 -9
  220. package/docs/{internationalization.md → frameworks/react/internationalization.md} +13 -3
  221. package/docs/{network-blocker.md → frameworks/react/network-blocker.md} +13 -51
  222. package/docs/{optimization.md → frameworks/react/optimization.md} +3 -2
  223. package/docs/{policy-packs.md → frameworks/react/policy-packs.md} +3 -1
  224. package/docs/{quickstart.md → frameworks/react/quickstart.md} +26 -42
  225. package/docs/frameworks/react/script-loader.md +553 -0
  226. package/docs/{server-side.md → frameworks/react/server-side.md} +9 -4
  227. package/docs/{styling → frameworks/react/styling}/classnames.md +3 -1
  228. package/docs/{styling → frameworks/react/styling}/color-scheme.md +3 -1
  229. package/docs/frameworks/react/styling/css-variables.md +53 -0
  230. package/docs/frameworks/react/styling/overview.md +302 -0
  231. package/docs/frameworks/react/styling/slots.md +94 -0
  232. package/docs/{styling → frameworks/react/styling}/tailwind.md +3 -1
  233. package/docs/frameworks/react/styling/tokens.md +156 -0
  234. package/docs/{troubleshooting.md → frameworks/react/troubleshooting.md} +3 -1
  235. package/docs/integrations/adobe-analytics.md +160 -0
  236. package/docs/integrations/ahrefs-analytics.md +157 -0
  237. package/docs/integrations/amplitude.md +230 -0
  238. package/docs/integrations/building-integrations.md +15 -181
  239. package/docs/integrations/clearbit.md +130 -0
  240. package/docs/integrations/cloudflare-web-analytics.md +126 -0
  241. package/docs/integrations/crisp.md +140 -0
  242. package/docs/integrations/databuddy.md +152 -150
  243. package/docs/integrations/fathom-analytics.md +150 -0
  244. package/docs/integrations/google-maps.md +263 -0
  245. package/docs/integrations/google-tag-manager.md +102 -101
  246. package/docs/integrations/google-tag.md +104 -92
  247. package/docs/integrations/heap.md +219 -0
  248. package/docs/integrations/hightouch.md +199 -0
  249. package/docs/integrations/hotjar.md +143 -0
  250. package/docs/integrations/intercom.md +144 -0
  251. package/docs/integrations/linkedin-insights.md +142 -90
  252. package/docs/integrations/logrocket.md +175 -0
  253. package/docs/integrations/matomo-analytics.md +171 -0
  254. package/docs/integrations/meta-pixel.md +379 -309
  255. package/docs/integrations/microsoft-clarity.md +173 -0
  256. package/docs/integrations/microsoft-uet.md +135 -91
  257. package/docs/integrations/mixpanel-analytics.md +130 -0
  258. package/docs/integrations/overview.md +119 -75
  259. package/docs/integrations/pirsch.md +142 -0
  260. package/docs/integrations/plausible-analytics.md +154 -0
  261. package/docs/integrations/posthog.md +186 -127
  262. package/docs/integrations/promptwatch.md +121 -0
  263. package/docs/integrations/reddit-pixel.md +241 -0
  264. package/docs/integrations/rudderstack.md +271 -0
  265. package/docs/integrations/rybbit-analytics.md +143 -0
  266. package/docs/integrations/segment.md +146 -0
  267. package/docs/integrations/snapchat-pixel.md +163 -0
  268. package/docs/integrations/tiktok-pixel.md +101 -91
  269. package/docs/integrations/umami-analytics.md +148 -0
  270. package/docs/integrations/vercel-analytics.md +141 -0
  271. package/docs/integrations/x-pixel.md +123 -109
  272. package/docs/integrations/youtube.md +193 -0
  273. package/docs/shared/concepts/client-modes.md +103 -0
  274. package/docs/shared/concepts/consent-categories.md +41 -0
  275. package/docs/shared/concepts/consent-models.md +72 -0
  276. package/docs/shared/concepts/cookie-management.md +88 -0
  277. package/docs/shared/concepts/glossary.md +24 -0
  278. package/docs/shared/concepts/initialization-flow.md +105 -0
  279. package/docs/shared/concepts/policy-packs.md +225 -0
  280. package/docs/shared/react/components/consent-banner.md +242 -0
  281. package/docs/shared/react/components/consent-dialog-link.md +45 -0
  282. package/docs/shared/react/components/consent-dialog-trigger.md +185 -0
  283. package/docs/shared/react/components/consent-dialog.md +119 -0
  284. package/docs/shared/react/components/consent-manager-provider.md +183 -0
  285. package/docs/shared/react/components/consent-widget.md +121 -0
  286. package/docs/shared/react/components/dev-tools.md +81 -0
  287. package/docs/shared/react/components/frame.md +52 -0
  288. package/docs/shared/react/guides/building-headless-components.md +110 -0
  289. package/docs/shared/react/guides/callbacks.md +89 -0
  290. package/docs/shared/react/guides/headless.md +31 -0
  291. package/docs/shared/react/guides/iframe-blocking.md +65 -0
  292. package/docs/shared/react/guides/internationalization.md +123 -0
  293. package/docs/shared/react/guides/network-blocker.md +72 -0
  294. package/docs/shared/react/guides/optimization.md +44 -0
  295. package/docs/shared/react/guides/policy-packs.md +173 -0
  296. package/docs/shared/react/guides/script-loader.md +309 -0
  297. package/docs/shared/react/hooks/use-color-scheme.md +31 -0
  298. package/docs/shared/react/hooks/use-consent-manager/checking-consent.md +95 -0
  299. package/docs/shared/react/hooks/use-consent-manager/location-info.md +96 -0
  300. package/docs/shared/react/hooks/use-consent-manager/overview.md +74 -0
  301. package/docs/shared/react/hooks/use-consent-manager/setting-consent.md +93 -0
  302. package/docs/shared/react/hooks/use-draggable.md +30 -0
  303. package/docs/shared/react/hooks/use-focus-trap.md +20 -0
  304. package/docs/shared/react/hooks/use-reduced-motion.md +33 -0
  305. package/docs/shared/react/hooks/use-ssr-status.md +16 -0
  306. package/docs/shared/react/hooks/use-text-direction.md +38 -0
  307. package/docs/shared/react/hooks/use-translations.md +15 -0
  308. package/docs/shared/react/iab/consent-banner.md +60 -0
  309. package/docs/shared/react/iab/consent-dialog.md +76 -0
  310. package/docs/shared/react/iab/overview.md +80 -0
  311. package/docs/shared/react/iab/use-gvl-data.md +21 -0
  312. package/docs/shared/react/styling/classnames.md +93 -0
  313. package/docs/shared/react/styling/color-scheme.md +35 -0
  314. package/docs/shared/react/styling/css-variables.md +53 -0
  315. package/docs/shared/react/styling/overview.md +261 -0
  316. package/docs/shared/react/styling/slots.md +93 -0
  317. package/docs/shared/react/styling/stylesheet-entrypoint.md +8 -0
  318. package/docs/shared/react/styling/tailwind.md +88 -0
  319. package/docs/shared/react/styling/tokens.md +155 -0
  320. package/docs/shared/troubleshooting.md +82 -0
  321. package/package.json +23 -12
  322. package/readme.json +12 -7
  323. package/docs/ai-agents.md +0 -111
  324. package/docs/components/consent-dialog-trigger.md +0 -103
  325. package/docs/components/consent-manager-provider.md +0 -425
  326. package/docs/hooks/use-consent-manager/overview.md +0 -420
  327. package/docs/hooks/use-translations.md +0 -118
  328. package/docs/script-loader.md +0 -321
  329. package/docs/styling/css-variables.md +0 -92
  330. package/docs/styling/overview.md +0 -460
  331. package/docs/styling/slots.md +0 -128
  332. package/docs/styling/tokens.md +0 -216
@@ -0,0 +1,309 @@
1
+ ---
2
+ title: Script Loader
3
+ description: Reference page for script loader.
4
+ group: reference
5
+ ---
6
+ The script loader manages third-party JavaScript based on consent state. You declare scripts in your provider's `scripts` option, and c15t decides when each script should load, stay loaded, unload, or receive a consent update.
7
+
8
+ Use it for analytics, pixels, tag managers, product analytics, and other vendor snippets that should not run until the right consent condition is satisfied. Prebuilt helpers live in [`@c15t/scripts`](/docs/integrations/overview); custom scripts can be declared directly when the vendor is specific to your app.
9
+
10
+ <PackageCommandTabs mode="install" command="@c15t/scripts" />
11
+
12
+ > ℹ️ **Info:**
13
+ > Start with the integrations overview before writing your own script. Built-in helpers encode vendor boot order, consent updates, and common defaults so you do not have to.
14
+ >
15
+ > 📝 **Note:**
16
+ > If you need a vendor c15t does not ship yet, see the custom integration guide. It explains when a one-off Script is enough and when to build a reusable manifest-backed helper.
17
+ >
18
+ > ℹ️ **Info:**
19
+ > The script loader handles JavaScript tags and callback lifecycles. For iframe-only embeds, use the iframe blocking pattern. For UI components such as maps or video players, combine consent state with a component-level placeholder or a dedicated renderable integration.
20
+
21
+ ## Mental Model
22
+
23
+ Every script you register has the same lifecycle. c15t evaluates each script against the current consent state, then drives it through a small number of states:
24
+
25
+ 1. **Pending** — registered but waiting for consent. Nothing is in the DOM yet.
26
+ 2. **Loaded** — consent matched, c15t injected the script (or ran callbacks for callback-only scripts).
27
+ 3. **Updated** — already loaded, consent state changed, `onConsentChange` ran so the SDK can react.
28
+ 4. **Unloaded** — consent was revoked. c15t removed the script element unless you opted into persistence.
29
+
30
+ Four lifecycle callbacks let you hook into transitions: `onBeforeLoad`, `onLoad`, `onConsentChange`, and `onError`. Two flags — [`alwaysLoad`](#always-load) and [`persistAfterConsentRevoked`](#persist-after-revocation) — change how c15t treats consent boundaries. Everything else (DOM placement, ad-block evasion, dynamic management) is a refinement on top of this core model.
31
+
32
+ ## Choose the Right Approach
33
+
34
+ Most projects mix more than one style. Pick the smallest one that keeps consent behavior obvious:
35
+
36
+ |Style|Use when|
37
+ |--|--|
38
+ |**Built-in helper** from `@c15t/scripts`|c15t already ships the vendor. See the [integrations overview](/docs/integrations/overview).|
39
+ |**Plain `Script`**|One-off app code with simple load and callback behavior.|
40
+ |**Callback-only `Script`**|Another package already loaded the SDK; c15t only synchronizes consent.|
41
+ |**Manifest-backed helper**|Reusable vendor integration with structured setup phases, queues, stubs, or a vendor consent API.|
42
+ |**Iframe / renderable integration**|Vendor exposes an iframe or React component, not just a `<script>` tag.|
43
+
44
+ ## Script Types
45
+
46
+ ### Standard Scripts
47
+
48
+ Standard scripts load an external JavaScript file via a `<script>` tag. This is the default for most analytics and pixel SDKs:
49
+
50
+ ```tsx
51
+ {
52
+ id: 'analytics',
53
+ src: 'https://cdn.example.com/analytics.js',
54
+ category: 'measurement',
55
+ }
56
+ ```
57
+
58
+ ### Inline Scripts
59
+
60
+ Inline scripts execute JavaScript from `textContent` instead of loading a URL. Use these sparingly; a manifest-backed helper is usually better for reusable vendor code.
61
+
62
+ ```tsx
63
+ {
64
+ id: 'gtag-config',
65
+ textContent: `
66
+ window.dataLayer = window.dataLayer || [];
67
+ function gtag(){dataLayer.push(arguments);}
68
+ gtag('js', new Date());
69
+ gtag('config', 'G-XXXXXX');
70
+ `,
71
+ category: 'measurement',
72
+ }
73
+ ```
74
+
75
+ ### Callback-Only Scripts
76
+
77
+ Callback-only scripts do not inject a script tag. They run lifecycle callbacks when consent allows them to. Use this when another package has already loaded the SDK and c15t only needs to drive consent:
78
+
79
+ ```tsx
80
+ {
81
+ id: 'posthog-consent',
82
+ callbackOnly: true,
83
+ category: 'measurement',
84
+ onLoad: ({ hasConsent }) => {
85
+ if (hasConsent) {
86
+ posthog.opt_in_capturing();
87
+ }
88
+ },
89
+ onConsentChange: ({ hasConsent }) => {
90
+ if (hasConsent) {
91
+ posthog.opt_in_capturing();
92
+ } else {
93
+ posthog.opt_out_capturing();
94
+ }
95
+ },
96
+ }
97
+ ```
98
+
99
+ ### Manifest-Backed Helpers
100
+
101
+ Built-in integrations in `@c15t/scripts` are manifest-backed. A manifest describes vendor setup as structured phases, then c15t compiles it into a `Script`. Manifests keep queue stubs, script URLs, consent signaling, and post-load work consistent across apps and they are safe to ship from a server.
102
+
103
+ Use a manifest-backed helper when:
104
+
105
+ * the integration should be reused across projects,
106
+ * the vendor snippet has ordered setup steps,
107
+ * the vendor exposes a consent API,
108
+ * or you plan to contribute the integration back to c15t.
109
+
110
+ Read the [custom integration guide](/docs/integrations/building-integrations) for the manifest contract, phases, and testing checklist.
111
+
112
+ ### Iframe And Renderable Integrations
113
+
114
+ Some vendors are not just script tags. YouTube embeds, maps, calendars, and checkout widgets often need a visible component, a placeholder, or an iframe.
115
+
116
+ * For iframe-only embeds, gate the iframe `src` with the [iframe blocking](/docs/frameworks/react/iframe-blocking) pattern instead of loading a script just to hide an iframe.
117
+ * For SDK-backed UI, use the script loader for the shared SDK and render the component only when consent and SDK readiness agree.
118
+ * Use `YouTubeEmbed` for the iframe-only YouTube candidate and `GoogleMap` for the callback-based SDK candidate.
119
+ * Use `useConsentScript()` when building custom wrappers. It registers scripts through the consent store, follows `loadedScripts`, and returns a promise-shaped readiness contract for callback-based SDKs.
120
+
121
+ ## Lifecycle Callbacks
122
+
123
+ Every script supports four callbacks. Each receives a `ScriptCallbackInfo` payload (id, element, hasConsent, consents):
124
+
125
+ * `onBeforeLoad` — runs before the script tag is injected. Create globals, queues, or vendor stubs here.
126
+ * `onLoad` — runs after the browser loads the script. Call vendor `init()` APIs here.
127
+ * `onConsentChange` — runs for loaded scripts when consent changes. Forward the new consent state to the vendor SDK.
128
+ * `onError` — runs when the script fails to load. Record diagnostics or render a fallback.
129
+
130
+ ```tsx
131
+ {
132
+ id: 'analytics',
133
+ src: 'https://analytics.example.com/v2.js',
134
+ category: 'measurement',
135
+ onBeforeLoad: ({ id }) => {
136
+ window.analyticsQueue = window.analyticsQueue || [];
137
+ },
138
+ onLoad: () => {
139
+ window.analytics.init('my-key');
140
+ },
141
+ onError: ({ error }) => {
142
+ console.error('Failed to load analytics:', error);
143
+ },
144
+ onConsentChange: ({ hasConsent }) => {
145
+ window.analytics.setConsent(hasConsent);
146
+ },
147
+ }
148
+ ```
149
+
150
+ ## Consent Conditions
151
+
152
+ The `category` field accepts a `HasCondition`. It can be a single consent category or a logical expression:
153
+
154
+ ```tsx
155
+ // Simple: requires measurement consent
156
+ { category: 'measurement' }
157
+
158
+ // AND: requires both measurement and marketing
159
+ { category: { and: ['measurement', 'marketing'] } }
160
+
161
+ // OR: requires either measurement or marketing
162
+ { category: { or: ['measurement', 'marketing'] } }
163
+ ```
164
+
165
+ Consent categories use the same names as the rest of c15t (`necessary`, `functionality`, `experience`, `measurement`, `marketing`).
166
+
167
+ ## Persistence Options
168
+
169
+ ### Always Load
170
+
171
+ `alwaysLoad` loads the script regardless of whether its category is currently granted. Use it only when the vendor must be present early **and** has a reliable consent API of its own — Google Tag Manager with Consent Mode is the canonical example.
172
+
173
+ ```tsx
174
+ {
175
+ id: 'google-tag-manager',
176
+ src: 'https://www.googletagmanager.com/gtm.js?id=GTM-XXXX',
177
+ category: 'measurement',
178
+ alwaysLoad: true,
179
+ }
180
+ ```
181
+
182
+ When `alwaysLoad` is on, `onConsentChange` becomes mandatory: it is how the loaded SDK learns about every transition.
183
+
184
+ > ⚠️ **Warning:**
185
+ > alwaysLoad shifts compliance responsibility to the vendor integration. Make sure the script receives denied-by-default consent signals before it can track.
186
+
187
+ ### Persist After Revocation
188
+
189
+ `persistAfterConsentRevoked` keeps a script in the page after consent is revoked instead of unloading it. Use it only when the vendor exposes a runtime consent toggle — otherwise unloading is safer because removing the element guarantees the SDK stops.
190
+
191
+ ```tsx
192
+ {
193
+ id: 'error-tracking',
194
+ src: 'https://errors.example.com/track.js',
195
+ category: 'measurement',
196
+ persistAfterConsentRevoked: true,
197
+ onConsentChange: ({ hasConsent }) => {
198
+ window.ErrorTracker.setConsent(hasConsent);
199
+ },
200
+ }
201
+ ```
202
+
203
+ As with `alwaysLoad`, `onConsentChange` is how the persisted SDK learns about consent updates.
204
+
205
+ ### `alwaysLoad` vs `persistAfterConsentRevoked`
206
+
207
+ These two flags answer different questions. Use this table to keep them straight:
208
+
209
+ |Question|`alwaysLoad`|`persistAfterConsentRevoked`|
210
+ |--|--|--|
211
+ |Loads before consent is granted?|Yes|No (waits for consent like a normal script)|
212
+ |Stays loaded after consent is revoked?|Yes|Yes|
213
+ |Requires a vendor consent API?|Yes|Yes|
214
+
215
+ ## DOM Placement
216
+
217
+ Control where the script is injected and whether the element id is anonymized:
218
+
219
+ ```tsx
220
+ {
221
+ id: 'widget',
222
+ src: 'https://widget.example.com/embed.js',
223
+ category: 'experience',
224
+ target: 'body', // 'head' (default) or 'body'
225
+ anonymizeId: true, // default: true, hides the c15t script id from ad blockers
226
+ nonce: 'abc123', // optional CSP nonce
227
+ }
228
+ ```
229
+
230
+ Set `anonymizeId: false` only when another script or test needs a stable DOM id. Pass `nonce` when your CSP requires it; c15t applies it directly to the generated `<script>` element.
231
+
232
+ ## Dynamic Management
233
+
234
+ Framework packages expose script-manager methods so integrations can be added, removed, or inspected at runtime. Use this for tenant-specific tools, feature-flagged scripts, or vendors that are configured after sign-in:
235
+
236
+ * `setScripts(scripts)` — registers script definitions and immediately evaluates them against consent.
237
+ * `removeScript(id)` — removes a definition and unloads its element if needed.
238
+ * `isScriptLoaded(id)` — returns whether c15t has loaded a script.
239
+ * `getLoadedScriptIds()` — returns every currently loaded script id.
240
+
241
+ Dynamic scripts should still use stable ids. If the same vendor is added repeatedly with different ids, c15t treats each call as a new script.
242
+
243
+ ## Calling Vendor APIs From Your App
244
+
245
+ The script loader controls **when the vendor SDK loads**. It does not intercept calls your application code makes to that SDK afterwards. Whether your event calls are safe before consent is granted depends on the script's persistence flags:
246
+
247
+ |Vendor pattern|What c15t does|What your app code must do|
248
+ |--|--|--|
249
+ |Consent-gated load, unloaded on revoke (e.g. cookieless analytics)|Script not in DOM until consent granted; removed on revoke. Global is `undefined` outside that window.|**Guard every call.** Unguarded `window.vendor.track(...)` throws when the global is absent.|
250
+ |Consent-gated load with `persistAfterConsentRevoked` (e.g. Meta Pixel)|Script not in DOM until consent granted; stays after revoke. c15t calls vendor's consent-revoke API on revocation.|Guard calls only for the pre-initial-consent window. Once loaded, the SDK handles its own suppression.|
251
+ |`alwaysLoad: true` with a vendor consent API (e.g. GTM, gtag, Databuddy, PostHog)|Script in DOM on page start; c15t signals consent state through the vendor's API.|Calls are safe — the vendor SDK suppresses transmission when consent is denied.|
252
+ |No app-facing API (e.g. Cloudflare Web Analytics)|Script in/out of DOM based on consent. Tracking is fully automatic.|Nothing to guard.|
253
+
254
+ The safe pattern in React is to read consent state through `useConsentManager().has(category)` before calling the SDK:
255
+
256
+ ```tsx
257
+ import { useCallback } from 'react';
258
+ import { useConsentManager } from '@c15t/react';
259
+
260
+ function useTrackSignup() {
261
+ const { has } = useConsentManager();
262
+
263
+ return useCallback(() => {
264
+ if (has('measurement')) {
265
+ window.fathom?.trackEvent('signup');
266
+ }
267
+ }, [has]);
268
+ }
269
+
270
+ function SignupButton() {
271
+ const trackSignup = useTrackSignup();
272
+
273
+ return <button onClick={trackSignup}>Sign up</button>;
274
+ }
275
+ ```
276
+
277
+ From non-React code, read the consent store directly:
278
+
279
+ ```ts
280
+ import { getOrCreateConsentRuntime } from 'c15t';
281
+
282
+ const { consentStore } = getOrCreateConsentRuntime();
283
+
284
+ if (consentStore.getState().has('measurement')) {
285
+ window.fathom?.trackEvent('signup');
286
+ }
287
+ ```
288
+
289
+ Each [integration page](/docs/integrations/overview) includes a vendor-specific **Tracking events in your app** block that names which pattern applies.
290
+
291
+ ## Debugging Checklist
292
+
293
+ When a script does not behave as expected:
294
+
295
+ 1. Confirm the script's `category` matches the consent that has been granted.
296
+ 2. Check whether the script is `alwaysLoad` or consent-gated.
297
+ 3. Confirm `onBeforeLoad` creates any globals before the vendor code reads them.
298
+ 4. Confirm `onConsentChange` updates persisted or always-loaded scripts when consent changes.
299
+ 5. Check whether the browser or an ad blocker blocked the request.
300
+ 6. Use c15t devtools to inspect script lifecycle events when available.
301
+
302
+ ## API Reference
303
+
304
+ |Property|Value|
305
+ |:--|:--|
306
+ |Type Name|\`Script\`|
307
+ |Source Path|\`./packages/core/src/libs/script-loader/types.ts\`|
308
+
309
+ \*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.\*
@@ -0,0 +1,31 @@
1
+ ---
2
+ title: Use Color Scheme
3
+ description: Reference page for use color scheme.
4
+ group: reference
5
+ ---
6
+ ## Parameters
7
+
8
+ |Value|Behavior|
9
+ |--|--|
10
+ |`'light'`|Force light mode|
11
+ |`'dark'`|Force dark mode|
12
+ |`'system'`|Follow `prefers-color-scheme` media query|
13
+ |`null`|Disable - c15t won't manage color scheme|
14
+ |`undefined`|No-op|
15
+
16
+ ## Provider-Level Configuration
17
+
18
+ You can also set the color scheme on the provider without using this hook:
19
+
20
+ ```tsx
21
+ <ConsentManagerProvider
22
+ options={{
23
+ colorScheme: 'system',
24
+ // ...
25
+ }}
26
+ >
27
+ ```
28
+
29
+ ## System Preference Detection
30
+
31
+ When set to `'system'`, the hook listens for changes to the `prefers-color-scheme` media query and updates automatically when the user changes their OS theme.
@@ -0,0 +1,95 @@
1
+ ---
2
+ title: Checking Consent
3
+ description: Reference page for checking consent.
4
+ group: reference
5
+ ---
6
+ ## has(condition)
7
+
8
+ The `has()` method evaluates whether the current consent state satisfies a condition. It supports simple category checks and complex logical expressions.
9
+
10
+ ### Simple Check
11
+
12
+ ```tsx
13
+ const { has } = useConsentManager();
14
+
15
+ if (has('measurement')) {
16
+ // User has granted measurement consent
17
+ }
18
+ ```
19
+
20
+ ### AND Logic
21
+
22
+ All conditions must be true:
23
+
24
+ ```tsx
25
+ has({ and: ['measurement', 'marketing'] })
26
+ // true only if BOTH measurement AND marketing are granted
27
+ ```
28
+
29
+ ### OR Logic
30
+
31
+ At least one condition must be true:
32
+
33
+ ```tsx
34
+ has({ or: ['measurement', 'marketing'] })
35
+ // true if EITHER measurement OR marketing is granted
36
+ ```
37
+
38
+ ### NOT Logic
39
+
40
+ Negates a condition:
41
+
42
+ ```tsx
43
+ has({ not: 'marketing' })
44
+ // true if marketing consent is NOT granted
45
+ ```
46
+
47
+ ### Nested Conditions
48
+
49
+ Combine operators for complex logic:
50
+
51
+ ```tsx
52
+ has({
53
+ and: [
54
+ 'necessary',
55
+ { or: ['measurement', 'marketing'] },
56
+ { not: 'functionality' },
57
+ ],
58
+ })
59
+ // true if: necessary AND (measurement OR marketing) AND NOT functionality
60
+ ```
61
+
62
+ ### HasCondition Type
63
+
64
+ ```ts
65
+ type HasCondition<CategoryType> =
66
+ | CategoryType // "measurement"
67
+ | { and: HasCondition[] | HasCondition } // { and: ["a", "b"] }
68
+ | { or: HasCondition[] | HasCondition } // { or: ["a", "b"] }
69
+ | { not: HasCondition } // { not: "a" }
70
+ ```
71
+
72
+ ## hasConsented()
73
+
74
+ Returns `true` if the user has made any consent choice (accepted, rejected, or customized). Returns `false` if no consent has been recorded yet.
75
+
76
+ ```tsx
77
+ const { hasConsented } = useConsentManager();
78
+
79
+ if (hasConsented()) {
80
+ // User has previously made a consent choice
81
+ } else {
82
+ // First visit — no consent recorded
83
+ }
84
+ ```
85
+
86
+ ## getDisplayedConsents()
87
+
88
+ Returns the consent types that should be displayed in the UI (based on active `consentCategories` and each type's `display` property):
89
+
90
+ ```tsx
91
+ const { getDisplayedConsents } = useConsentManager();
92
+
93
+ const visibleCategories = getDisplayedConsents();
94
+ // Returns ConsentType[] with name, description, defaultValue, etc.
95
+ ```
@@ -0,0 +1,96 @@
1
+ ---
2
+ title: Location Info
3
+ description: Reference page for location info.
4
+ group: reference
5
+ ---
6
+ ## locationInfo
7
+
8
+ The `locationInfo` state contains the user's detected geographic information:
9
+
10
+ ```tsx
11
+ const { locationInfo } = useConsentManager();
12
+
13
+ if (locationInfo) {
14
+ console.log(locationInfo.jurisdiction); // 'GDPR', 'CCPA', etc.
15
+ console.log(locationInfo.countryCode); // 'DE', 'US', etc.
16
+ console.log(locationInfo.regionCode); // 'BY', 'CA', etc.
17
+ }
18
+ ```
19
+
20
+ `locationInfo` is `null` until the backend responds with geolocation data (or in offline mode if no overrides are set).
21
+
22
+ ## Jurisdiction Codes
23
+
24
+ |Code|Region|Consent Model|
25
+ |--|--|--|
26
+ |`GDPR`|European Union|opt-in|
27
+ |`UK_GDPR`|United Kingdom|opt-in|
28
+ |`CH`|Switzerland|opt-in|
29
+ |`BR`|Brazil (LGPD)|opt-in|
30
+ |`APPI`|Japan|opt-in|
31
+ |`PIPA`|South Korea|opt-in|
32
+ |`PIPEDA`|Canada (excl. Quebec)|opt-out|
33
+ |`QC_LAW25`|Quebec, Canada|opt-in|
34
+ |`CCPA`|California, USA|opt-out|
35
+ |`AU`|Australia|opt-out|
36
+ |`NONE`|No jurisdiction|null model|
37
+
38
+ ## setOverrides()
39
+
40
+ Override detected values for testing or manual configuration. This triggers a re-fetch of consent banner data with the new values:
41
+
42
+ ```tsx
43
+ const { setOverrides } = useConsentManager();
44
+
45
+ // Override country (triggers jurisdiction detection)
46
+ await setOverrides({ country: 'DE' });
47
+
48
+ // Override language
49
+ await setOverrides({ language: 'de' });
50
+
51
+ // Override both
52
+ await setOverrides({ country: 'US', region: 'CA', language: 'es' });
53
+ ```
54
+
55
+ ## setLocationInfo()
56
+
57
+ Directly set location info without triggering a re-fetch:
58
+
59
+ ```tsx
60
+ const { setLocationInfo } = useConsentManager();
61
+
62
+ setLocationInfo({
63
+ jurisdiction: 'GDPR',
64
+ countryCode: 'DE',
65
+ regionCode: 'BY',
66
+ });
67
+ ```
68
+
69
+ ## Testing Different Jurisdictions
70
+
71
+ A development-only component for testing consent behavior across jurisdictions:
72
+
73
+ ```tsx
74
+ function JurisdictionTester() {
75
+ const { setOverrides, model, locationInfo } = useConsentManager();
76
+
77
+ const testCases = [
78
+ { label: 'GDPR', country: 'DE' },
79
+ { label: 'CCPA', country: 'US', region: 'CA' },
80
+ { label: 'PIPEDA', country: 'CA', region: undefined },
81
+ { label: 'QC_LAW25', country: 'CA', region: 'QC' },
82
+ { label: 'NONE', country: 'US', region: 'TX' },
83
+ ];
84
+
85
+ return (
86
+ <div>
87
+ <p>Current: {locationInfo?.jurisdiction ?? 'none'} → model: {model}</p>
88
+ {testCases.map((tc) => (
89
+ <button key={tc.label} onClick={() => setOverrides({ country: tc.country, region: tc.region })}>
90
+ Test as {tc.label}
91
+ </button>
92
+ ))}
93
+ </div>
94
+ );
95
+ }
96
+ ```
@@ -0,0 +1,74 @@
1
+ ---
2
+ title: Overview
3
+ description: Reference page for overview.
4
+ group: reference
5
+ ---
6
+ > ⚠️ **Warning:**
7
+ > Must be used within a ConsentManagerProvider. Throws an error if used outside the provider.
8
+
9
+ ## State Properties
10
+
11
+ |Property|Value|
12
+ |:--|:--|
13
+ |Type Name|\`StoreRuntimeState\`|
14
+ |Source Path|\`./packages/core/src/store/type.ts\`|
15
+
16
+ \*ExtractedTypeTable: Could not extract "StoreRuntimeState" from "./packages/core/src/store/type.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
17
+
18
+ ## Action Methods
19
+
20
+ |Property|Value|
21
+ |:--|:--|
22
+ |Type Name|\`StoreActions\`|
23
+ |Source Path|\`./packages/core/src/store/type.ts\`|
24
+
25
+ \*ExtractedTypeTable: Could not extract "StoreActions" from "./packages/core/src/store/type.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
26
+
27
+ ## Key Types
28
+
29
+ ### ConsentState
30
+
31
+ A record mapping consent category names to their boolean values:
32
+
33
+ ```ts
34
+ type ConsentState = Record<AllConsentNames, boolean>;
35
+ // Example: { necessary: true, measurement: true, marketing: false }
36
+ ```
37
+
38
+ ### ConsentInfo
39
+
40
+ Metadata about when and how consent was recorded:
41
+
42
+ ```ts
43
+ interface ConsentInfo {
44
+ time: number; // Epoch timestamp when consent was recorded
45
+ subjectId?: string; // Client-generated subject ID (sub_xxx format)
46
+ externalId?: string; // External user ID linked via identifyUser()
47
+ identityProvider?: string; // Identity provider (e.g. 'clerk', 'auth0')
48
+ }
49
+ ```
50
+
51
+ ### LocationInfo
52
+
53
+ Detected geographic location from the c15t backend:
54
+
55
+ ```ts
56
+ interface LocationInfo {
57
+ countryCode: string; // ISO 3166-1 alpha-2 (e.g. 'DE')
58
+ regionCode: string; // Region/state code (e.g. 'BY')
59
+ jurisdiction: string; // Applicable jurisdiction (e.g. 'GDPR', 'CCPA')
60
+ }
61
+ ```
62
+
63
+ ### Model
64
+
65
+ The active consent model:
66
+
67
+ ```ts
68
+ type Model = 'opt-in' | 'opt-out' | 'iab' | null;
69
+ ```
70
+
71
+ * `'opt-in'` — Explicit consent required before tracking (GDPR)
72
+ * `'opt-out'` — Tracking allowed by default, user can opt out (CCPA)
73
+ * `'iab'` — IAB TCF 2.3 compliance mode
74
+ * `null` — No jurisdiction detected yet
@@ -0,0 +1,93 @@
1
+ ---
2
+ title: Setting Consent
3
+ description: Reference page for setting consent.
4
+ group: reference
5
+ ---
6
+ ## saveConsents(type)
7
+
8
+ The primary way to persist consent. Accepts one of three strategies:
9
+
10
+ ```tsx
11
+ const { saveConsents } = useConsentManager();
12
+
13
+ // Accept all - sets every active category to true
14
+ await saveConsents('all');
15
+
16
+ // Reject all - only necessary stays true, everything else false
17
+ await saveConsents('necessary');
18
+
19
+ // Save current selections - persists whatever the user toggled
20
+ await saveConsents('custom');
21
+ ```
22
+
23
+ **What happens when you call saveConsents:**
24
+
25
+ 1. Consent state is updated in the store
26
+ 2. UI closes (activeUI → 'none')
27
+ 3. Consent is saved to localStorage and cookie
28
+ 4. If consent was revoked and `reloadOnConsentRevoked` is true, the page reloads
29
+ 5. Otherwise, scripts/iframes/network blocker are updated
30
+ 6. Consent is synced to the backend API
31
+
32
+ ## setConsent(name, value)
33
+
34
+ Updates a single consent category AND automatically saves it. Use this for simple one-off consent changes:
35
+
36
+ ```tsx
37
+ const { setConsent } = useConsentManager();
38
+
39
+ // Grant measurement consent immediately
40
+ setConsent('measurement', true);
41
+
42
+ // Revoke marketing consent immediately
43
+ setConsent('marketing', false);
44
+ ```
45
+
46
+ ## setSelectedConsent(name, value)
47
+
48
+ Updates the selection state without saving. This is what dialog toggles use - the user can flip toggles without committing until they click "Save":
49
+
50
+ ```tsx
51
+ const { setSelectedConsent, saveConsents } = useConsentManager();
52
+
53
+ // User toggles measurement on
54
+ setSelectedConsent('measurement', true);
55
+
56
+ // User toggles marketing off
57
+ setSelectedConsent('marketing', false);
58
+
59
+ // User clicks "Save" - now it persists
60
+ await saveConsents('custom');
61
+ ```
62
+
63
+ ## resetConsents()
64
+
65
+ Resets all consent preferences to their default values and clears stored consent:
66
+
67
+ ```tsx
68
+ const { resetConsents } = useConsentManager();
69
+
70
+ resetConsents();
71
+ // All consents back to defaults, consent info cleared
72
+ ```
73
+
74
+ ## Accept All / Reject All Patterns
75
+
76
+ Common patterns for banner buttons:
77
+
78
+ ```tsx
79
+ function ConsentActions() {
80
+ const { saveConsents } = useConsentManager();
81
+
82
+ return (
83
+ <div>
84
+ <button onClick={() => saveConsents('necessary')}>
85
+ Reject All
86
+ </button>
87
+ <button onClick={() => saveConsents('all')}>
88
+ Accept All
89
+ </button>
90
+ </div>
91
+ );
92
+ }
93
+ ```