@c15t/nextjs 2.1.0 → 2.2.1
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 +155 -0
- package/README.md +31 -15
- package/client/components/integrations.js +3 -0
- package/dist/components/integrations/index.cjs +1 -0
- package/dist/components/integrations/index.js +1 -0
- package/dist/headless.cjs +1 -1
- package/dist/index.cjs +1 -1
- package/dist/libs/browser-initial-data.cjs +1 -1
- package/dist/libs/initial-data.cjs +1 -1
- package/dist/styles.tw3.css +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.js +1 -1
- package/dist-types/components/integrations/index.d.ts +1 -0
- package/dist-types/libs/browser-initial-data.d.ts +1 -1
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +155 -73
- package/docs/{building-headless-components.md → frameworks/next/building-headless-components.md} +3 -1
- package/docs/{callbacks.md → frameworks/next/callbacks.md} +3 -1
- package/docs/{components → frameworks/next/components}/consent-banner.md +10 -21
- package/docs/{components → frameworks/next/components}/consent-dialog-link.md +8 -5
- package/docs/frameworks/next/components/consent-dialog-trigger.md +202 -0
- package/docs/{components → frameworks/next/components}/consent-dialog.md +7 -15
- package/docs/frameworks/next/components/consent-manager-provider.md +327 -0
- package/docs/{components → frameworks/next/components}/consent-widget.md +8 -6
- package/docs/{components → frameworks/next/components}/dev-tools.md +9 -6
- package/docs/{components → frameworks/next/components}/frame.md +8 -9
- package/docs/{concepts → frameworks/next/concepts}/client-modes.md +4 -2
- package/docs/{concepts → frameworks/next/concepts}/consent-categories.md +1 -0
- package/docs/{concepts → frameworks/next/concepts}/consent-models.md +1 -0
- package/docs/{concepts → frameworks/next/concepts}/cookie-management.md +3 -3
- package/docs/{concepts → frameworks/next/concepts}/glossary.md +1 -0
- package/docs/{concepts → frameworks/next/concepts}/initialization-flow.md +1 -0
- package/docs/{concepts → frameworks/next/concepts}/policy-packs.md +1 -0
- package/docs/{headless.md → frameworks/next/headless.md} +3 -1
- package/docs/{hooks → frameworks/next/hooks}/use-color-scheme.md +1 -0
- package/docs/{hooks → frameworks/next/hooks}/use-consent-manager/checking-consent.md +3 -1
- package/docs/{hooks → frameworks/next/hooks}/use-consent-manager/location-info.md +3 -1
- package/docs/frameworks/next/hooks/use-consent-manager/overview.md +185 -0
- package/docs/{hooks → frameworks/next/hooks}/use-consent-manager/setting-consent.md +3 -1
- package/docs/{hooks → frameworks/next/hooks}/use-draggable.md +3 -1
- package/docs/{hooks → frameworks/next/hooks}/use-focus-trap.md +1 -0
- package/docs/{hooks → frameworks/next/hooks}/use-reduced-motion.md +3 -1
- package/docs/{hooks → frameworks/next/hooks}/use-ssr-status.md +6 -5
- package/docs/{hooks → frameworks/next/hooks}/use-text-direction.md +1 -0
- package/docs/frameworks/next/hooks/use-translations.md +55 -0
- package/docs/{iab → frameworks/next/iab}/consent-banner.md +9 -12
- package/docs/{iab → frameworks/next/iab}/consent-dialog.md +9 -14
- package/docs/{iab → frameworks/next/iab}/overview.md +4 -2
- package/docs/{iab → frameworks/next/iab}/use-gvl-data.md +3 -2
- package/docs/{iframe-blocking.md → frameworks/next/iframe-blocking.md} +8 -9
- package/docs/{internationalization.md → frameworks/next/internationalization.md} +13 -3
- package/docs/{network-blocker.md → frameworks/next/network-blocker.md} +13 -51
- package/docs/{optimization.md → frameworks/next/optimization.md} +5 -4
- package/docs/{policy-packs.md → frameworks/next/policy-packs.md} +3 -1
- package/docs/{quickstart.md → frameworks/next/quickstart.md} +26 -42
- package/docs/{script-loader.md → frameworks/next/script-loader.md} +72 -90
- package/docs/{server-side.md → frameworks/next/server-side.md} +12 -15
- package/docs/{styling → frameworks/next/styling}/classnames.md +3 -1
- package/docs/{styling → frameworks/next/styling}/color-scheme.md +3 -1
- package/docs/frameworks/next/styling/css-variables.md +53 -0
- package/docs/frameworks/next/styling/overview.md +299 -0
- package/docs/frameworks/next/styling/slots.md +94 -0
- package/docs/{styling → frameworks/next/styling}/tailwind.md +3 -1
- package/docs/frameworks/next/styling/tokens.md +156 -0
- package/docs/{troubleshooting.md → frameworks/next/troubleshooting.md} +3 -1
- package/docs/integrations/adobe-analytics.md +160 -0
- package/docs/integrations/ahrefs-analytics.md +15 -82
- package/docs/integrations/amplitude.md +230 -0
- package/docs/integrations/building-integrations.md +15 -181
- package/docs/integrations/clearbit.md +130 -0
- package/docs/integrations/cloudflare-web-analytics.md +15 -83
- package/docs/integrations/crisp.md +13 -87
- package/docs/integrations/databuddy.md +16 -85
- package/docs/integrations/fathom-analytics.md +15 -86
- package/docs/integrations/google-maps.md +263 -0
- package/docs/integrations/google-tag-manager.md +18 -86
- package/docs/integrations/google-tag.md +15 -84
- package/docs/integrations/heap.md +219 -0
- package/docs/integrations/hightouch.md +199 -0
- package/docs/integrations/hotjar.md +15 -83
- package/docs/integrations/intercom.md +13 -83
- package/docs/integrations/linkedin-insights.md +15 -82
- package/docs/integrations/logrocket.md +175 -0
- package/docs/integrations/matomo-analytics.md +13 -88
- package/docs/integrations/meta-pixel.md +33 -316
- package/docs/integrations/microsoft-clarity.md +15 -83
- package/docs/integrations/microsoft-uet.md +16 -83
- package/docs/integrations/mixpanel-analytics.md +15 -83
- package/docs/integrations/overview.md +55 -6
- package/docs/integrations/pirsch.md +142 -0
- package/docs/integrations/plausible-analytics.md +14 -97
- package/docs/integrations/posthog.md +26 -98
- package/docs/integrations/promptwatch.md +16 -82
- package/docs/integrations/reddit-pixel.md +27 -122
- package/docs/integrations/rudderstack.md +271 -0
- package/docs/integrations/rybbit-analytics.md +15 -94
- package/docs/integrations/segment.md +15 -82
- package/docs/integrations/snapchat-pixel.md +21 -102
- package/docs/integrations/tiktok-pixel.md +13 -81
- package/docs/integrations/umami-analytics.md +16 -88
- package/docs/integrations/vercel-analytics.md +13 -85
- package/docs/integrations/x-pixel.md +27 -102
- package/docs/integrations/youtube.md +193 -0
- package/docs/shared/concepts/client-modes.md +103 -0
- package/docs/shared/concepts/consent-categories.md +41 -0
- package/docs/shared/concepts/consent-models.md +72 -0
- package/docs/shared/concepts/cookie-management.md +88 -0
- package/docs/shared/concepts/glossary.md +24 -0
- package/docs/shared/concepts/initialization-flow.md +105 -0
- package/docs/shared/concepts/policy-packs.md +225 -0
- package/docs/shared/react/components/consent-banner.md +242 -0
- package/docs/shared/react/components/consent-dialog-link.md +45 -0
- package/docs/shared/react/components/consent-dialog-trigger.md +185 -0
- package/docs/shared/react/components/consent-dialog.md +119 -0
- package/docs/shared/react/components/consent-manager-provider.md +225 -0
- package/docs/shared/react/components/consent-widget.md +121 -0
- package/docs/shared/react/components/dev-tools.md +81 -0
- package/docs/shared/react/components/frame.md +52 -0
- package/docs/shared/react/guides/building-headless-components.md +110 -0
- package/docs/shared/react/guides/callbacks.md +89 -0
- package/docs/shared/react/guides/headless.md +31 -0
- package/docs/shared/react/guides/iframe-blocking.md +65 -0
- package/docs/shared/react/guides/internationalization.md +123 -0
- package/docs/shared/react/guides/network-blocker.md +72 -0
- package/docs/shared/react/guides/optimization.md +44 -0
- package/docs/shared/react/guides/policy-packs.md +173 -0
- package/docs/shared/react/guides/script-loader.md +311 -0
- package/docs/shared/react/hooks/use-color-scheme.md +31 -0
- package/docs/shared/react/hooks/use-consent-manager/checking-consent.md +95 -0
- package/docs/shared/react/hooks/use-consent-manager/location-info.md +96 -0
- package/docs/shared/react/hooks/use-consent-manager/overview.md +74 -0
- package/docs/shared/react/hooks/use-consent-manager/setting-consent.md +93 -0
- package/docs/shared/react/hooks/use-draggable.md +30 -0
- package/docs/shared/react/hooks/use-focus-trap.md +20 -0
- package/docs/shared/react/hooks/use-reduced-motion.md +33 -0
- package/docs/shared/react/hooks/use-ssr-status.md +16 -0
- package/docs/shared/react/hooks/use-text-direction.md +38 -0
- package/docs/shared/react/hooks/use-translations.md +15 -0
- package/docs/shared/react/iab/consent-banner.md +60 -0
- package/docs/shared/react/iab/consent-dialog.md +76 -0
- package/docs/shared/react/iab/overview.md +80 -0
- package/docs/shared/react/iab/use-gvl-data.md +21 -0
- package/docs/shared/react/styling/classnames.md +93 -0
- package/docs/shared/react/styling/color-scheme.md +35 -0
- package/docs/shared/react/styling/css-variables.md +53 -0
- package/docs/shared/react/styling/overview.md +261 -0
- package/docs/shared/react/styling/slots.md +93 -0
- package/docs/shared/react/styling/stylesheet-entrypoint.md +8 -0
- package/docs/shared/react/styling/tailwind.md +88 -0
- package/docs/shared/react/styling/tokens.md +155 -0
- package/docs/shared/troubleshooting.md +82 -0
- package/package.json +19 -10
- package/readme.json +14 -8
- package/docs/ai-agents.md +0 -111
- package/docs/components/consent-dialog-trigger.md +0 -103
- package/docs/components/consent-manager-provider.md +0 -425
- package/docs/hooks/use-consent-manager/overview.md +0 -420
- package/docs/hooks/use-translations.md +0 -118
- package/docs/styling/css-variables.md +0 -92
- package/docs/styling/overview.md +0 -457
- package/docs/styling/slots.md +0 -128
- package/docs/styling/tokens.md +0 -216
|
@@ -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
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Draggable
|
|
3
|
+
description: Reference page for use draggable.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
## Options
|
|
7
|
+
|
|
8
|
+
|Option|Type|Default|Description|
|
|
9
|
+
|--|--|--|--|
|
|
10
|
+
|`defaultPosition`|`CornerPosition`|`'bottom-right'`|Initial corner position|
|
|
11
|
+
|`persistPosition`|`boolean`|`true`|Save position to localStorage|
|
|
12
|
+
|`onPositionChange`|`(position: CornerPosition) => void`|-|Callback on position change|
|
|
13
|
+
|
|
14
|
+
## Return Value
|
|
15
|
+
|
|
16
|
+
|Property|Type|Description||||
|
|
17
|
+
|--|--|--|--|--|--|
|
|
18
|
+
|`corner`|`CornerPosition`|Current corner: `'top-left'`|`'top-right'`|`'bottom-left'`|`'bottom-right'`|
|
|
19
|
+
|`isDragging`|`boolean`|Whether the element is being dragged||||
|
|
20
|
+
|`isSnapping`|`boolean`|Whether the element is animating to a new corner||||
|
|
21
|
+
|`wasDragged`|`() => boolean`|Whether the last interaction was a drag (vs click)||||
|
|
22
|
+
|`handlers`|`object`|Pointer event handlers to spread onto the element||||
|
|
23
|
+
|`dragStyle`|`CSSProperties`|Transform style for drag offset||||
|
|
24
|
+
|
|
25
|
+
## Behavior
|
|
26
|
+
|
|
27
|
+
* Drag starts on pointer down (left click / single touch)
|
|
28
|
+
* Movement threshold of 5px distinguishes drag from click
|
|
29
|
+
* On pointer up, element snaps to the nearest corner based on drag direction and velocity
|
|
30
|
+
* Position persists to localStorage by default
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Focus Trap
|
|
3
|
+
description: Reference page for use focus trap.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
## Parameters
|
|
7
|
+
|
|
8
|
+
|Parameter|Type|Description|
|
|
9
|
+
|--|--|--|
|
|
10
|
+
|`shouldTrap`|`boolean`|Whether focus should be trapped|
|
|
11
|
+
|`containerRef`|`RefObject<HTMLElement \|null> \|null`|Ref to the container element|
|
|
12
|
+
|
|
13
|
+
## Behavior
|
|
14
|
+
|
|
15
|
+
* **Tab**: Moves focus to the next focusable element. Wraps to the first element when reaching the end.
|
|
16
|
+
* **Shift+Tab**: Moves focus to the previous focusable element. Wraps to the last element when reaching the start.
|
|
17
|
+
* Focus is restored to the previously focused element when the trap is deactivated.
|
|
18
|
+
|
|
19
|
+
> ℹ️ **Info:**
|
|
20
|
+
> ConsentBanner and ConsentDialog use useFocusTrap internally when trapFocus is enabled (default: true). You only need this hook when building custom consent UI.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Reduced Motion
|
|
3
|
+
description: Reference page for use reduced motion.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
`useReducedMotion()` reads the `prefers-reduced-motion: reduce` media query and reactively updates when the user's preference changes. Use it to conditionally skip animations for users who have enabled reduced motion in their OS accessibility settings.
|
|
7
|
+
|
|
8
|
+
The hook returns `false` during SSR to avoid hydration mismatches, then updates to the actual preference on the client.
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
import { useReducedMotion } from '@c15t/react/hooks';
|
|
12
|
+
|
|
13
|
+
function AnimatedBanner() {
|
|
14
|
+
const prefersReducedMotion = useReducedMotion();
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<div
|
|
18
|
+
style={{
|
|
19
|
+
transition: prefersReducedMotion ? 'none' : 'opacity 300ms ease',
|
|
20
|
+
opacity: 1,
|
|
21
|
+
}}
|
|
22
|
+
>
|
|
23
|
+
Consent banner content
|
|
24
|
+
</div>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Return Value
|
|
30
|
+
|
|
31
|
+
|Type|Description|
|
|
32
|
+
|--|--|
|
|
33
|
+
|`boolean`|`true` if the user prefers reduced motion, `false` otherwise|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use SSR Status
|
|
3
|
+
description: Reference page for use ssr status.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
## Return Value
|
|
7
|
+
|
|
8
|
+
|Property|Value|
|
|
9
|
+
|:--|:--|
|
|
10
|
+
|Type Name|\`SSRStatus\`|
|
|
11
|
+
|Source Path|\`./packages/react/src/hooks/use-ssr-status.ts\`|
|
|
12
|
+
|
|
13
|
+
\*ExtractedTypeTable: Could not extract "SSRStatus" from "./packages/react/src/hooks/use-ssr-status.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
14
|
+
|
|
15
|
+
> ℹ️ **Info:**
|
|
16
|
+
> Must be used within a ConsentManagerProvider. Throws if used outside the provider context.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Text Direction
|
|
3
|
+
description: Reference page for use text direction.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
`useTextDirection()` determines the correct text direction (`'ltr'` or `'rtl'`) based on the provided language and sets it on the document. It wraps the `@c15t/ui` text direction utilities as a React hook.
|
|
7
|
+
|
|
8
|
+
This is used internally by IAB components but is available for custom UI that needs to handle bidirectional text.
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
import { useTextDirection } from '@c15t/react/hooks';
|
|
12
|
+
|
|
13
|
+
function CustomConsentUI({ language }: { language: string }) {
|
|
14
|
+
const direction = useTextDirection(language);
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<div dir={direction}>
|
|
18
|
+
{/* Content renders correctly for RTL languages like Arabic and Hebrew */}
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Parameters
|
|
25
|
+
|
|
26
|
+
|Parameter|Type|Default|Description|
|
|
27
|
+
|--|--|--|--|
|
|
28
|
+
|`language`|`string \|undefined`|—|BCP 47 language tag (e.g. `'en'`, `'ar'`, `'he'`)|
|
|
29
|
+
|
|
30
|
+
## Return Value
|
|
31
|
+
|
|
32
|
+
|Type|Description|
|
|
33
|
+
|--|--|
|
|
34
|
+
|`'ltr' \|'rtl'`|The text direction for the given language|
|
|
35
|
+
|
|
36
|
+
## RTL Languages
|
|
37
|
+
|
|
38
|
+
The hook recognizes standard RTL languages including Arabic (`ar`), Hebrew (`he`), Persian (`fa`), and Urdu (`ur`), among others.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Translations
|
|
3
|
+
description: Reference page for use translations.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
## Translation Sections
|
|
7
|
+
|
|
8
|
+
The returned `Translations` object has these sections:
|
|
9
|
+
|
|
10
|
+
|Property|Value|
|
|
11
|
+
|:--|:--|
|
|
12
|
+
|Type Name|\`Translations\`|
|
|
13
|
+
|Source Path|\`./packages/translations/src/types.ts\`|
|
|
14
|
+
|
|
15
|
+
\*ExtractedTypeTable: Could not extract "Translations" from "./packages/translations/src/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,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Consent Banner
|
|
3
|
+
description: Reference page for consent banner.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
> ℹ️ **Info:**
|
|
7
|
+
> c15t's IAB TCF support can be used in production. Use Inth for a hosted, IAB TCF-certified CMP setup with a managed CMP ID, or register your own CMP with IAB Europe and configure your own CMP ID.
|
|
8
|
+
|
|
9
|
+
`IABConsentBanner` is a pre-built consent banner that follows the [IAB Transparency & Consent Framework (TCF) 2.3](https://iabeurope.eu/tcf-2-0/) specification. It renders when the consent model is set to `'iab'` and includes required disclosures like partner count, purpose summaries, and legitimate interest notices.
|
|
10
|
+
|
|
11
|
+
Use this component instead of `ConsentBanner` when you need IAB TCF compliance for programmatic advertising in EU jurisdictions.
|
|
12
|
+
|
|
13
|
+
## When to Use
|
|
14
|
+
|
|
15
|
+
* Your site participates in the IAB TCF ecosystem (ad exchanges, SSPs, DSPs)
|
|
16
|
+
* You need to disclose vendor partnerships and data processing purposes per IAB requirements
|
|
17
|
+
* The detected jurisdiction requires IAB TCF compliance (typically EU/EEA)
|
|
18
|
+
|
|
19
|
+
> ℹ️ **Info:**
|
|
20
|
+
> The banner only renders when IAB mode is enabled and the GVL (Global Vendor List) has been loaded. If iab.enabled is false or the server does not return GVL data, nothing is rendered.
|
|
21
|
+
|
|
22
|
+
## Banner Content
|
|
23
|
+
|
|
24
|
+
The IAB banner automatically displays:
|
|
25
|
+
|
|
26
|
+
* **Title** — Heading text from IAB translations
|
|
27
|
+
* **Description** — Includes the partner count (e.g., "We and our \{partnerCount} partners...")
|
|
28
|
+
* **Partners link** — Clickable link that opens the vendor tab in the preference center
|
|
29
|
+
* **Purpose/stack list** — Up to 5 purpose/stack names summarizing data usage, with an "and X more" overflow
|
|
30
|
+
* **Legitimate interest notice** — Required IAB disclosure about legitimate interest processing
|
|
31
|
+
* **Scope notice** — Service-specific scope disclosure
|
|
32
|
+
|
|
33
|
+
## Buttons
|
|
34
|
+
|
|
35
|
+
The banner includes three action buttons:
|
|
36
|
+
|
|
37
|
+
|Button|Action|
|
|
38
|
+
|--|--|
|
|
39
|
+
|**Reject All**|Rejects all IAB purposes and closes the banner|
|
|
40
|
+
|**Accept All**|Accepts all IAB purposes and closes the banner|
|
|
41
|
+
|**Customize**|Opens the IABConsentDialog purposes tab|
|
|
42
|
+
|
|
43
|
+
### Primary Button
|
|
44
|
+
|
|
45
|
+
Highlight a specific button as the primary action:
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
<IABConsentBanner primaryButton="accept" />
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Options: `'reject'`, `'accept'`, `'customize'` (default: `'customize'`)
|
|
52
|
+
|
|
53
|
+
## Props
|
|
54
|
+
|
|
55
|
+
|Property|Value|
|
|
56
|
+
|:--|:--|
|
|
57
|
+
|Type Name|\`IABConsentBannerProps\`|
|
|
58
|
+
|Source Path|\`./packages/react/src/components/iab-consent-banner/iab-consent-banner.tsx\`|
|
|
59
|
+
|
|
60
|
+
\*ExtractedTypeTable: Could not extract "IABConsentBannerProps" from "./packages/react/src/components/iab-consent-banner/iab-consent-banner.tsx" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Consent Dialog
|
|
3
|
+
description: Reference page for consent dialog.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
> ℹ️ **Info:**
|
|
7
|
+
> c15t's IAB TCF support can be used in production. Use Inth for a hosted, IAB TCF-certified CMP setup with a managed CMP ID, or register your own CMP with IAB Europe and configure your own CMP ID.
|
|
8
|
+
|
|
9
|
+
`IABConsentDialog` is an IAB TCF 2.3 compliant consent dialog that provides a tabbed interface for managing purpose consent and vendor preferences. It includes purpose grouping via stacks, individual purpose/vendor toggles, special purpose and feature disclosures, and legitimate interest handling.
|
|
10
|
+
|
|
11
|
+
## Tabs
|
|
12
|
+
|
|
13
|
+
The dialog has two tabs:
|
|
14
|
+
|
|
15
|
+
### Purposes Tab
|
|
16
|
+
|
|
17
|
+
Displays all IAB purposes grouped into:
|
|
18
|
+
|
|
19
|
+
* **Standalone purposes** — Purpose 1 (Store and/or access information on a device) is always shown standalone per IAB TCF spec
|
|
20
|
+
* **Stacks** — Groups of related purposes determined by the GVL. Each stack is expandable to show individual purpose toggles
|
|
21
|
+
* **Special features** — Opt-in features like precise geolocation
|
|
22
|
+
* **Essential functions** — Special purposes and features that are locked (no user toggle) because they're required for basic operation
|
|
23
|
+
|
|
24
|
+
Each purpose shows:
|
|
25
|
+
|
|
26
|
+
* Name and description
|
|
27
|
+
* Number of vendors using this purpose
|
|
28
|
+
* Consent toggle (or lock icon for essential functions)
|
|
29
|
+
* Legitimate interest toggle where applicable
|
|
30
|
+
* Expandable vendor list
|
|
31
|
+
|
|
32
|
+
### Vendors Tab
|
|
33
|
+
|
|
34
|
+
Displays all vendors from the GVL plus any custom vendors:
|
|
35
|
+
|
|
36
|
+
* Search and filter vendors
|
|
37
|
+
* Per-vendor consent and legitimate interest toggles
|
|
38
|
+
* Vendor details: privacy policy link, cookie usage, data retention
|
|
39
|
+
* Purpose and feature associations
|
|
40
|
+
|
|
41
|
+
## Floating Trigger
|
|
42
|
+
|
|
43
|
+
Add a floating button so users can re-open the dialog after dismissing the banner. IAB TCF requires the preference center to be easily resurfaceable:
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
<IABConsentDialog showTrigger />
|
|
47
|
+
|
|
48
|
+
{/* Custom trigger options */}
|
|
49
|
+
<IABConsentDialog
|
|
50
|
+
showTrigger={{
|
|
51
|
+
icon: 'settings',
|
|
52
|
+
defaultPosition: 'bottom-left',
|
|
53
|
+
showWhen: 'after-consent',
|
|
54
|
+
size: 'sm',
|
|
55
|
+
}}
|
|
56
|
+
/>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Footer Actions
|
|
60
|
+
|
|
61
|
+
The dialog footer provides three buttons:
|
|
62
|
+
|
|
63
|
+
|Button|Action|
|
|
64
|
+
|--|--|
|
|
65
|
+
|**Reject All**|Rejects all purposes and vendors, closes dialog and banner|
|
|
66
|
+
|**Accept All**|Accepts all purposes and vendors, closes dialog and banner|
|
|
67
|
+
|**Save Settings**|Saves current selections, closes dialog and banner|
|
|
68
|
+
|
|
69
|
+
## Props
|
|
70
|
+
|
|
71
|
+
|Property|Value|
|
|
72
|
+
|:--|:--|
|
|
73
|
+
|Type Name|\`IABConsentDialogProps\`|
|
|
74
|
+
|Source Path|\`./packages/react/src/components/iab-consent-dialog/iab-consent-dialog.tsx\`|
|
|
75
|
+
|
|
76
|
+
\*ExtractedTypeTable: Could not extract "IABConsentDialogProps" from "./packages/react/src/components/iab-consent-dialog/iab-consent-dialog.tsx" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Overview
|
|
3
|
+
description: Reference page for overview.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
## What is IAB TCF?
|
|
7
|
+
|
|
8
|
+
The [IAB Transparency & Consent Framework (TCF)](https://iabeurope.eu/tcf-2-0/) is a standardized protocol for communicating user consent choices to ad tech vendors in the programmatic advertising ecosystem. TCF 2.3 is the current version and is widely adopted across the EU/EEA.
|
|
9
|
+
|
|
10
|
+
When your site participates in the IAB ecosystem (ad exchanges, SSPs, DSPs, DMPs), you need to:
|
|
11
|
+
|
|
12
|
+
* Disclose which vendors process user data and for what purposes
|
|
13
|
+
* Collect granular consent for each IAB-defined purpose
|
|
14
|
+
* Generate a **TC String** — a standardized encoding of consent choices that ad tech vendors can read
|
|
15
|
+
* Expose the `__tcfapi` CMP stub for vendor scripts to query consent status
|
|
16
|
+
|
|
17
|
+
## CMP Registration
|
|
18
|
+
|
|
19
|
+
[Inth](https://inth.com), c15t's hosted platform, is IAB TCF certified. When you use Inth as your backend with c15t's prebuilt IAB UI, the correct CMP ID is automatically provided to your client via the `/init` endpoint — no client-side configuration needed.
|
|
20
|
+
|
|
21
|
+
If you self-host the c15t backend or want to operate as your own CMP, register your own CMP with IAB Europe and configure your CMP ID on the backend via `advanced.iab.cmpId` or on the client via the `iab.cmpId` option. Registering your own CMP may also involve IAB Europe fees, so check IAB Europe's current CMP registration terms and pricing before choosing this route. A valid (non-zero) CMP ID is required for IAB TCF compliance.
|
|
22
|
+
|
|
23
|
+
> ⚠️ **Warning:**
|
|
24
|
+
> If you heavily customize or build your own IAB banner or dialog instead of using the default IABConsentBanner and IABConsentDialog components, you cannot use Inth's CMP ID. You must register your own CMP with IAB Europe and use your own CMP ID.
|
|
25
|
+
|
|
26
|
+
## How c15t Implements TCF
|
|
27
|
+
|
|
28
|
+
c15t provides a complete IAB TCF 2.3 CMP (Consent Management Platform) implementation:
|
|
29
|
+
|
|
30
|
+
1. **Global Vendor List (GVL)** — Automatically fetched from the c15t backend. Contains the official IAB vendor registry with purposes, features, and stacks.
|
|
31
|
+
2. **IABConsentBanner** — A pre-built banner showing partner count, purpose summaries, and legitimate interest notices.
|
|
32
|
+
3. **IABConsentDialog** — A tabbed preference center for granular purpose and vendor consent management.
|
|
33
|
+
4. **TC String generation** — Consent choices are encoded into the standard TC String format.
|
|
34
|
+
5. **`__tcfapi` stub** — The standard CMP API is exposed on `window` so vendor scripts can query consent.
|
|
35
|
+
|
|
36
|
+
If you use the prebuilt styled IAB UI, add your framework's `iab/styles.css` entrypoint alongside the base c15t stylesheet. IAB CSS is published separately so apps that do not render IAB surfaces do not ship those component rules.
|
|
37
|
+
|
|
38
|
+
## IAB Configuration Options
|
|
39
|
+
|
|
40
|
+
Configure IAB mode with `iab({ ... })` from `@c15t/iab`. The factory enables the addon and injects the runtime module automatically. The user-facing options are:
|
|
41
|
+
|
|
42
|
+
|Option|Type|Description|
|
|
43
|
+
|--|--|--|
|
|
44
|
+
|`cmpId`|`number`|CMP ID registered with IAB Europe. Automatically provided by the backend when using Inth with the prebuilt IAB UI. Only set this if you have your own CMP registration.|
|
|
45
|
+
|`vendors`|`number[]`|IAB vendor IDs that your site works with|
|
|
46
|
+
|`customVendors`|`NonIABVendor[]`|Custom vendors not in the IAB registry|
|
|
47
|
+
|
|
48
|
+
## Key Concepts
|
|
49
|
+
|
|
50
|
+
### Purposes
|
|
51
|
+
|
|
52
|
+
IAB defines 11 standard purposes for data processing (e.g., "Store and/or access information on a device", "Select basic ads", "Measure ad performance"). Each purpose can be consented to individually.
|
|
53
|
+
|
|
54
|
+
### Stacks
|
|
55
|
+
|
|
56
|
+
Purposes are grouped into **stacks** by the GVL for a simplified UI presentation. For example, "Advertising based on limited data" might group purposes 2, 7, and 10 together.
|
|
57
|
+
|
|
58
|
+
### Special Features
|
|
59
|
+
|
|
60
|
+
Features like precise geolocation or device scanning that require explicit opt-in beyond standard consent.
|
|
61
|
+
|
|
62
|
+
### Legitimate Interest
|
|
63
|
+
|
|
64
|
+
Some purposes can be processed under legitimate interest rather than consent. Users can object to legitimate interest processing per-vendor.
|
|
65
|
+
|
|
66
|
+
### Vendors
|
|
67
|
+
|
|
68
|
+
Each vendor in the GVL declares which purposes it uses, whether via consent or legitimate interest. The preference center lets users toggle consent per-vendor.
|
|
69
|
+
|
|
70
|
+
## Standard vs IAB Components
|
|
71
|
+
|
|
72
|
+
|Feature|ConsentBanner / ConsentDialog|IABConsentBanner / IABConsentDialog|
|
|
73
|
+
|--|--|--|
|
|
74
|
+
|Consent model|opt-in / opt-out|IAB TCF 2.3|
|
|
75
|
+
|Granularity|Category-level (measurement, marketing, etc.)|Purpose-level + vendor-level|
|
|
76
|
+
|Vendor management|No|Yes (full GVL integration)|
|
|
77
|
+
|TC String|No|Yes|
|
|
78
|
+
|`__tcfapi`|No|Yes|
|
|
79
|
+
|Legitimate interest|No|Yes|
|
|
80
|
+
|Use when|General GDPR/CCPA compliance|Programmatic advertising in EU/EEA|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use GVL Data
|
|
3
|
+
description: Reference page for use gvl data.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
> ⚠️ **Warning:**
|
|
7
|
+
> c15t's IAB TCF support can be used in production through Inth or with your own registered CMP ID. useGVLData() is different: it remains an internal hook and is not part of the supported public API.
|
|
8
|
+
|
|
9
|
+
`useGVLData()` currently powers the built-in `IABConsentDialog`, but it is **not part of the public package surface**.
|
|
10
|
+
|
|
11
|
+
Older docs showed it as a public hook. That is no longer accurate.
|
|
12
|
+
|
|
13
|
+
If you need supported customization points today:
|
|
14
|
+
|
|
15
|
+
* Use `IABConsentBanner` and `IABConsentDialog` from `@c15t/react/iab` for the supported prebuilt UI
|
|
16
|
+
* Use `useHeadlessIABConsentUI()` from `@c15t/react/iab` when you need lower-level control over banner/dialog state and actions
|
|
17
|
+
|
|
18
|
+
> ⚠️ **Warning:**
|
|
19
|
+
> Until useGVLData() is exported as public API, avoid importing it from deep internal paths. Those paths are not covered by semver guarantees and can change without notice.
|
|
20
|
+
|
|
21
|
+
When a public GVL-focused hook becomes part of the supported API, this page should document that public surface instead of the internal dialog hook.
|