@c15t/react 3.0.0-alpha.1 → 3.0.0-alpha.10
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 +96 -70
- package/README.md +21 -17
- package/SKILL.md +34 -0
- package/dist/aggregate-components.js +1 -1
- package/dist/chunk-warming.js +1 -1
- package/dist/component-hooks/use-headless-consent-ui.js +1 -1
- package/dist/component-hooks/use-headless-iab-consent-ui.js +1 -1
- package/dist/component-hooks/use-panel-trigger.js +1 -1
- package/dist/components/consent-gate/atoms.js +1 -0
- package/dist/components/consent-gate/consent-gate.js +2 -0
- package/dist/components/consent-gate/frame.js +2 -0
- package/dist/components/consent-gate/index.js +2 -0
- package/dist/components/consent-preferences-link/consent-preferences-link.js +1 -1
- package/dist/components/iab-panel/atoms/card.js +1 -1
- package/dist/components/iab-panel/atoms/feature-item.js +2 -0
- package/dist/components/iab-panel/atoms/header.js +1 -1
- package/dist/components/iab-panel/atoms/purpose-item.js +1 -1
- package/dist/components/iab-panel/atoms/root.js +1 -1
- package/dist/components/iab-panel/atoms/stack-item.js +1 -1
- package/dist/components/iab-panel/atoms/vendor-list.js +1 -1
- package/dist/components/iab-panel/hooks/use-gvl-data.js +1 -1
- package/dist/components/iab-panel/iab-panel.js +1 -1
- package/dist/components/iab-panel/index.js +1 -1
- package/dist/components/iab-prompt/atoms/overlay.js +1 -1
- package/dist/components/iab-prompt/atoms/root.js +1 -1
- package/dist/components/panel/atoms/card.js +1 -1
- package/dist/components/panel/atoms/overlay.js +1 -1
- package/dist/components/panel/atoms/root.js +1 -1
- package/dist/components/panel/panel.js +1 -1
- package/dist/components/panel-trigger/atoms/button.js +1 -1
- package/dist/components/panel-trigger/atoms/icon.js +1 -1
- package/dist/components/panel-trigger/atoms/root.js +1 -1
- package/dist/components/panel-trigger/atoms/toolbar.js +1 -1
- package/dist/components/panel-trigger/atoms/trigger-icons.js +1 -0
- package/dist/components/panel-trigger/panel-trigger-toolbar.js +1 -1
- package/dist/components/panel-trigger/panel-trigger.js +1 -1
- package/dist/components/preferences/atoms/accordion.js +1 -1
- package/dist/components/preferences/atoms/root.js +1 -1
- package/dist/components/preferences/atoms/vendor-list.js +1 -0
- package/dist/components/preferences/index.js +1 -1
- package/dist/components/prompt/atoms/early-tap-script.js +2 -0
- package/dist/components/prompt/atoms/overlay.js +1 -1
- package/dist/components/prompt/atoms/root.js +1 -1
- package/dist/components/prompt/components.js +1 -1
- package/dist/components/prompt/policy-actions.js +1 -1
- package/dist/components/prompt/prompt.js +1 -1
- package/dist/components/shared/dialog-sheets.js +1 -0
- package/dist/components/shared/first-paint-sheets.js +1 -0
- package/dist/components/shared/iab-dialog-sheets.js +1 -0
- package/dist/components/shared/iab-first-paint-sheets.js +1 -0
- package/dist/components/shared/libs/compose-refs.js +1 -0
- package/dist/components/shared/libs/slot.js +1 -1
- package/dist/components/shared/primitives/button.js +1 -1
- package/dist/components/shared/primitives/legal-links/index.js +1 -1
- package/dist/components/shared/streamed-surface.js +2 -0
- package/dist/components/shared/surface-styles.js +2 -0
- package/dist/components/shared/ui/dialog/dialog.js +1 -1
- package/dist/components/shared/ui/icon.js +1 -1
- package/dist/components/shared/ui/logo.js +1 -1
- package/dist/components/shared/ui/preference-item/preference-item.js +1 -1
- package/dist/consent-gate.js +2 -0
- package/dist/consent-theme.js +1 -0
- package/dist/context/consent-tracking-context.js +1 -1
- package/dist/context/index.js +1 -1
- package/dist/context.js +1 -1
- package/dist/devtools-launcher.js +2 -0
- package/dist/devtools.js +1 -1
- package/dist/draft-context.js +2 -0
- package/dist/draft.js +1 -1
- package/dist/external-iab-context.js +1 -1
- package/dist/gpp.js +2 -0
- package/dist/headless.js +1 -1
- package/dist/hooks/use-color-scheme.js +1 -1
- package/dist/hooks/use-committed-ref.js +2 -0
- package/dist/hooks/use-focus-trap.js +1 -1
- package/dist/hooks/use-headless-iab-consent-ui.js +1 -1
- package/dist/hooks/use-iab-policy-guard.js +1 -0
- package/dist/hooks/use-late-entry.js +2 -0
- package/dist/hooks.js +1 -1
- package/dist/iab/styles.tw3.css +5 -45
- package/dist/iab-context.js +1 -1
- package/dist/index-parts/consent-banner.js +1 -0
- package/dist/index-parts/consent-dialog-link.js +1 -0
- package/dist/index-parts/consent-dialog-trigger.js +1 -0
- package/dist/index-parts/consent-dialog.js +1 -0
- package/dist/index-parts/consent-gate.js +1 -0
- package/dist/index-parts/core.js +1 -0
- package/dist/index-parts/draft.js +1 -0
- package/dist/index-parts/frame.js +1 -0
- package/dist/index-parts/hooks.js +1 -0
- package/dist/index-parts/hosted.js +1 -0
- package/dist/index-parts/module-hooks.js +1 -0
- package/dist/index-parts/offline.js +1 -0
- package/dist/index-parts/presets.js +1 -0
- package/dist/index-parts/provider.js +1 -0
- package/dist/index-parts/theme.js +1 -0
- package/dist/index-parts/translations.js +1 -0
- package/dist/index.js +1 -1
- package/dist/kernel-selector.js +1 -0
- package/dist/modes.js +1 -0
- package/dist/module-hooks/iframe-blocker.js +1 -1
- package/dist/module-hooks/network-blocker.js +1 -1
- package/dist/module-hooks/network-hold.js +2 -0
- package/dist/module-hooks/persistence.js +1 -1
- package/dist/panel-link.js +1 -1
- package/dist/panel-trigger.js +1 -1
- package/dist/panel.js +1 -1
- package/dist/postcss-tailwind3.js +1 -0
- package/dist/preferences.js +1 -2
- package/dist/provider.js +1 -1
- package/dist/server/fetch-ssr-data.js +1 -1
- package/dist/server/headers.js +1 -1
- package/dist/server/normalize-url.js +1 -1
- package/dist/styles.tw3.css +33 -51
- package/dist/transports/hosted.js +1 -0
- package/dist/transports/manifest.js +1 -0
- package/dist/transports/offline.js +1 -1
- package/dist/utils/deferred-module.js +2 -0
- package/dist/utils/merge-slot-props.js +1 -1
- package/dist/utils/theme-utils.js +1 -1
- package/dist/version.js +1 -1
- package/dist-types/aggregate-components.d.ts +2 -2
- package/dist-types/chunk-warming.d.ts +45 -8
- package/dist-types/component-hooks/use-headless-consent-ui.d.ts +5 -5
- package/dist-types/component-hooks/use-headless-iab-consent-ui.d.ts +2 -2
- package/dist-types/components/consent-gate/atoms.d.ts +11 -0
- package/dist-types/components/consent-gate/consent-gate.d.ts +2 -0
- package/dist-types/components/consent-gate/frame.d.ts +19 -0
- package/dist-types/components/consent-gate/index.d.ts +25 -0
- package/dist-types/components/{frame → consent-gate}/types.d.ts +7 -7
- package/dist-types/components/consent-preferences-link/consent-preferences-link.d.ts +1 -1
- package/dist-types/components/consent-preferences-link/index.d.ts +1 -1
- package/dist-types/components/iab-panel/atoms/feature-item.d.ts +28 -0
- package/dist-types/components/iab-panel/atoms/purpose-item.d.ts +5 -2
- package/dist-types/components/iab-panel/atoms/stack-item.d.ts +7 -2
- package/dist-types/components/iab-panel/atoms/vendor-list.d.ts +1 -1
- package/dist-types/components/iab-panel/iab-panel.d.ts +3 -3
- package/dist-types/components/iab-panel/index.d.ts +29 -26
- package/dist-types/components/iab-panel/use-iab-translations.d.ts +4 -0
- package/dist-types/components/iab-prompt/iab-prompt.d.ts +3 -3
- package/dist-types/components/iab-prompt/index.d.ts +19 -19
- package/dist-types/components/panel/atoms/card.d.ts +5 -4
- package/dist-types/components/panel/atoms/overlay.d.ts +1 -1
- package/dist-types/components/panel/index.d.ts +8 -8
- package/dist-types/components/panel/panel.d.ts +3 -3
- package/dist-types/components/panel-link/index.d.ts +1 -1
- package/dist-types/components/panel-trigger/atoms/button.d.ts +1 -1
- package/dist-types/components/panel-trigger/atoms/icon.d.ts +1 -1
- package/dist-types/components/panel-trigger/atoms/root.d.ts +2 -2
- package/dist-types/components/panel-trigger/atoms/toolbar.d.ts +2 -2
- package/dist-types/components/panel-trigger/atoms/trigger-icons.d.ts +25 -0
- package/dist-types/components/panel-trigger/index.d.ts +4 -4
- package/dist-types/components/panel-trigger/panel-trigger-toolbar.d.ts +1 -1
- package/dist-types/components/panel-trigger/panel-trigger.d.ts +9 -17
- package/dist-types/components/panel-trigger/types.d.ts +1 -1
- package/dist-types/components/preferences/atoms/accordion.d.ts +6 -4
- package/dist-types/components/preferences/atoms/button.d.ts +1 -1
- package/dist-types/components/preferences/atoms/footer.d.ts +1 -1
- package/dist-types/components/preferences/atoms/root.d.ts +1 -1
- package/dist-types/components/preferences/atoms/vendor-list.d.ts +23 -0
- package/dist-types/components/preferences/index.d.ts +14 -12
- package/dist-types/components/preferences/policy-actions.d.ts +2 -2
- package/dist-types/components/preferences/preferences.d.ts +1 -1
- package/dist-types/components/preferences/types.d.ts +1 -1
- package/dist-types/components/prompt/atoms/early-tap-script.d.ts +17 -0
- package/dist-types/components/prompt/atoms/root.d.ts +4 -0
- package/dist-types/components/prompt/components.d.ts +9 -3
- package/dist-types/components/prompt/index.d.ts +12 -12
- package/dist-types/components/prompt/policy-actions.d.ts +2 -2
- package/dist-types/components/prompt/prompt.d.ts +5 -1
- package/dist-types/components/shared/dialog-sheets.d.ts +9 -0
- package/dist-types/components/shared/first-paint-sheets.d.ts +8 -0
- package/dist-types/components/shared/iab-dialog-sheets.d.ts +3 -0
- package/dist-types/components/shared/iab-first-paint-sheets.d.ts +3 -0
- package/dist-types/components/shared/libs/compose-refs.d.ts +20 -0
- package/dist-types/components/shared/policy-actions.d.ts +2 -2
- package/dist-types/components/shared/primitives/box.d.ts +1 -1
- package/dist-types/components/shared/primitives/button.d.ts +2 -2
- package/dist-types/components/shared/primitives/button.types.d.ts +1 -1
- package/dist-types/components/shared/streamed-surface.d.ts +23 -0
- package/dist-types/components/shared/surface-styles.d.ts +36 -0
- package/dist-types/components/shared/ui/accordion/accordion.d.ts +2 -2
- package/dist-types/components/shared/ui/accordion/index.d.ts +2 -2
- package/dist-types/components/shared/ui/animated-collapse/index.d.ts +2 -2
- package/dist-types/components/shared/ui/branding.d.ts +1 -1
- package/dist-types/components/shared/ui/button/button.d.ts +1 -1
- package/dist-types/components/shared/ui/button/index.d.ts +2 -2
- package/dist-types/components/shared/ui/collapsible/index.d.ts +1 -1
- package/dist-types/components/shared/ui/dialog/index.d.ts +1 -1
- package/dist-types/components/shared/ui/icon.d.ts +2 -1
- package/dist-types/components/shared/ui/logo.d.ts +0 -10
- package/dist-types/components/shared/ui/preference-item/index.d.ts +1 -1
- package/dist-types/components/shared/ui/preference-item/preference-item.d.ts +13 -0
- package/dist-types/components/shared/ui/switch/index.d.ts +2 -2
- package/dist-types/components/shared/ui/switch/switch.d.ts +1 -1
- package/dist-types/components/shared/ui/tabs/index.d.ts +1 -1
- package/dist-types/consent-gate.d.ts +1 -0
- package/dist-types/consent-theme.d.ts +38 -0
- package/dist-types/context/consent-tracking-context.d.ts +10 -0
- package/dist-types/context/index.d.ts +3 -3
- package/dist-types/context/theme-context.d.ts +3 -3
- package/dist-types/context.d.ts +25 -1
- package/dist-types/devtools-launcher.d.ts +29 -0
- package/dist-types/devtools.d.ts +13 -2
- package/dist-types/draft-context.d.ts +31 -0
- package/dist-types/draft.d.ts +81 -9
- package/dist-types/gpp.d.ts +27 -0
- package/dist-types/headless.d.ts +6 -7
- package/dist-types/hooks/use-committed-ref.d.ts +24 -0
- package/dist-types/hooks/use-focus-trap.d.ts +3 -1
- package/dist-types/hooks/use-headless-iab-consent-ui.d.ts +1 -1
- package/dist-types/hooks/use-iab-manager.d.ts +5 -5
- package/dist-types/hooks/use-iab-policy-guard.d.ts +35 -0
- package/dist-types/hooks/use-late-entry.d.ts +14 -0
- package/dist-types/hooks/use-theme.d.ts +1 -1
- package/dist-types/hooks.d.ts +106 -11
- package/dist-types/iab.d.ts +7 -7
- package/dist-types/index-parts/consent-banner.d.ts +7 -0
- package/dist-types/index-parts/consent-dialog-link.d.ts +7 -0
- package/dist-types/index-parts/consent-dialog-trigger.d.ts +7 -0
- package/dist-types/index-parts/consent-dialog.d.ts +7 -0
- package/dist-types/index-parts/consent-gate.d.ts +7 -0
- package/dist-types/index-parts/core.d.ts +7 -0
- package/dist-types/index-parts/draft.d.ts +7 -0
- package/dist-types/index-parts/frame.d.ts +7 -0
- package/dist-types/index-parts/hooks.d.ts +7 -0
- package/dist-types/index-parts/hosted.d.ts +7 -0
- package/dist-types/index-parts/module-hooks.d.ts +7 -0
- package/dist-types/index-parts/offline.d.ts +7 -0
- package/dist-types/index-parts/presets.d.ts +7 -0
- package/dist-types/index-parts/provider.d.ts +7 -0
- package/dist-types/index-parts/theme.d.ts +8 -0
- package/dist-types/index-parts/translations.d.ts +7 -0
- package/dist-types/index.d.ts +32 -28
- package/dist-types/kernel-selector.d.ts +68 -0
- package/dist-types/modes.d.ts +26 -0
- package/dist-types/module-hooks/iframe-blocker.d.ts +33 -1
- package/dist-types/module-hooks/network-blocker.d.ts +23 -0
- package/dist-types/module-hooks/network-hold.d.ts +47 -0
- package/dist-types/module-hooks.d.ts +4 -4
- package/dist-types/panel-link.d.ts +1 -1
- package/dist-types/panel-trigger.d.ts +1 -1
- package/dist-types/panel.d.ts +13 -1
- package/dist-types/postcss-tailwind3.d.ts +21 -0
- package/dist-types/preferences.d.ts +12 -1
- package/dist-types/primitives/accordion.d.ts +1 -1
- package/dist-types/primitives/button.d.ts +1 -1
- package/dist-types/primitives/collapsible.d.ts +1 -1
- package/dist-types/primitives/dialog.d.ts +1 -1
- package/dist-types/primitives/preference-item.d.ts +1 -1
- package/dist-types/primitives/switch.d.ts +1 -1
- package/dist-types/primitives/tabs.d.ts +1 -1
- package/dist-types/primitives.d.ts +7 -7
- package/dist-types/prompt.d.ts +1 -1
- package/dist-types/provider.d.ts +169 -28
- package/dist-types/server/fetch-ssr-data.d.ts +1 -1
- package/dist-types/server/headers.d.ts +14 -4
- package/dist-types/server/index.d.ts +5 -5
- package/dist-types/server/normalize-url.d.ts +14 -7
- package/dist-types/server/types.d.ts +12 -1
- package/dist-types/theme-provider.d.ts +2 -2
- package/dist-types/transports/hosted.d.ts +36 -0
- package/dist-types/transports/manifest.d.ts +48 -0
- package/dist-types/transports/offline.d.ts +7 -16
- package/dist-types/types/index.d.ts +3 -3
- package/dist-types/types/manager.d.ts +1 -1
- package/dist-types/types/theme/index.d.ts +1 -1
- package/dist-types/ui-config-context.d.ts +14 -2
- package/dist-types/utils/deferred-module.d.ts +13 -0
- package/dist-types/utils/index.d.ts +4 -4
- package/dist-types/utils/merge-slot-props.d.ts +17 -3
- package/dist-types/utils/merge-styles.d.ts +1 -1
- package/dist-types/utils/theme-utils.d.ts +18 -3
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +96 -70
- package/docs/assets/v3/bottom-bar.png +0 -0
- package/docs/assets/v3/brand-card.png +0 -0
- package/docs/assets/v3/brand-preferences.png +0 -0
- package/docs/assets/v3/choice-wall.png +0 -0
- package/docs/assets/v3/headless-bar-html.png +0 -0
- package/docs/assets/v3/headless-bar-mobile.png +0 -0
- package/docs/assets/v3/headless-bar.png +0 -0
- package/docs/assets/v3/slim-bar.png +0 -0
- package/docs/concepts/choose-your-setup.md +138 -0
- package/docs/concepts/consent-categories.md +84 -0
- package/docs/concepts/consent-state.md +421 -0
- package/docs/concepts/data-fetching.md +270 -0
- package/docs/concepts/how-consent-works.md +123 -0
- package/docs/concepts/modes.md +278 -0
- package/docs/{frameworks/react/concepts/policy-presets.md → concepts/policies.md} +8 -60
- package/docs/customization/class-names.md +202 -0
- package/docs/customization/dark-mode.md +157 -0
- package/docs/customization/motion.md +128 -0
- package/docs/customization/overview.md +68 -33
- package/docs/customization/recipes.md +838 -47
- package/docs/customization/slots.md +217 -35
- package/docs/customization/stylesheets.md +248 -0
- package/docs/customization/tailwind.md +863 -0
- package/docs/customization/tokens.md +167 -36
- package/docs/customization/translations.md +87 -3
- package/docs/frameworks/react/callbacks.md +118 -0
- package/docs/frameworks/react/clear-on-revocation.md +106 -0
- package/docs/frameworks/react/components/consent-banner.md +48 -27
- package/docs/frameworks/react/components/consent-dialog-link.md +13 -11
- package/docs/frameworks/react/components/consent-dialog-trigger.md +86 -76
- package/docs/frameworks/react/components/consent-dialog.md +111 -58
- package/docs/frameworks/react/components/{frame.md → consent-gate.md} +70 -49
- package/docs/frameworks/react/components/consent-provider.md +140 -0
- package/docs/frameworks/react/components/consent-widget.md +69 -24
- package/docs/frameworks/react/components/dev-tools.md +76 -85
- package/docs/frameworks/react/components.md +113 -0
- package/docs/frameworks/react/compose.md +354 -0
- package/docs/frameworks/react/content-security-policy.md +143 -0
- package/docs/frameworks/react/customize.md +258 -0
- package/docs/frameworks/react/embeds.md +89 -0
- package/docs/frameworks/react/gpp.md +163 -0
- package/docs/frameworks/react/headless.md +4 -4
- package/docs/frameworks/react/hooks.md +70 -0
- package/docs/frameworks/react/iab.md +259 -0
- package/docs/frameworks/react/network-blocker.md +140 -0
- package/docs/frameworks/react/quickstart.md +220 -102
- package/docs/frameworks/react/rendering.md +263 -0
- package/docs/frameworks/react/scripts.md +114 -0
- package/docs/frameworks/react/translations.md +155 -0
- package/docs/frameworks/react/troubleshooting.md +188 -61
- package/docs/frameworks/react/upgrade-v3.md +651 -0
- package/docs/frameworks/react/vendor-consent.md +188 -0
- package/docs/guides/banner-experiments.md +672 -0
- package/docs/guides/troubleshooting.md +192 -54
- package/docs/guides/verify-consent.md +96 -49
- package/docs/integrations/adobe-analytics.md +177 -183
- package/docs/integrations/ahrefs-analytics.md +162 -178
- package/docs/integrations/amplitude.md +172 -180
- package/docs/integrations/building-integrations.md +137 -33
- package/docs/integrations/clearbit.md +164 -178
- package/docs/integrations/cloudflare-web-analytics.md +166 -180
- package/docs/integrations/cloudflare-zaraz.md +333 -0
- package/docs/integrations/crisp.md +174 -182
- package/docs/integrations/databuddy.md +167 -197
- package/docs/integrations/fathom-analytics.md +168 -180
- package/docs/integrations/front-chat.md +308 -0
- package/docs/integrations/google-maps.md +142 -108
- package/docs/integrations/google-tag-manager.md +258 -185
- package/docs/integrations/google-tag.md +226 -182
- package/docs/integrations/heap.md +173 -179
- package/docs/integrations/hightouch.md +171 -181
- package/docs/integrations/hotjar.md +169 -179
- package/docs/integrations/intercom.md +193 -177
- package/docs/integrations/klaviyo.md +473 -0
- package/docs/integrations/linkedin-insights.md +184 -174
- package/docs/integrations/logrocket.md +170 -180
- package/docs/integrations/matomo-analytics.md +198 -202
- package/docs/integrations/meta-pixel.md +198 -174
- package/docs/integrations/microsoft-clarity.md +173 -179
- package/docs/integrations/microsoft-uet.md +158 -178
- package/docs/integrations/mixpanel-analytics.md +165 -184
- package/docs/integrations/one-dollar-stats.md +292 -0
- package/docs/integrations/openai-pixel.md +214 -325
- package/docs/integrations/overview.md +152 -83
- package/docs/integrations/pinterest-tag.md +315 -0
- package/docs/integrations/pirsch.md +179 -183
- package/docs/integrations/plausible-analytics.md +182 -182
- package/docs/integrations/posthog.md +323 -264
- package/docs/integrations/promptwatch.md +164 -178
- package/docs/integrations/reddit-pixel.md +195 -181
- package/docs/integrations/rudderstack.md +211 -210
- package/docs/integrations/rybbit-analytics.md +181 -184
- package/docs/integrations/segment.md +192 -178
- package/docs/integrations/sentry.md +402 -0
- package/docs/integrations/snapchat-pixel.md +196 -180
- package/docs/integrations/tiktok-pixel.md +181 -174
- package/docs/integrations/umami-analytics.md +173 -182
- package/docs/integrations/vercel-analytics.md +176 -181
- package/docs/integrations/x-pixel.md +186 -174
- package/docs/integrations/youtube.md +150 -111
- package/package.json +48 -17
- package/dist/component-hooks/use-manager.js +0 -2
- package/dist/components/frame/atoms.js +0 -1
- package/dist/components/frame/frame.js +0 -2
- package/dist/components/frame/index.js +0 -2
- package/dist/frame.js +0 -2
- package/dist/ui-save.js +0 -1
- package/dist-types/component-hooks/use-manager.d.ts +0 -40
- package/dist-types/components/frame/atoms.d.ts +0 -11
- package/dist-types/components/frame/frame.d.ts +0 -2
- package/dist-types/components/frame/index.d.ts +0 -24
- package/dist-types/frame.d.ts +0 -1
- package/dist-types/ui-save.d.ts +0 -5
- package/docs/assets/v3/brand-bar.png +0 -0
- package/docs/assets/v3/mobile-card.png +0 -0
- package/docs/assets/v3/preferences.png +0 -0
- package/docs/frameworks/react/components/consent-manager-provider.md +0 -71
- package/docs/frameworks/react/concepts/consent-categories.md +0 -33
- package/docs/frameworks/react/hooks/use-consent-manager/overview.md +0 -58
- package/docs/frameworks/react/iab/overview.md +0 -53
- package/docs/frameworks/react/script-loader.md +0 -63
- package/docs/frameworks/react/styling/overview.md +0 -217
- package/docs/guides/consent-state.md +0 -60
- package/docs/guides/data-fetching.md +0 -163
- package/docs/guides/deployment-modes.md +0 -63
- package/docs/integrations/clear-on-revocation.md +0 -167
- package/docs/upgrade-v3.md +0 -334
- package/readme.json +0 -48
- package/src/iab/styles.css +0 -11
- package/src/styles.css +0 -10
- /package/dist/components/{frame → consent-gate}/types.js +0 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: IAB TCF
|
|
3
|
+
description: Mount the IAB TCF banner and dialog inside a React ConsentProvider
|
|
4
|
+
and configure the CMP ID, policy and vendor data.
|
|
5
|
+
group: frameworks
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Prepare the IAB configuration
|
|
9
|
+
|
|
10
|
+
Use the IAB integration when your application needs the Transparency and Consent
|
|
11
|
+
Framework. Configure an IAB policy, the correct CMP identity and vendor data for
|
|
12
|
+
your deployment. A demo CMP ID is not a production configuration.
|
|
13
|
+
|
|
14
|
+
A CMP ID is assigned to a company when it registers as a CMP with IAB Europe
|
|
15
|
+
([register.consensu.org/CMP](https://register.consensu.org/CMP)). Every TC
|
|
16
|
+
String names the CMP that wrote it, so an ID you did not register attributes
|
|
17
|
+
your users' consent records to someone else. Omitting it leaves the add-on
|
|
18
|
+
unmounted: no `__tcfapi`, and no TC String written.
|
|
19
|
+
|
|
20
|
+
Install `@c15t/iab` alongside your framework adapter, then mount the IAB
|
|
21
|
+
components inside an existing consent provider connected to Inth.
|
|
22
|
+
|
|
23
|
+
Import the components from `c15t/react/iab` and render them inside your
|
|
24
|
+
existing `ConsentProvider` from `c15t/react`.
|
|
25
|
+
|
|
26
|
+
The IAB banner and dialog render their own styles by default. Leave the
|
|
27
|
+
provider's `styles` option enabled and render the components without a CSS
|
|
28
|
+
import:
|
|
29
|
+
|
|
30
|
+
```tsx title="src/iab-consent.tsx"
|
|
31
|
+
import {
|
|
32
|
+
IABProvider,
|
|
33
|
+
IABConsentBanner,
|
|
34
|
+
IABConsentDialog,
|
|
35
|
+
} from 'c15t/react/iab';
|
|
36
|
+
|
|
37
|
+
export const IABConsent = ({ cmpId }: { cmpId: number }) => (
|
|
38
|
+
<IABProvider cmpId={cmpId}>
|
|
39
|
+
<IABConsentBanner />
|
|
40
|
+
<IABConsentDialog />
|
|
41
|
+
</IABProvider>
|
|
42
|
+
);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Supply the CMP ID from your deployment's IAB configuration. Keep a persistent
|
|
46
|
+
preferences entry point through the surrounding consent provider.
|
|
47
|
+
|
|
48
|
+
## Resolve the policy before rendering
|
|
49
|
+
|
|
50
|
+
IAB components remain hidden until an applicable policy resolves. Forcing a
|
|
51
|
+
dialog open does not create a policy or vendor list. Inspect resolution and the
|
|
52
|
+
Global Vendor List response before changing rendering conditions.
|
|
53
|
+
|
|
54
|
+
IAB presentation follows `presentation.prompt.blocking` and
|
|
55
|
+
`presentation.preferences.blocking`. A blocking dialog needs focus management,
|
|
56
|
+
scroll locking and a backdrop together.
|
|
57
|
+
|
|
58
|
+
## Mount IABProvider for every IAB policy
|
|
59
|
+
|
|
60
|
+
IAB is opt-in. The standard `ConsentBanner` and `ConsentDialog` do not
|
|
61
|
+
handle the IAB model, so when a visitor's policy uses it, the backend
|
|
62
|
+
sends its vendor list and the app has no `IABProvider`, they throw an
|
|
63
|
+
`IABUnavailableError` (code `C15T_IAB_UNAVAILABLE`):
|
|
64
|
+
`c15t: this visitor's policy uses IAB TCF, but no <IABProvider> is mounted`.
|
|
65
|
+
The error happens during render, on the server and in the browser, so
|
|
66
|
+
your error boundary or the framework's error overlay shows it. Render `IABProvider` from
|
|
67
|
+
`c15t/react/iab` for those visitors, or remove the `iab` model from the
|
|
68
|
+
policy.
|
|
69
|
+
|
|
70
|
+
## Verify vendor and purpose choices
|
|
71
|
+
|
|
72
|
+
Test category choices alongside vendor, purpose, legitimate-interest and special
|
|
73
|
+
feature controls used by your integration. Confirm the TC String and `__tcfapi`
|
|
74
|
+
reflect the saved state, and verify the vendor's actual requests. A category-only
|
|
75
|
+
banner test does not establish that the IAB flow works.
|
|
76
|
+
|
|
77
|
+
## Load an external stylesheet
|
|
78
|
+
|
|
79
|
+
With Tailwind CSS 3, or when you want to put c15t in a named cascade layer,
|
|
80
|
+
import `c15t/react/styles.css` and then `c15t/react/iab/styles.css` at your
|
|
81
|
+
global stylesheet entry. The IAB stylesheet holds the IAB rules and uses the
|
|
82
|
+
base stylesheet's tokens. Set `styles: false` so the components use those
|
|
83
|
+
stylesheets:
|
|
84
|
+
|
|
85
|
+
```tsx title="src/consent.tsx (partial)"
|
|
86
|
+
import 'c15t/react/styles.css';
|
|
87
|
+
import 'c15t/react/iab/styles.css';
|
|
88
|
+
|
|
89
|
+
// In the ConsentProvider options:
|
|
90
|
+
styles: false,
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Tailwind CSS 3 also needs the
|
|
94
|
+
[PostCSS plugin](../../customization/tailwind.md#set-up-tailwind-css-3).
|
|
95
|
+
|
|
96
|
+
## Restrict how vendors use a purpose
|
|
97
|
+
|
|
98
|
+
Publisher restrictions override a vendor's declared use of one purpose. Pass
|
|
99
|
+
them to `IABProvider` as `publisherRestrictions`. The vendor IDs below are
|
|
100
|
+
placeholders; use vendors from your list whose declarations allow each
|
|
101
|
+
restriction.
|
|
102
|
+
|
|
103
|
+
```tsx title="src/iab-consent.tsx"
|
|
104
|
+
import {
|
|
105
|
+
IABProvider,
|
|
106
|
+
IABConsentBanner,
|
|
107
|
+
IABConsentDialog,
|
|
108
|
+
} from 'c15t/react/iab';
|
|
109
|
+
|
|
110
|
+
const publisherRestrictions = [
|
|
111
|
+
// Vendors 10 and 755 may not use purpose 4.
|
|
112
|
+
{ purposeId: 4, restrictionType: 0 as const, vendorIds: [10, 755] },
|
|
113
|
+
// Vendor 755 must use legitimate interest for purpose 7.
|
|
114
|
+
{ purposeId: 7, restrictionType: 2 as const, vendorIds: [755] },
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
export const IABConsent = ({ cmpId }: { cmpId: number }) => (
|
|
118
|
+
<IABProvider cmpId={cmpId} publisherRestrictions={publisherRestrictions}>
|
|
119
|
+
<IABConsentBanner />
|
|
120
|
+
<IABConsentDialog />
|
|
121
|
+
</IABProvider>
|
|
122
|
+
);
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Each restriction type has a requirement that depends on the vendor list:
|
|
126
|
+
|
|
127
|
+
| `restrictionType` | Meaning | Allowed when the vendor |
|
|
128
|
+
| ----------------- | -------------------------------------- | ------------------------------------------------------------------------------- |
|
|
129
|
+
| `0` | Purpose not allowed on any legal basis | declares the purpose for consent or legitimate interest |
|
|
130
|
+
| `1` | Consent required | declares the purpose for legitimate interest and lists it in `flexiblePurposes` |
|
|
131
|
+
| `2` | Legitimate interest required | declares the purpose for consent and lists it in `flexiblePurposes` |
|
|
132
|
+
|
|
133
|
+
Type `2` is never allowed for purposes 1, 3, 4, 5 and 6, which TCF allows
|
|
134
|
+
only with consent. TCF allows restrictions only in service-specific TC strings.
|
|
135
|
+
c15t always writes those, so the deprecated `isServiceSpecific` option has no
|
|
136
|
+
effect on restrictions.
|
|
137
|
+
c15t copies the restrictions when the CMP starts, so changing your array
|
|
138
|
+
afterwards has no effect.
|
|
139
|
+
|
|
140
|
+
c15t checks restrictions when the vendor list loads and again before each TC
|
|
141
|
+
String is encoded. Unsupported restrictions include type `3`, which the spec
|
|
142
|
+
reserves, a vendor or purpose missing from the list, and a vendor with two
|
|
143
|
+
restriction types for one purpose. They are never dropped. Loading IAB
|
|
144
|
+
settings, saving and generating a TC String all reject with a
|
|
145
|
+
`PublisherRestrictionError` exported by `@c15t/iab`. On a `createIAB` handle
|
|
146
|
+
these are `whenReady()`, `save()` and `generateTCString()`. No TC String is
|
|
147
|
+
written and no consent is recorded. Retrying `whenReady()` does not fetch
|
|
148
|
+
another vendor list. The error lasts until a new vendor list is set up: with an
|
|
149
|
+
explicit `gvl` option that never happens, so saving keeps failing even if the
|
|
150
|
+
kernel later holds a different list. When the CMP follows the kernel's list
|
|
151
|
+
instead, a replacement list is checked again and saving works once it accepts
|
|
152
|
+
the restrictions. When a replacement vendor list makes a restriction
|
|
153
|
+
unsupported, c15t also clears the TC authority confirmed under the previous
|
|
154
|
+
list, so gated scripts stop until the configuration is fixed. Whenever c15t
|
|
155
|
+
withdraws the authority it confirmed, it also removes the TC String from the
|
|
156
|
+
`euconsent-v2` cookie and localStorage entry. Because the check reads the
|
|
157
|
+
current vendor list, a vendor that stops declaring a purpose or its flexibility
|
|
158
|
+
makes a restriction invalid. Narrow a `vendors` allowlist and your restrictions
|
|
159
|
+
together.
|
|
160
|
+
|
|
161
|
+
Saved TC Strings carry the restrictions in their `PubRestrictions` section, and
|
|
162
|
+
`__tcfapi('getTCData')` reports them as `publisher.restrictions`, keyed by
|
|
163
|
+
purpose ID, then vendor ID. A stored TC String whose restrictions differ from
|
|
164
|
+
the current configuration is not restored. If the visitor's stored choice is
|
|
165
|
+
otherwise current, the banner opens again, as it does after a policy change,
|
|
166
|
+
and closes once the visitor saves. IAB gates that depend on the TC String stay
|
|
167
|
+
denied until then. c15t also removes the superseded TC String from the
|
|
168
|
+
`euconsent-v2` cookie and localStorage entry, so vendors reading standard
|
|
169
|
+
storage do not pick it up. An unchanged configuration restores the stored TC
|
|
170
|
+
String without asking.
|
|
171
|
+
When reading a string written under TCF policy version 2 or 3, c15t accepts
|
|
172
|
+
type `2` for purposes 3 to 6, which those versions allowed. Strings c15t
|
|
173
|
+
writes always follow the current policy.
|
|
174
|
+
|
|
175
|
+
The React, Vue, Svelte and `@c15t/browser/iab` preference centres list each
|
|
176
|
+
vendor under the legal basis the restrictions leave it. A vendor whose purpose
|
|
177
|
+
now requires legitimate interest gets an objection control instead of a
|
|
178
|
+
consent toggle, and a prohibited purpose no longer lists the vendor. A
|
|
179
|
+
purpose whose vendors all use legitimate interest has no consent switch,
|
|
180
|
+
because turning one off would change nothing the vendors rely on; its
|
|
181
|
+
objection control is the opt-out. Such a purpose does not decide its c15t
|
|
182
|
+
category: the category follows the purposes in it that the visitor can
|
|
183
|
+
consent to. Legitimate interest never grants a category on its own. If none of
|
|
184
|
+
a category's purposes has a consent basis, nothing can consent to them, Accept
|
|
185
|
+
All included, so the category stays denied. See
|
|
186
|
+
[categories under an IAB policy](../../concepts/consent-state.md#categories-under-an-iab-policy).
|
|
187
|
+
Stack switches
|
|
188
|
+
cover only the purposes some vendor processes on consent. Display-model rows
|
|
189
|
+
expose this as `hasConsentBasis`. Custom preference UIs can call
|
|
190
|
+
`applyPublisherRestrictionsToGVL` from `@c15t/iab/headless`, or pass
|
|
191
|
+
`publisherRestrictions` to `processGVLForDialog`, to get the same vendor
|
|
192
|
+
declarations. The configured restrictions are on the kernel's IAB state as
|
|
193
|
+
`publisherRestrictions`.
|
|
194
|
+
|
|
195
|
+
Consent-gated scripts, network rules and iframes with a `vendorId` also apply
|
|
196
|
+
the confirmed restrictions for that vendor:
|
|
197
|
+
|
|
198
|
+
* Type `0` blocks a target that declares the purpose in `iabPurposes` or
|
|
199
|
+
`iabLegIntPurposes`.
|
|
200
|
+
* Type `1` makes a purpose declared in `iabLegIntPurposes` require purpose and
|
|
201
|
+
vendor consent. Legitimate interest no longer satisfies it.
|
|
202
|
+
* Type `2` makes a purpose declared in `iabPurposes` require purpose and vendor
|
|
203
|
+
legitimate interest. Consent no longer satisfies it.
|
|
204
|
+
|
|
205
|
+
Types `1` and `2` block the target when the vendor list does not mark the
|
|
206
|
+
purpose as flexible for that vendor. Targets without a `vendorId` ignore
|
|
207
|
+
restrictions. A target that uses only legitimate interest once restrictions
|
|
208
|
+
apply is not blocked by a refused category, since it needs no consent; its
|
|
209
|
+
legitimate interest signals and the visitor's objection decide. GPC and strict
|
|
210
|
+
scope still block it, and the category stays refused for scripts that depend on
|
|
211
|
+
it. Accept All grants the vendor signal a restriction moves a purpose to,
|
|
212
|
+
including legitimate interest for a vendor that declares none. Legitimate
|
|
213
|
+
interest a restriction introduces applies until the visitor objects: the
|
|
214
|
+
preference centres show it as allowed, and saving without touching it encodes
|
|
215
|
+
it as allowed. `introducedLegitimateInterest` from `@c15t/iab/headless` lists
|
|
216
|
+
those purposes and vendors for custom preference UIs.
|
|
217
|
+
|
|
218
|
+
## How the preference centre shows features
|
|
219
|
+
|
|
220
|
+
The stock IAB preference centres in React, Next.js, Vue, Svelte, Astro and the
|
|
221
|
+
script tag follow TCF 2.4 and Policies v5.0.b. Special purposes stay in their
|
|
222
|
+
locked section with a lock icon, because the visitor cannot object to them.
|
|
223
|
+
|
|
224
|
+
Features get their own section after the special purposes. It shows the IAB
|
|
225
|
+
standard text for features from the Global Vendor List's
|
|
226
|
+
`standardTexts.features`. If the list has no standard text, it shows the
|
|
227
|
+
`iab.preferenceCenter.features.description` translation. Each feature lists
|
|
228
|
+
its name, description, illustrations and the vendors that use it. The section has no switch, lock or vendor toggle, because
|
|
229
|
+
TCF forbids showing features next to a control that cannot be disabled.
|
|
230
|
+
|
|
231
|
+
The feature section follows the theme's spacing and typography tokens.
|
|
232
|
+
Its disclosure arrows are decorative and stay out of the accessibility tree.
|
|
233
|
+
|
|
234
|
+
A custom preference UI gets the same rows from
|
|
235
|
+
`resolveIABDialogDisplayModel` in `@c15t/iab/headless`. `essentialRows` holds
|
|
236
|
+
the special purposes only. `featureRows` holds the features, with
|
|
237
|
+
`locked: false` and `toggle: 'none'`, so render them without a control.
|
|
238
|
+
`featuresStandardText` is the standard text, or `null` when you should use the
|
|
239
|
+
translation.
|
|
240
|
+
|
|
241
|
+
Each vendor's privacy policy and legitimate interest links come from its
|
|
242
|
+
`urls[]` entry in the Global Vendor List. The stock preference centres pick
|
|
243
|
+
the entry for the language the banner shows, then English. A custom UI gets
|
|
244
|
+
the same links from `resolveIABVendorUrls(vendor, language)` in
|
|
245
|
+
`@c15t/iab/headless`, or from `policyUrl` and `legitimateInterestUrl` on the
|
|
246
|
+
vendors `processGVLForDialog` returns when you pass it `language`. Vendor lists
|
|
247
|
+
older than GVL v3 have a single `policyUrl` field, which c15t still reads.
|
|
248
|
+
|
|
249
|
+
## Consent scope
|
|
250
|
+
|
|
251
|
+
c15t stores TCF choices per site and browser, which the TCF calls
|
|
252
|
+
service-specific scope. It does not sync TC strings across devices, and every
|
|
253
|
+
TC string it writes has `IsServiceSpecific` set to `1`.
|
|
254
|
+
|
|
255
|
+
Do not use `/consent/check` or your own account data to skip the TCF banner on
|
|
256
|
+
another device. That turns the choice into multi-device scope, which the TCF
|
|
257
|
+
requires you to disclose in the first layer, and c15t does not show that
|
|
258
|
+
disclosure. The `isServiceSpecific` option is deprecated. c15t ignores it and
|
|
259
|
+
logs a warning when you pass `false`.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Network blocker
|
|
3
|
+
description: Hold fetch and XMLHttpRequest calls in a React app until their
|
|
4
|
+
consent category is allowed, with networkBlocker rules in the ConsentProvider
|
|
5
|
+
options.
|
|
6
|
+
group: frameworks
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Add rules
|
|
10
|
+
|
|
11
|
+
Some SDKs are already on the page and send beacons or API calls of their own.
|
|
12
|
+
Add `networkBlocker` rules to the provider options to stop `fetch` and
|
|
13
|
+
`XMLHttpRequest` calls to those domains until the category is allowed. Load
|
|
14
|
+
vendor SDKs through [`scripts`](./scripts.md) first, so they
|
|
15
|
+
do not run at all before consent.
|
|
16
|
+
|
|
17
|
+
This partial example adds the option next to the existing `mode` and
|
|
18
|
+
`scripts`:
|
|
19
|
+
|
|
20
|
+
```tsx title="src/consent.tsx"
|
|
21
|
+
const networkBlocker = {
|
|
22
|
+
rules: [
|
|
23
|
+
{
|
|
24
|
+
id: 'google-analytics',
|
|
25
|
+
domain: 'google-analytics.com',
|
|
26
|
+
category: 'measurement',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 'meta-pixel',
|
|
30
|
+
domain: 'facebook.com',
|
|
31
|
+
pathIncludes: '/tr',
|
|
32
|
+
category: 'marketing',
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
<ConsentProvider options={{ mode, scripts, networkBlocker }}>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Match requests with rules
|
|
41
|
+
|
|
42
|
+
Each rule names a `domain` and the consent `category` a request needs. The
|
|
43
|
+
domain also matches its subdomains: `google-analytics.com` covers
|
|
44
|
+
`www.google-analytics.com`. `pathIncludes` narrows the rule to paths that
|
|
45
|
+
contain a substring, and `methods` narrows it to HTTP methods. A request is
|
|
46
|
+
blocked when a matching rule's condition is not met by the visitor's
|
|
47
|
+
effective permissions.
|
|
48
|
+
|
|
49
|
+
`category` takes the same conditions as scripts:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
{ category: 'measurement' }
|
|
53
|
+
{ category: { and: ['measurement', 'marketing'] } }
|
|
54
|
+
{ category: { or: ['measurement', 'marketing'] } }
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Add `vendor` to also block the request while the visitor has turned that
|
|
58
|
+
vendor off. IAB TCF rules use `vendorId` and the `iab*` purpose fields
|
|
59
|
+
instead.
|
|
60
|
+
|
|
61
|
+
| Option | Default | Purpose |
|
|
62
|
+
| -------------------- | -------- | ------------------------------------------------------------ |
|
|
63
|
+
| `rules` | required | Rules described above |
|
|
64
|
+
| `enabled` | `true` | Set `false` to keep the rules but stop blocking |
|
|
65
|
+
| `logBlockedRequests` | `true` | Log each blocked request with `console.warn` |
|
|
66
|
+
| `onRequestBlocked` | none | Called with `{ method, url, rule }` for each blocked request |
|
|
67
|
+
|
|
68
|
+
## What a blocked request looks like
|
|
69
|
+
|
|
70
|
+
The blocker wraps `window.fetch` and `XMLHttpRequest`. A blocked `fetch`
|
|
71
|
+
resolves to a `451` response with the status text
|
|
72
|
+
`Request blocked by consent`, and nothing is sent. A blocked XHR is aborted
|
|
73
|
+
and fires an `error` event. Requests that match no rule are not delayed.
|
|
74
|
+
|
|
75
|
+
## When blocking starts
|
|
76
|
+
|
|
77
|
+
The provider holds matching requests from its first render in the browser,
|
|
78
|
+
before any of its children render or run effects. That covers requests from
|
|
79
|
+
child components, including their mount effects, and from effects in
|
|
80
|
+
components rendered next to the provider. The blocker module itself loads
|
|
81
|
+
after mount and decides each held request. Apps without `networkBlocker` do
|
|
82
|
+
not download it.
|
|
83
|
+
|
|
84
|
+
The standalone `useNetworkBlocker` hook works the same way from the first
|
|
85
|
+
render of the component that calls it. That render patches `fetch` and
|
|
86
|
+
`XMLHttpRequest`. If React throws the render away and never commits it, the
|
|
87
|
+
hold ends after 10 seconds. Nothing checked consent for the requests it held,
|
|
88
|
+
so they fail the way the blocker fails a blocked request: a 451 response for
|
|
89
|
+
`fetch`, a failed XHR. The same happens when the component unmounts before
|
|
90
|
+
the blocker loads.
|
|
91
|
+
|
|
92
|
+
While consent is unknown, a matching request that would be blocked waits
|
|
93
|
+
instead of failing. Consent is unknown until the policy has loaded, which is
|
|
94
|
+
also when a returning visitor's stored choice takes effect. The request is
|
|
95
|
+
then sent if the choice allows it and blocked otherwise. If the policy fails
|
|
96
|
+
to load, optional categories stay denied and waiting requests are blocked.
|
|
97
|
+
If the policy request never finishes, they keep waiting and are never sent.
|
|
98
|
+
|
|
99
|
+
A synchronous XHR cannot wait. Before the blocker module has loaded, a
|
|
100
|
+
matching one throws a `NetworkError` from `send()`. After that, one that
|
|
101
|
+
consent does not allow yet is blocked.
|
|
102
|
+
|
|
103
|
+
## What the network blocker cannot stop
|
|
104
|
+
|
|
105
|
+
The blocker only sees requests made after the provider starts rendering in
|
|
106
|
+
the browser, through `fetch` or `XMLHttpRequest`. It cannot stop:
|
|
107
|
+
|
|
108
|
+
* Code that runs before the provider renders: inline scripts in the HTML,
|
|
109
|
+
third-party tags in `<head>`, scripts loaded before hydration (such as
|
|
110
|
+
`next/script` with `beforeInteractive`), and client modules that evaluate
|
|
111
|
+
earlier. Webpack builds evaluate a route's client component modules when
|
|
112
|
+
its chunk loads, so their top-level code runs first. Turbopack evaluates a
|
|
113
|
+
client component module when its first element renders, which inside the
|
|
114
|
+
provider is after blocking starts.
|
|
115
|
+
* Code that saved its own reference to `fetch` or `XMLHttpRequest` before the
|
|
116
|
+
provider rendered.
|
|
117
|
+
* `navigator.sendBeacon`, `WebSocket`, `EventSource`, and requests made by
|
|
118
|
+
`<img>`, `<script>` or `<iframe>` elements, web workers and service
|
|
119
|
+
workers.
|
|
120
|
+
* With the standalone `useNetworkBlocker` hook instead of the provider
|
|
121
|
+
option, requests sent before the component that calls it renders.
|
|
122
|
+
Blocking starts in that component's first render, not the provider's.
|
|
123
|
+
|
|
124
|
+
Keep tracking calls out of that window:
|
|
125
|
+
|
|
126
|
+
* Send them from an effect or an event handler, never at module top level.
|
|
127
|
+
* Load vendor SDKs through `scripts` instead of a `<script>` tag or
|
|
128
|
+
`next/script`, so they wait for consent before they run at all.
|
|
129
|
+
* Check `useConsent('measurement')` (or the category you need) before you
|
|
130
|
+
call a vendor from your own code, and treat the blocker as a backstop.
|
|
131
|
+
|
|
132
|
+
## Verify the blocked requests
|
|
133
|
+
|
|
134
|
+
Open DevTools Network in a private window, under a policy that asks for
|
|
135
|
+
consent.
|
|
136
|
+
|
|
137
|
+
1. Before a choice, requests matching a rule are absent, and the console logs
|
|
138
|
+
each blocked request.
|
|
139
|
+
2. Allow the rule's category and save. Matching requests go out.
|
|
140
|
+
3. Reject, reload, and check that they stay absent.
|