@c15t/nextjs 2.2.0 → 3.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +102 -142
- package/README.md +4 -4
- package/dist/api.js +1 -0
- package/dist/config.js +1 -0
- package/dist/devtools.js +2 -0
- package/dist/headers.js +1 -0
- package/dist/iab/styles.css +1 -1
- package/dist/iab/styles.tw3.css +133 -19
- package/dist/index.js +1 -1
- package/dist/middleware.js +1 -0
- package/dist/node-bridge.js +1 -0
- package/dist/pages.js +1 -0
- package/dist/proxy.js +1 -0
- package/dist/root.js +2 -0
- package/dist/server.js +1 -0
- package/dist/static.js +1 -0
- package/dist/styles.css +1 -1
- package/dist/styles.tw3.css +173 -29
- package/dist/version.js +1 -1
- package/dist-types/api.d.ts +88 -0
- package/dist-types/config.d.ts +110 -0
- package/dist-types/devtools.d.ts +1 -0
- package/dist-types/headers.d.ts +4 -0
- package/dist-types/index.d.ts +28 -10
- package/dist-types/middleware.d.ts +15 -0
- package/dist-types/node-bridge.d.ts +57 -0
- package/dist-types/pages.d.ts +88 -0
- package/dist-types/proxy.d.ts +34 -0
- package/dist-types/root.d.ts +86 -0
- package/dist-types/server.d.ts +164 -0
- package/dist-types/static.d.ts +42 -0
- package/dist-types/types.d.ts +5 -36
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +102 -142
- package/docs/assets/v3/brand-bar.png +0 -0
- package/docs/assets/v3/brand-card.png +0 -0
- package/docs/assets/v3/choice-wall.png +0 -0
- package/docs/assets/v3/mobile-card.png +0 -0
- package/docs/assets/v3/preferences.png +0 -0
- package/docs/customization/overview.md +45 -0
- package/docs/customization/recipes.md +79 -0
- package/docs/customization/slots.md +55 -0
- package/docs/customization/tokens.md +76 -0
- package/docs/customization/translations.md +49 -0
- package/docs/frameworks/next/api-reference/data-fetching.md +416 -0
- package/docs/frameworks/next/app-router.md +403 -0
- package/docs/frameworks/next/client-side.md +118 -0
- package/docs/frameworks/next/components/consent-banner.md +251 -211
- package/docs/frameworks/next/components/consent-dialog-link.md +96 -35
- package/docs/frameworks/next/components/consent-dialog-trigger.md +74 -149
- package/docs/frameworks/next/components/consent-dialog.md +189 -134
- package/docs/frameworks/next/components/consent-manager-provider.md +60 -318
- package/docs/frameworks/next/components/consent-widget.md +172 -114
- package/docs/frameworks/next/components/dev-tools.md +199 -40
- package/docs/frameworks/next/components/frame.md +137 -42
- package/docs/frameworks/next/concepts/consent-categories.md +24 -89
- package/docs/frameworks/next/concepts/policy-presets.md +142 -0
- package/docs/frameworks/next/content-security-policy.md +189 -0
- package/docs/frameworks/next/data-fetching.md +74 -0
- package/docs/frameworks/next/geography-headers.md +251 -0
- package/docs/frameworks/next/headless.md +95 -185
- package/docs/frameworks/next/hooks/use-consent-manager/overview.md +42 -163
- package/docs/frameworks/next/iab/overview.md +37 -107
- package/docs/frameworks/next/optimization.md +158 -194
- package/docs/frameworks/next/pages-router.md +296 -0
- package/docs/frameworks/next/quickstart.md +31 -132
- package/docs/frameworks/next/script-loader.md +134 -467
- package/docs/frameworks/next/server-side.md +97 -130
- package/docs/frameworks/next/static-export.md +164 -0
- package/docs/frameworks/next/styling/overview.md +166 -250
- package/docs/frameworks/next/troubleshooting.md +134 -144
- package/docs/guides/consent-state.md +60 -0
- package/docs/guides/data-fetching.md +163 -0
- package/docs/guides/deployment-modes.md +63 -0
- package/docs/guides/troubleshooting.md +68 -0
- package/docs/guides/verify-consent.md +62 -0
- package/docs/integrations/adobe-analytics.md +239 -105
- package/docs/integrations/ahrefs-analytics.md +238 -104
- package/docs/integrations/amplitude.md +219 -157
- package/docs/integrations/building-integrations.md +32 -224
- package/docs/integrations/clearbit.md +247 -86
- package/docs/integrations/cloudflare-web-analytics.md +250 -84
- package/docs/integrations/crisp.md +251 -97
- package/docs/integrations/databuddy.md +259 -153
- package/docs/integrations/fathom-analytics.md +239 -96
- package/docs/integrations/google-maps.md +328 -207
- package/docs/integrations/google-tag-manager.md +248 -96
- package/docs/integrations/google-tag.md +261 -90
- package/docs/integrations/heap.md +222 -149
- package/docs/integrations/hightouch.md +225 -131
- package/docs/integrations/hotjar.md +239 -90
- package/docs/integrations/intercom.md +239 -98
- package/docs/integrations/linkedin-insights.md +243 -113
- package/docs/integrations/logrocket.md +241 -123
- package/docs/integrations/matomo-analytics.md +256 -111
- package/docs/integrations/meta-pixel.md +197 -324
- package/docs/integrations/microsoft-clarity.md +233 -114
- package/docs/integrations/microsoft-uet.md +245 -110
- package/docs/integrations/mixpanel-analytics.md +252 -87
- package/docs/integrations/openai-pixel.md +441 -0
- package/docs/integrations/overview.md +95 -133
- package/docs/integrations/pirsch.md +249 -96
- package/docs/integrations/plausible-analytics.md +241 -100
- package/docs/integrations/posthog.md +353 -214
- package/docs/integrations/promptwatch.md +251 -81
- package/docs/integrations/reddit-pixel.md +226 -173
- package/docs/integrations/rudderstack.md +244 -187
- package/docs/integrations/rybbit-analytics.md +244 -91
- package/docs/integrations/segment.md +238 -92
- package/docs/integrations/snapchat-pixel.md +240 -110
- package/docs/integrations/tiktok-pixel.md +249 -81
- package/docs/integrations/umami-analytics.md +242 -95
- package/docs/integrations/vercel-analytics.md +242 -90
- package/docs/integrations/x-pixel.md +238 -104
- package/docs/integrations/youtube.md +354 -142
- package/docs/upgrade-v3.md +334 -0
- package/iab/styles.css +1 -1
- package/iab/styles.tw3.css +1 -1
- package/package.json +106 -65
- package/readme.json +3 -3
- package/src/iab/styles.css +1 -1
- package/src/iab/styles.tw3.css +1 -1
- package/src/styles.css +1 -1
- package/src/styles.tw3.css +1 -1
- package/styles.css +1 -1
- package/styles.tw3.css +1 -1
- package/client/components/consent-dialog-link.js +0 -3
- package/client/components/integrations.js +0 -3
- package/dist/components/integrations/index.cjs +0 -1
- package/dist/components/integrations/index.js +0 -1
- package/dist/headless.cjs +0 -1
- package/dist/index.cjs +0 -1
- package/dist/libs/browser-initial-data.cjs +0 -1
- package/dist/libs/browser-initial-data.js +0 -1
- package/dist/libs/initial-data.cjs +0 -1
- package/dist/libs/initial-data.js +0 -1
- package/dist/types.cjs +0 -1
- package/dist/version.cjs +0 -1
- package/dist-types/components/integrations/index.d.ts +0 -1
- package/dist-types/libs/browser-initial-data.d.ts +0 -9
- package/dist-types/libs/initial-data.d.ts +0 -33
- package/docs/frameworks/next/building-headless-components.md +0 -379
- package/docs/frameworks/next/callbacks.md +0 -186
- package/docs/frameworks/next/concepts/client-modes.md +0 -177
- package/docs/frameworks/next/concepts/consent-models.md +0 -117
- package/docs/frameworks/next/concepts/cookie-management.md +0 -122
- package/docs/frameworks/next/concepts/glossary.md +0 -24
- package/docs/frameworks/next/concepts/initialization-flow.md +0 -149
- package/docs/frameworks/next/concepts/policy-packs.md +0 -230
- package/docs/frameworks/next/hooks/use-color-scheme.md +0 -41
- package/docs/frameworks/next/hooks/use-consent-manager/checking-consent.md +0 -96
- package/docs/frameworks/next/hooks/use-consent-manager/location-info.md +0 -97
- package/docs/frameworks/next/hooks/use-consent-manager/setting-consent.md +0 -94
- package/docs/frameworks/next/hooks/use-draggable.md +0 -59
- package/docs/frameworks/next/hooks/use-focus-trap.md +0 -42
- package/docs/frameworks/next/hooks/use-reduced-motion.md +0 -37
- package/docs/frameworks/next/hooks/use-ssr-status.md +0 -32
- package/docs/frameworks/next/hooks/use-text-direction.md +0 -50
- package/docs/frameworks/next/hooks/use-translations.md +0 -55
- package/docs/frameworks/next/iab/consent-banner.md +0 -91
- package/docs/frameworks/next/iab/consent-dialog.md +0 -129
- package/docs/frameworks/next/iab/use-gvl-data.md +0 -21
- package/docs/frameworks/next/iframe-blocking.md +0 -106
- package/docs/frameworks/next/internationalization.md +0 -207
- package/docs/frameworks/next/network-blocker.md +0 -140
- package/docs/frameworks/next/policy-packs.md +0 -248
- package/docs/frameworks/next/styling/classnames.md +0 -94
- package/docs/frameworks/next/styling/color-scheme.md +0 -84
- package/docs/frameworks/next/styling/css-variables.md +0 -53
- package/docs/frameworks/next/styling/slots.md +0 -94
- package/docs/frameworks/next/styling/tailwind.md +0 -137
- package/docs/frameworks/next/styling/tokens.md +0 -156
- package/docs/shared/concepts/client-modes.md +0 -103
- package/docs/shared/concepts/consent-categories.md +0 -41
- package/docs/shared/concepts/consent-models.md +0 -72
- package/docs/shared/concepts/cookie-management.md +0 -88
- package/docs/shared/concepts/glossary.md +0 -24
- package/docs/shared/concepts/initialization-flow.md +0 -105
- package/docs/shared/concepts/policy-packs.md +0 -225
- package/docs/shared/react/components/consent-banner.md +0 -242
- package/docs/shared/react/components/consent-dialog-link.md +0 -45
- package/docs/shared/react/components/consent-dialog-trigger.md +0 -185
- package/docs/shared/react/components/consent-dialog.md +0 -119
- package/docs/shared/react/components/consent-manager-provider.md +0 -225
- package/docs/shared/react/components/consent-widget.md +0 -121
- package/docs/shared/react/components/dev-tools.md +0 -81
- package/docs/shared/react/components/frame.md +0 -52
- package/docs/shared/react/guides/building-headless-components.md +0 -110
- package/docs/shared/react/guides/callbacks.md +0 -89
- package/docs/shared/react/guides/headless.md +0 -31
- package/docs/shared/react/guides/iframe-blocking.md +0 -65
- package/docs/shared/react/guides/internationalization.md +0 -123
- package/docs/shared/react/guides/network-blocker.md +0 -72
- package/docs/shared/react/guides/optimization.md +0 -44
- package/docs/shared/react/guides/policy-packs.md +0 -173
- package/docs/shared/react/guides/script-loader.md +0 -311
- package/docs/shared/react/hooks/use-color-scheme.md +0 -31
- package/docs/shared/react/hooks/use-consent-manager/checking-consent.md +0 -95
- package/docs/shared/react/hooks/use-consent-manager/location-info.md +0 -96
- package/docs/shared/react/hooks/use-consent-manager/overview.md +0 -74
- package/docs/shared/react/hooks/use-consent-manager/setting-consent.md +0 -93
- package/docs/shared/react/hooks/use-draggable.md +0 -30
- package/docs/shared/react/hooks/use-focus-trap.md +0 -20
- package/docs/shared/react/hooks/use-reduced-motion.md +0 -33
- package/docs/shared/react/hooks/use-ssr-status.md +0 -16
- package/docs/shared/react/hooks/use-text-direction.md +0 -38
- package/docs/shared/react/hooks/use-translations.md +0 -15
- package/docs/shared/react/iab/consent-banner.md +0 -60
- package/docs/shared/react/iab/consent-dialog.md +0 -76
- package/docs/shared/react/iab/overview.md +0 -80
- package/docs/shared/react/iab/use-gvl-data.md +0 -21
- package/docs/shared/react/styling/classnames.md +0 -93
- package/docs/shared/react/styling/color-scheme.md +0 -35
- package/docs/shared/react/styling/css-variables.md +0 -53
- package/docs/shared/react/styling/overview.md +0 -261
- package/docs/shared/react/styling/slots.md +0 -93
- package/docs/shared/react/styling/stylesheet-entrypoint.md +0 -8
- package/docs/shared/react/styling/tailwind.md +0 -88
- package/docs/shared/react/styling/tokens.md +0 -155
- package/docs/shared/troubleshooting.md +0 -82
|
@@ -1,185 +1,64 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
3
|
-
description:
|
|
4
|
-
the
|
|
2
|
+
title: Hooks
|
|
3
|
+
description: Gate features and save consent choices in Next.js Client Components
|
|
4
|
+
with the focused hooks exported from c15t/next.
|
|
5
5
|
group: frameworks
|
|
6
6
|
---
|
|
7
|
-
`useConsentManager()` is the primary hook for interacting with the consent system. It returns the complete consent store state and all action methods.
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
import { useConsentManager } from '@c15t/nextjs';
|
|
8
|
+
## Read only the state you need
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
saveConsents,
|
|
18
|
-
// ... all state and actions
|
|
19
|
-
} = useConsentManager();
|
|
20
|
-
}
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
> ⚠️ **Warning:**
|
|
24
|
-
> Must be used within a ConsentManagerProvider. Throws an error if used outside the provider.
|
|
25
|
-
|
|
26
|
-
## State Properties
|
|
27
|
-
|
|
28
|
-
|Property|Value|
|
|
29
|
-
|:--|:--|
|
|
30
|
-
|Type Name|\`StoreRuntimeState\`|
|
|
31
|
-
|Source Path|\`./packages/core/src/store/type.ts\`|
|
|
32
|
-
|
|
33
|
-
\*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.\*
|
|
34
|
-
|
|
35
|
-
## Action Methods
|
|
36
|
-
|
|
37
|
-
|Property|Value|
|
|
38
|
-
|:--|:--|
|
|
39
|
-
|Type Name|\`StoreActions\`|
|
|
40
|
-
|Source Path|\`./packages/core/src/store/type.ts\`|
|
|
41
|
-
|
|
42
|
-
\*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.\*
|
|
43
|
-
|
|
44
|
-
## User Identification
|
|
45
|
-
|
|
46
|
-
You can link a consent subject to your own internal user ID or a non-secret anonymous visitor ID. c15t stores the identifier in the subject row's `externalId` field. Consent records remain associated with that subject through `subjectId`, so your backend can find the subject and its related consent records by external ID for GDPR Article 15 exports.
|
|
47
|
-
|
|
48
|
-
### 1. Providing the Current User ID
|
|
49
|
-
|
|
50
|
-
When using Clerk, prefer the Clerk `userId` whenever the visitor is signed in. Before sign-in, you can fall back to a non-secret visitor ID stored in a first-party cookie:
|
|
51
|
-
|
|
52
|
-
> ⚠️ **Warning:**
|
|
53
|
-
> ConsentManagerProvider runs on the client. Values passed through options.user are therefore available to client-side JavaScript, even when they were read from an HttpOnly cookie on the server. Pass only a non-secret identifier, such as a Clerk userId or an opaque visitor ID. Never pass a Clerk session token or a value returned by getToken().
|
|
54
|
-
>
|
|
55
|
-
> ℹ️ **Info:**
|
|
56
|
-
> Clerk's auth() helper requires clerkMiddleware() to be configured. This example also uses the asynchronous cookies() API from Next.js 15+. For Next.js 14 and earlier, use const cookieStore = cookies(); without await. Keep the layout asynchronous because Clerk's auth() is asynchronous.
|
|
57
|
-
|
|
58
|
-
```tsx
|
|
59
|
-
// app/layout.tsx
|
|
60
|
-
import { ClerkProvider } from '@clerk/nextjs';
|
|
61
|
-
import { auth } from '@clerk/nextjs/server';
|
|
62
|
-
import { ConsentManagerProvider } from '@c15t/nextjs';
|
|
63
|
-
import { cookies } from 'next/headers';
|
|
64
|
-
import { ClerkConsentSync } from './clerk-consent-sync';
|
|
65
|
-
|
|
66
|
-
export default async function RootLayout({ children }: { children: React.ReactNode }) {
|
|
67
|
-
const { userId } = await auth();
|
|
68
|
-
const cookieStore = await cookies();
|
|
69
|
-
const visitorId = cookieStore.get('consent_visitor_id')?.value;
|
|
70
|
-
const consentUser = userId
|
|
71
|
-
? { id: userId, identityProvider: 'clerk' }
|
|
72
|
-
: visitorId
|
|
73
|
-
? { id: visitorId, identityProvider: 'anonymous-visitor' }
|
|
74
|
-
: undefined;
|
|
75
|
-
|
|
76
|
-
return (
|
|
77
|
-
<html lang="en">
|
|
78
|
-
<body>
|
|
79
|
-
<ClerkProvider>
|
|
80
|
-
<ConsentManagerProvider
|
|
81
|
-
options={{
|
|
82
|
-
mode: 'hosted',
|
|
83
|
-
backendURL: '/api/c15t',
|
|
84
|
-
consentCategories: ['necessary', 'measurement', 'marketing'],
|
|
85
|
-
user: consentUser,
|
|
86
|
-
}}
|
|
87
|
-
>
|
|
88
|
-
<ClerkConsentSync />
|
|
89
|
-
{children}
|
|
90
|
-
</ConsentManagerProvider>
|
|
91
|
-
</ClerkProvider>
|
|
92
|
-
</body>
|
|
93
|
-
</html>
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### 2. Synchronizing Clerk Sign-ins
|
|
99
|
-
|
|
100
|
-
Clerk can complete a sign-in without reloading the page. Add a client component inside `ConsentManagerProvider` to update the current consent subject as soon as Clerk exposes the authenticated `userId`:
|
|
10
|
+
Every hook reads the runtime from the `ConsentRoot` set up in your
|
|
11
|
+
[App Router](../../app-router.md) or
|
|
12
|
+
[Pages Router](../../pages-router.md) guide, so call them from a
|
|
13
|
+
Client Component rendered inside that root and import them from
|
|
14
|
+
`c15t/next`.
|
|
101
15
|
|
|
102
|
-
```tsx
|
|
103
|
-
// app/clerk-consent-sync.tsx
|
|
16
|
+
```tsx title="components/optional-feature.tsx"
|
|
104
17
|
'use client';
|
|
105
18
|
|
|
106
|
-
import {
|
|
107
|
-
import { useConsentManager } from '@c15t/nextjs';
|
|
108
|
-
import { useEffect } from 'react';
|
|
109
|
-
|
|
110
|
-
export function ClerkConsentSync() {
|
|
111
|
-
const { isLoaded, isSignedIn, userId } = useAuth();
|
|
112
|
-
const { identifyUser } = useConsentManager();
|
|
113
|
-
|
|
114
|
-
useEffect(() => {
|
|
115
|
-
if (!isLoaded || !isSignedIn || !userId) {
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
19
|
+
import { useConsent } from 'c15t/next';
|
|
118
20
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}).then(() => {
|
|
123
|
-
// Prevent the old anonymous ID from replacing the Clerk ID after sign-out.
|
|
124
|
-
document.cookie =
|
|
125
|
-
'consent_visitor_id=; Max-Age=0; Path=/; SameSite=Lax';
|
|
126
|
-
});
|
|
127
|
-
}, [identifyUser, isLoaded, isSignedIn, userId]);
|
|
128
|
-
|
|
129
|
-
return null;
|
|
21
|
+
export function OptionalFeature() {
|
|
22
|
+
const allowed = useConsent('marketing');
|
|
23
|
+
return allowed ? <div>Optional marketing content</div> : null;
|
|
130
24
|
}
|
|
131
25
|
```
|
|
132
26
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
> ℹ️ **Info:**
|
|
136
|
-
> Backend subject identification requires hosted mode (mode: 'hosted'). In offline mode, identifyUser() cannot update a backend subject. Identifiers supplied through options.user can still be held in client state and persisted with locally stored consent, so do not place sensitive values there.
|
|
137
|
-
|
|
138
|
-
## Key Types
|
|
139
|
-
|
|
140
|
-
### ConsentState
|
|
27
|
+
Call hooks inside the consent provider. `useConsent` reads effective permission,
|
|
28
|
+
which can be true under an opt-out policy without a recorded grant.
|
|
141
29
|
|
|
142
|
-
|
|
30
|
+
| Need | Hook |
|
|
31
|
+
| --------------------------------- | ------------------------------------------ |
|
|
32
|
+
| One category's current permission | `useConsent(category)` |
|
|
33
|
+
| All current permissions | `useConsents()` |
|
|
34
|
+
| Recorded per-category choices | `useExplicitChoice()` |
|
|
35
|
+
| Whether a prompt is required | `usePromptRequirement()` |
|
|
36
|
+
| Active policy and resolution | `usePolicyRule()`, `usePolicyResolution()` |
|
|
37
|
+
| Save an explicit choice | `useSaveConsents()` |
|
|
38
|
+
| Open or close a consent surface | `useSetActiveUI()` |
|
|
39
|
+
| Acknowledge a notice | `useDismissNotice()` |
|
|
143
40
|
|
|
144
|
-
|
|
145
|
-
type ConsentState = Record<AllConsentNames, boolean>;
|
|
146
|
-
// Example: { necessary: true, measurement: true, marketing: false }
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
### ConsentInfo
|
|
150
|
-
|
|
151
|
-
Metadata about when and how consent was recorded:
|
|
41
|
+
## Save from a visitor action
|
|
152
42
|
|
|
153
|
-
|
|
154
|
-
interface ConsentInfo {
|
|
155
|
-
time: number; // Epoch timestamp when consent was recorded
|
|
156
|
-
subjectId?: string; // Client-generated subject ID (sub_xxx format)
|
|
157
|
-
externalId?: string; // External user ID linked via identifyUser()
|
|
158
|
-
identityProvider?: string; // Identity provider (e.g. 'clerk', 'auth0')
|
|
159
|
-
}
|
|
160
|
-
```
|
|
43
|
+
Place this Client Component inside your existing consent boundary.
|
|
161
44
|
|
|
162
|
-
|
|
45
|
+
```tsx title="components/reject-button.tsx"
|
|
46
|
+
'use client';
|
|
163
47
|
|
|
164
|
-
|
|
48
|
+
import { useSaveConsents } from 'c15t/next';
|
|
165
49
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
regionCode: string; // Region/state code (e.g. 'BY')
|
|
170
|
-
jurisdiction: string; // Applicable jurisdiction (e.g. 'GDPR', 'CCPA')
|
|
50
|
+
export function RejectButton() {
|
|
51
|
+
const save = useSaveConsents();
|
|
52
|
+
return <button type="button" onClick={() => void save('none')}>Reject optional</button>;
|
|
171
53
|
}
|
|
172
54
|
```
|
|
173
55
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
```ts
|
|
179
|
-
type Model = 'opt-in' | 'opt-out' | 'iab' | null;
|
|
180
|
-
```
|
|
56
|
+
This is an isolated action example, not a complete policy-aware banner. Use the
|
|
57
|
+
stock UI or headless surface actions for a complete prompt. Do not call save on
|
|
58
|
+
mount to persist a state derived from permissions.
|
|
181
59
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
60
|
+
`useConsentManager` remains available for the combined UI API, including draft
|
|
61
|
+
management. Prefer focused hooks for simple feature gates and use the headless
|
|
62
|
+
UI hook when implementing a complete custom prompt. Read
|
|
63
|
+
[consent state](../../../../guides/consent-state.md) before treating a callback as evidence
|
|
64
|
+
of a choice.
|
|
@@ -1,128 +1,58 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: IAB TCF
|
|
3
|
-
description:
|
|
4
|
-
|
|
2
|
+
title: IAB TCF
|
|
3
|
+
description: Mount the IAB TCF banner and dialog inside a Next.js ConsentRoot
|
|
4
|
+
and configure the CMP ID, policy and vendor data.
|
|
5
5
|
group: frameworks
|
|
6
6
|
---
|
|
7
|
-
## What is IAB TCF?
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
## Prepare the IAB configuration
|
|
10
9
|
|
|
11
|
-
|
|
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.
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
* Generate a **TC String** — a standardized encoding of consent choices that ad tech vendors can read
|
|
16
|
-
* Expose the `__tcfapi` CMP stub for vendor scripts to query consent status
|
|
14
|
+
Install `@c15t/iab` alongside your framework adapter, then mount the IAB
|
|
15
|
+
components inside an existing consent provider connected to Inth.
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
Next.js uses the React IAB components. There is no `c15t/next/iab` JavaScript
|
|
18
|
+
entry point, so import the components from `c15t/react/iab` and render this
|
|
19
|
+
Client Component inside the `ConsentRoot` from your
|
|
20
|
+
[App Router](../app-router.md) or
|
|
21
|
+
[Pages Router](../pages-router.md) setup. Import
|
|
22
|
+
`c15t/next/iab/styles.css` at your global stylesheet entry.
|
|
19
23
|
|
|
20
|
-
|
|
24
|
+
```tsx title="components/iab-consent.tsx"
|
|
25
|
+
'use client';
|
|
21
26
|
|
|
22
|
-
|
|
27
|
+
import { IABProvider, IABConsentBanner, IABConsentDialog } from 'c15t/react/iab';
|
|
23
28
|
|
|
24
|
-
|
|
25
|
-
> 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.
|
|
26
|
-
|
|
27
|
-
## How c15t Implements TCF
|
|
28
|
-
|
|
29
|
-
c15t provides a complete IAB TCF 2.3 CMP (Consent Management Platform) implementation:
|
|
30
|
-
|
|
31
|
-
1. **Global Vendor List (GVL)** — Automatically fetched from the c15t backend. Contains the official IAB vendor registry with purposes, features, and stacks.
|
|
32
|
-
2. **IABConsentBanner** — A pre-built banner showing partner count, purpose summaries, and legitimate interest notices.
|
|
33
|
-
3. **IABConsentDialog** — A tabbed preference center for granular purpose and vendor consent management.
|
|
34
|
-
4. **TC String generation** — Consent choices are encoded into the standard TC String format.
|
|
35
|
-
5. **`__tcfapi` stub** — The standard CMP API is exposed on `window` so vendor scripts can query consent.
|
|
36
|
-
|
|
37
|
-
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.
|
|
38
|
-
|
|
39
|
-
## Quick Setup
|
|
40
|
-
|
|
41
|
-
If you use the prebuilt styled IAB UI, import the IAB stylesheet alongside the base stylesheet in your global CSS entrypoint:
|
|
42
|
-
|
|
43
|
-
```css title="src/app/globals.css"
|
|
44
|
-
@import "@c15t/nextjs/styles.css";
|
|
45
|
-
@import "@c15t/nextjs/iab/styles.css";
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
```tsx
|
|
49
|
-
import { type ReactNode } from 'react';
|
|
50
|
-
import { iab } from '@c15t/iab';
|
|
51
|
-
import { ConsentManagerProvider } from '@c15t/nextjs';
|
|
52
|
-
import { IABConsentBanner, IABConsentDialog } from '@c15t/react/iab';
|
|
53
|
-
|
|
54
|
-
export default function ConsentManager({ children }: { children: ReactNode }) {
|
|
29
|
+
export function IABConsent({ cmpId }: { cmpId: number }) {
|
|
55
30
|
return (
|
|
56
|
-
<
|
|
57
|
-
options={{
|
|
58
|
-
mode: 'hosted',
|
|
59
|
-
backendURL: '/api/c15t',
|
|
60
|
-
iab: iab({
|
|
61
|
-
vendors: [1, 2, 10, 25], // IAB vendor IDs you work with
|
|
62
|
-
// cmpId is automatically provided by the backend (inth.com).
|
|
63
|
-
// Only set this if you have your own CMP registration with IAB Europe.
|
|
64
|
-
// cmpId: 123,
|
|
65
|
-
}),
|
|
66
|
-
}}
|
|
67
|
-
>
|
|
31
|
+
<IABProvider cmpId={cmpId}>
|
|
68
32
|
<IABConsentBanner />
|
|
69
|
-
<IABConsentDialog
|
|
70
|
-
|
|
71
|
-
</ConsentManagerProvider>
|
|
33
|
+
<IABConsentDialog />
|
|
34
|
+
</IABProvider>
|
|
72
35
|
);
|
|
73
36
|
}
|
|
74
37
|
```
|
|
75
38
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
Configure IAB mode with `iab({ ... })` from `@c15t/iab`. The factory enables the addon and injects the runtime module automatically. The user-facing options are:
|
|
79
|
-
|
|
80
|
-
|Option|Type|Description|
|
|
81
|
-
|--|--|--|
|
|
82
|
-
|`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.|
|
|
83
|
-
|`vendors`|`number[]`|IAB vendor IDs that your site works with|
|
|
84
|
-
|`customVendors`|`NonIABVendor[]`|Custom vendors not in the IAB registry|
|
|
85
|
-
|
|
86
|
-
## Key Concepts
|
|
87
|
-
|
|
88
|
-
### Purposes
|
|
89
|
-
|
|
90
|
-
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.
|
|
91
|
-
|
|
92
|
-
### Stacks
|
|
93
|
-
|
|
94
|
-
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.
|
|
95
|
-
|
|
96
|
-
### Special Features
|
|
97
|
-
|
|
98
|
-
Features like precise geolocation or device scanning that require explicit opt-in beyond standard consent.
|
|
99
|
-
|
|
100
|
-
### Legitimate Interest
|
|
101
|
-
|
|
102
|
-
Some purposes can be processed under legitimate interest rather than consent. Users can object to legitimate interest processing per-vendor.
|
|
103
|
-
|
|
104
|
-
### Vendors
|
|
105
|
-
|
|
106
|
-
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.
|
|
39
|
+
Supply the CMP ID from your deployment's IAB configuration. Keep a persistent
|
|
40
|
+
preferences entry point through the surrounding consent provider.
|
|
107
41
|
|
|
108
|
-
##
|
|
42
|
+
## Resolve the policy before rendering
|
|
109
43
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|Granularity|Category-level (measurement, marketing, etc.)|Purpose-level + vendor-level|
|
|
114
|
-
|Vendor management|No|Yes (full GVL integration)|
|
|
115
|
-
|TC String|No|Yes|
|
|
116
|
-
|`__tcfapi`|No|Yes|
|
|
117
|
-
|Legitimate interest|No|Yes|
|
|
118
|
-
|Use when|General GDPR/CCPA compliance|Programmatic advertising in EU/EEA|
|
|
44
|
+
IAB components remain hidden until an applicable policy resolves. Forcing a
|
|
45
|
+
dialog open does not create a policy or vendor list. Inspect resolution and the
|
|
46
|
+
Global Vendor List response before changing rendering conditions.
|
|
119
47
|
|
|
120
|
-
|
|
48
|
+
IAB presentation follows `presentation.prompt.blocking` and
|
|
49
|
+
`presentation.preferences.blocking`. A blocking dialog needs focus management,
|
|
50
|
+
scroll locking and a backdrop together. See [migration](../../../upgrade-v3.md) for
|
|
51
|
+
legacy option behavior.
|
|
121
52
|
|
|
122
|
-
|
|
123
|
-
|--|--|
|
|
124
|
-
|[IABConsentBanner](/docs/frameworks/next/iab/consent-banner)|TCF-compliant banner with partner disclosure|
|
|
125
|
-
|[IABConsentDialog](/docs/frameworks/next/iab/consent-dialog)|Tabbed preference center for purposes and vendors|
|
|
53
|
+
## Verify vendor and purpose choices
|
|
126
54
|
|
|
127
|
-
|
|
128
|
-
|
|
55
|
+
Test category choices alongside vendor, purpose, legitimate-interest and special
|
|
56
|
+
feature controls used by your integration. Confirm the TC String and `__tcfapi`
|
|
57
|
+
reflect the saved state, and verify the vendor's actual requests. A category-only
|
|
58
|
+
banner test does not establish that the IAB flow works.
|