@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
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Pages Router
|
|
3
|
+
description: Set up Pages Router with Inth, cached manifests and consent-gated scripts.
|
|
4
|
+
group: frameworks
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Before you start
|
|
8
|
+
|
|
9
|
+
This guide uses [Inth](https://inth.com) with cached manifests. Your Next.js
|
|
10
|
+
server reuses public policy data and resolves consent for each visitor. The
|
|
11
|
+
browser sends consent submissions to Inth.
|
|
12
|
+
|
|
13
|
+
You can use a [self-hosted backend](https://c15t.com/docs/self-host/quickstart) with the same
|
|
14
|
+
configuration and your own endpoint. [Offline mode](./api-reference/data-fetching.md#offline-configuration)
|
|
15
|
+
uses bundled policy and browser storage without backend records. Not recommended
|
|
16
|
+
for production environments.
|
|
17
|
+
|
|
18
|
+
This setup needs a Next.js server. For `output: 'export'`, follow
|
|
19
|
+
[static export](./static-export.md). For a smaller setup with no
|
|
20
|
+
local API routes, use [client-side initialization](./client-side.md).
|
|
21
|
+
Same-origin [rewrites](./optimization.md) are optional.
|
|
22
|
+
|
|
23
|
+
Location-based policies need trusted location headers from your host. Without
|
|
24
|
+
them, c15t uses your unknown-location rule. Check the supported
|
|
25
|
+
[geography headers](./api-reference/data-fetching.md#geography-and-privacy-signals)
|
|
26
|
+
before deploying.
|
|
27
|
+
|
|
28
|
+
The setup below uses `getServerSideProps` for request-specific consent. Pages
|
|
29
|
+
without prefetch initialize in the browser through the same `ConsentRoot`.
|
|
30
|
+
|
|
31
|
+
## Install c15t and configure your backend
|
|
32
|
+
|
|
33
|
+
[Create an Inth project](https://inth.com), configure its policy rules and allow
|
|
34
|
+
your app's origin. Copy its backend endpoint for the upstream configuration.
|
|
35
|
+
|
|
36
|
+
If you chose self-hosting, complete the
|
|
37
|
+
[backend quickstart](https://c15t.com/docs/self-host/quickstart) and use its public endpoint in
|
|
38
|
+
the steps below. Offline setups do not need an endpoint; use the
|
|
39
|
+
[offline example](./api-reference/data-fetching.md#offline-configuration).
|
|
40
|
+
|
|
41
|
+
| Package manager | Command |
|
|
42
|
+
| :-------------- | :----------------- |
|
|
43
|
+
| npm | `npm install c15t` |
|
|
44
|
+
| pnpm | `pnpm add c15t` |
|
|
45
|
+
| yarn | `yarn add c15t` |
|
|
46
|
+
| bun | `bun add c15t` |
|
|
47
|
+
|
|
48
|
+
| Package manager | Command |
|
|
49
|
+
| :-------------- | :-------------------------- |
|
|
50
|
+
| npm | `npm install @c15t/scripts` |
|
|
51
|
+
| pnpm | `pnpm add @c15t/scripts` |
|
|
52
|
+
| yarn | `yarn add @c15t/scripts` |
|
|
53
|
+
| bun | `bun add @c15t/scripts` |
|
|
54
|
+
|
|
55
|
+
Set `NEXT_PUBLIC_C15T_BACKEND_URL` to the absolute endpoint supplied by Inth or
|
|
56
|
+
your self-hosted backend, including any path prefix. This is a public endpoint,
|
|
57
|
+
not a secret. Configure the backend to allow your app's origin.
|
|
58
|
+
|
|
59
|
+
## Share the consent URLs
|
|
60
|
+
|
|
61
|
+
Create this file at the project root. Set `manifestURL` explicitly to select
|
|
62
|
+
manifest resolution.
|
|
63
|
+
|
|
64
|
+
```ts title="c15t.config.ts"
|
|
65
|
+
import { defineConsentConfig } from 'c15t/next';
|
|
66
|
+
|
|
67
|
+
const backendURL = process.env.NEXT_PUBLIC_C15T_BACKEND_URL;
|
|
68
|
+
if (!backendURL) throw new Error('Set NEXT_PUBLIC_C15T_BACKEND_URL');
|
|
69
|
+
|
|
70
|
+
export const consentConfig = defineConsentConfig({
|
|
71
|
+
backendURL,
|
|
72
|
+
manifestURL: '/api/c15t/manifest',
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Add the manifest API route
|
|
77
|
+
|
|
78
|
+
The Pages Router adapter reads `C15T_BACKEND_URL`, falling back to the
|
|
79
|
+
`NEXT_PUBLIC_C15T_BACKEND_URL` configured above. If you set both, use the same
|
|
80
|
+
absolute backend endpoint.
|
|
81
|
+
|
|
82
|
+
```ts title="pages/api/c15t/manifest.ts"
|
|
83
|
+
import { createPagesApiHandlers } from 'c15t/next/pages';
|
|
84
|
+
|
|
85
|
+
export default createPagesApiHandlers().manifest;
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The manifest route caches public policy data. Server prefetch resolves it
|
|
89
|
+
using the visitor's request. Consent submissions go directly to `backendURL`.
|
|
90
|
+
|
|
91
|
+
The following imports assume `pages/` is at the project root. Adjust them if you
|
|
92
|
+
use `src/pages/`.
|
|
93
|
+
|
|
94
|
+
## Register scripts in a client wrapper
|
|
95
|
+
|
|
96
|
+
The [runnable Next.js example](https://c15t.com/docs/examples) uses PostHog for measurement and
|
|
97
|
+
X Pixel for marketing. Set `NEXT_PUBLIC_POSTHOG_KEY` and
|
|
98
|
+
`NEXT_PUBLIC_X_PIXEL_ID` to your own project identifiers before building.
|
|
99
|
+
`NEXT_PUBLIC_POSTHOG_HOST` optionally selects your PostHog region's API host.
|
|
100
|
+
Omit a vendor's ID to leave that integration disabled, or replace its helper
|
|
101
|
+
with the [integration](../../integrations/overview.md) your application uses. Include the
|
|
102
|
+
measurement and marketing categories in your policy for these two vendors.
|
|
103
|
+
|
|
104
|
+
Create `lib/scripts.ts` with the example's script configuration:
|
|
105
|
+
|
|
106
|
+
```ts title="lib/scripts.ts"
|
|
107
|
+
import { posthog } from '@c15t/scripts/posthog';
|
|
108
|
+
import { xPixel } from '@c15t/scripts/x-pixel';
|
|
109
|
+
import type { Script } from 'c15t';
|
|
110
|
+
|
|
111
|
+
export const posthogConfigured = Boolean(process.env.NEXT_PUBLIC_POSTHOG_KEY);
|
|
112
|
+
export const xPixelConfigured = Boolean(process.env.NEXT_PUBLIC_X_PIXEL_ID);
|
|
113
|
+
|
|
114
|
+
export const scripts: Script[] = [];
|
|
115
|
+
|
|
116
|
+
if (process.env.NEXT_PUBLIC_POSTHOG_KEY) {
|
|
117
|
+
scripts.push(
|
|
118
|
+
posthog({
|
|
119
|
+
apiHost: process.env.NEXT_PUBLIC_POSTHOG_HOST,
|
|
120
|
+
id: process.env.NEXT_PUBLIC_POSTHOG_KEY,
|
|
121
|
+
initOptions: { cookieless_mode: 'never' },
|
|
122
|
+
loadMode: 'after-consent',
|
|
123
|
+
})
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (process.env.NEXT_PUBLIC_X_PIXEL_ID) {
|
|
128
|
+
scripts.push(xPixel({ pixelId: process.env.NEXT_PUBLIC_X_PIXEL_ID }));
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
PostHog waits for measurement consent here. `cookieless_mode: 'never'` disables
|
|
133
|
+
cookieless capture after rejection. X Pixel waits for marketing consent. Remove
|
|
134
|
+
any existing loader for these vendors, including `next/script` and tag-manager
|
|
135
|
+
entries, so each integration loads once.
|
|
136
|
+
|
|
137
|
+
Create this client wrapper. It keeps scripts and browser callbacks in the client
|
|
138
|
+
while the router supplies the visitor's resolved state through `state`:
|
|
139
|
+
|
|
140
|
+
```tsx title="components/consent.tsx"
|
|
141
|
+
'use client';
|
|
142
|
+
|
|
143
|
+
import type { ReactNode } from 'react';
|
|
144
|
+
import {
|
|
145
|
+
ConsentBanner,
|
|
146
|
+
ConsentDialog,
|
|
147
|
+
ConsentDialogLink,
|
|
148
|
+
ConsentRoot,
|
|
149
|
+
} from 'c15t/next';
|
|
150
|
+
import type { ConsentRootProps } from 'c15t/next';
|
|
151
|
+
import { consentConfig } from '../c15t.config';
|
|
152
|
+
import { scripts } from '../lib/scripts';
|
|
153
|
+
|
|
154
|
+
export function Consent({
|
|
155
|
+
children,
|
|
156
|
+
state,
|
|
157
|
+
}: {
|
|
158
|
+
children: ReactNode;
|
|
159
|
+
state: ConsentRootProps['state'];
|
|
160
|
+
}) {
|
|
161
|
+
return (
|
|
162
|
+
<ConsentRoot state={state} config={consentConfig} scripts={scripts}>
|
|
163
|
+
{children}
|
|
164
|
+
<ConsentBanner />
|
|
165
|
+
<ConsentDialog />
|
|
166
|
+
<footer>
|
|
167
|
+
<ConsentDialogLink>Privacy settings</ConsentDialogLink>
|
|
168
|
+
</footer>
|
|
169
|
+
</ConsentRoot>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`ConsentRoot` already provides the consent runtime. Mount this wrapper once;
|
|
175
|
+
do not add a second provider. Keep your site's content and footer inside it.
|
|
176
|
+
|
|
177
|
+
## Keep one root in the app
|
|
178
|
+
|
|
179
|
+
Add c15t to your global stylesheet. With Tailwind CSS 4, keep its import first:
|
|
180
|
+
|
|
181
|
+
```css title="styles/globals.css"
|
|
182
|
+
@import 'tailwindcss';
|
|
183
|
+
@import 'c15t/next/styles.css';
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Without Tailwind, omit its import. For Tailwind CSS 3, use the
|
|
187
|
+
[separate stylesheet recipe](./styling/overview.md#stylesheet).
|
|
188
|
+
Keep any existing app styles and adjust the import below to their location.
|
|
189
|
+
|
|
190
|
+
```tsx title="pages/_app.tsx"
|
|
191
|
+
import type { AppProps } from 'next/app';
|
|
192
|
+
import type { ConsentRootProps } from 'c15t/next';
|
|
193
|
+
import { Consent } from '../components/consent';
|
|
194
|
+
import '../styles/globals.css';
|
|
195
|
+
|
|
196
|
+
type ConsentPageProps = {
|
|
197
|
+
consentState?: ConsentRootProps['state'];
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
export default function App({ Component, pageProps }: AppProps<ConsentPageProps>) {
|
|
201
|
+
return (
|
|
202
|
+
<Consent state={pageProps.consentState ?? {}}>
|
|
203
|
+
<Component {...pageProps} />
|
|
204
|
+
</Consent>
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
`consentState` is the visitor's resolved state; `consentConfig` contains the
|
|
210
|
+
shared URLs. Without page prefetch, the browser loads the manifest and resolves
|
|
211
|
+
policy locally. Without supplied location, geography is unknown. For browser
|
|
212
|
+
initialization with request geography, see the
|
|
213
|
+
[optional local init route](./api-reference/data-fetching.md#do-i-need-the-local-init-route).
|
|
214
|
+
Consent submissions go to `${backendURL}/subjects` on the configured backend.
|
|
215
|
+
|
|
216
|
+
## Prefetch for a server-rendered page
|
|
217
|
+
|
|
218
|
+
Use `c15t/next/pages` with the `req` from `getServerSideProps`. The App Router
|
|
219
|
+
helper reads a different request context and must not be used here.
|
|
220
|
+
|
|
221
|
+
```tsx title="pages/index.tsx"
|
|
222
|
+
import type { GetServerSideProps } from 'next';
|
|
223
|
+
import type { ConsentRootProps } from 'c15t/next';
|
|
224
|
+
import { resolveConsent } from 'c15t/next/pages';
|
|
225
|
+
import { consentConfig } from '../c15t.config';
|
|
226
|
+
|
|
227
|
+
type PageProps = { consentState: ConsentRootProps['state'] };
|
|
228
|
+
|
|
229
|
+
export const getServerSideProps: GetServerSideProps<PageProps> = async ({ req }) => {
|
|
230
|
+
const state = await resolveConsent({ config: consentConfig, req });
|
|
231
|
+
return {
|
|
232
|
+
props: {
|
|
233
|
+
consentState: JSON.parse(
|
|
234
|
+
JSON.stringify(state)
|
|
235
|
+
) as PageProps['consentState'],
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
export default function Home() {
|
|
241
|
+
return <main>Your page</main>;
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
The JSON round-trip removes `undefined` fields, such as an absent GPC signal,
|
|
246
|
+
because Next.js rejects them in `getServerSideProps` props.
|
|
247
|
+
|
|
248
|
+
Repeat prefetch on pages that need request-specific initial HTML. Do not use
|
|
249
|
+
`getStaticProps` to resolve visitor cookies or geography: it runs without the
|
|
250
|
+
visitor's request. Keep the shared URL configuration consistent across pages.
|
|
251
|
+
|
|
252
|
+
## Verify entry and navigation
|
|
253
|
+
|
|
254
|
+
For an opt-in policy, reject and confirm neither configured vendor loads. Allow
|
|
255
|
+
measurement only: PostHog can load, while X Pixel stays blocked. Revoke
|
|
256
|
+
measurement from Privacy settings and check PostHog's capture is disabled.
|
|
257
|
+
See [script loading](./script-loader.md) for vendor-specific
|
|
258
|
+
loading and revocation behavior.
|
|
259
|
+
|
|
260
|
+
Load a server-rendered page directly, reject, and reload. Then navigate without
|
|
261
|
+
a full reload and reopen preferences. The mounted boundary should retain the
|
|
262
|
+
choice. Also test direct entry to a statically generated page; it uses browser
|
|
263
|
+
manifest resolution, so verify your unknown-location rule.
|
|
264
|
+
|
|
265
|
+
Confirm the server reads `/manifest` instead of the backend `/init` and choices
|
|
266
|
+
reach `${backendURL}/subjects`. See
|
|
267
|
+
[Optimization](./optimization.md) for caching, or compare
|
|
268
|
+
alternatives in [data fetching](./data-fetching.md). For a deployment with no Next.js server, use
|
|
269
|
+
[static export](./static-export.md) and remove local API routes.
|
|
270
|
+
|
|
271
|
+
## Use regular backend initialization instead
|
|
272
|
+
|
|
273
|
+
For a complete browser-only setup with hosted records, follow
|
|
274
|
+
[client-side initialization](./client-side.md). It needs no
|
|
275
|
+
local route handlers or server prefetch.
|
|
276
|
+
|
|
277
|
+
For the smallest hosted configuration, keep only `backendURL` in
|
|
278
|
+
`defineConsentConfig`:
|
|
279
|
+
|
|
280
|
+
```ts title="c15t.config.ts"
|
|
281
|
+
import { defineConsentConfig } from 'c15t/next';
|
|
282
|
+
|
|
283
|
+
const backendURL = process.env.NEXT_PUBLIC_C15T_BACKEND_URL;
|
|
284
|
+
if (!backendURL) throw new Error('Set NEXT_PUBLIC_C15T_BACKEND_URL');
|
|
285
|
+
|
|
286
|
+
export const consentConfig = defineConsentConfig({ backendURL });
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
This is an alternative to the manifest configuration. Remove the unused local
|
|
290
|
+
manifest route. The existing prefetch and boundary now initialize
|
|
291
|
+
through `${backendURL}/init`; consent saves still use `${backendURL}/subjects`.
|
|
292
|
+
A backend-only config does not enable manifest mode automatically.
|
|
293
|
+
|
|
294
|
+
Compare the choices in [data fetching](./data-fetching.md), or
|
|
295
|
+
configure cache settings and optional rewrites in
|
|
296
|
+
[Optimization](./optimization.md).
|
|
@@ -1,145 +1,44 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Quickstart
|
|
3
|
-
description: Add consent management to
|
|
4
|
-
|
|
5
|
-
- value: javascript
|
|
6
|
-
href: /docs/frameworks/javascript/quickstart
|
|
7
|
-
label: JavaScript
|
|
8
|
-
- value: react
|
|
9
|
-
href: /docs/frameworks/react/quickstart
|
|
10
|
-
label: React
|
|
11
|
-
- value: next
|
|
12
|
-
href: /docs/frameworks/next/quickstart
|
|
13
|
-
label: Next.js
|
|
3
|
+
description: Add c15t consent management to Next.js with Inth, with setup guides
|
|
4
|
+
for the App Router, the Pages Router and static export.
|
|
14
5
|
group: frameworks
|
|
15
6
|
---
|
|
16
|
-
## Via CLI
|
|
17
7
|
|
|
18
|
-
|
|
8
|
+
## Choose your setup
|
|
19
9
|
|
|
20
|
-
|
|
10
|
+
We recommend [Inth](https://inth.com) for policy management and consent records.
|
|
11
|
+
For Next.js server deployments, the guides use cached manifests: your server
|
|
12
|
+
reuses public policy data and resolves consent for each visitor. Static exports
|
|
13
|
+
initialize through Inth in the browser.
|
|
21
14
|
|
|
22
|
-
|
|
15
|
+
| Your deployment | Start here |
|
|
16
|
+
| ------------------------------------- | ----------------------------------- |
|
|
17
|
+
| App Router with a Next.js server | [App Router](./app-router.md) |
|
|
18
|
+
| Pages Router with a Next.js server | [Pages Router](./pages-router.md) |
|
|
19
|
+
| Either router with `output: 'export'` | [Static export](./static-export.md) |
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
Each guide includes installation, backend prerequisites, consent-gated scripts
|
|
22
|
+
and a persistent preferences link. Start with the guide for your deployment; you do not need to read
|
|
23
|
+
the fetching reference first.
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
[Self-hosting](https://c15t.com/docs/self-host/quickstart) uses the same setup with your own
|
|
26
|
+
backend. [Offline mode](./api-reference/data-fetching.md#offline-configuration)
|
|
27
|
+
resolves bundled policy and keeps choices in browser storage, with no backend
|
|
28
|
+
requests or records. Not recommended for production environments.
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
## Other setup choices
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
For a smaller hosted setup without server prefetch or local API routes, use
|
|
33
|
+
[client-side initialization](./client-side.md). Consent resolves
|
|
34
|
+
in the browser, so the initial HTML has no resolved consent prompt.
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
[Data fetching](./data-fetching.md) compares manifests and regular
|
|
37
|
+
backend initialization. [Server rendering](./server-side.md)
|
|
38
|
+
explains when to await consent or stream the page while it resolves. Same-origin
|
|
39
|
+
[rewrites](./optimization.md) are optional optimizations.
|
|
36
40
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
import {
|
|
42
|
-
ConsentManagerProvider,
|
|
43
|
-
ConsentBanner,
|
|
44
|
-
ConsentDialog,
|
|
45
|
-
} from '@c15t/nextjs';
|
|
46
|
-
|
|
47
|
-
export default function ConsentManagerClient({ children }: { children: ReactNode }) {
|
|
48
|
-
return (
|
|
49
|
-
<ConsentManagerProvider
|
|
50
|
-
options={{
|
|
51
|
-
mode: 'hosted',
|
|
52
|
-
backendURL: 'https://your-instance.c15t.dev',
|
|
53
|
-
consentCategories: ['necessary', 'measurement', 'marketing'],
|
|
54
|
-
// Shows banner during development. Remove for production.
|
|
55
|
-
overrides: { country: 'DE' },
|
|
56
|
-
}}
|
|
57
|
-
>
|
|
58
|
-
<ConsentBanner />
|
|
59
|
-
<ConsentDialog />
|
|
60
|
-
{children}
|
|
61
|
-
</ConsentManagerProvider>
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
```tsx
|
|
67
|
-
import type { ReactNode } from 'react';
|
|
68
|
-
import ConsentManagerProvider from './provider';
|
|
69
|
-
|
|
70
|
-
export function ConsentManager({ children }: { children: ReactNode }) {
|
|
71
|
-
return <ConsentManagerProvider>{children}</ConsentManagerProvider>;
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
> ℹ️ Info:
|
|
76
|
-
> Hosted mode is the recommended production setup because the backend resolves jurisdiction and policy, keeps durable consent records, and lets c15t recover from temporary network failures by re-syncing later.
|
|
77
|
-
>
|
|
78
|
-
> ⚠️ Warning:
|
|
79
|
-
> Don't have a backend yet? You can use mode: 'offline' for local-only consent storage, but it gives up backend audit history, server-side consent awareness, and automatic jurisdiction detection. Review the browser-only storage consequences before choosing it for production.
|
|
80
|
-
|
|
81
|
-
4. **Mount ConsentManager at the app root** Wrap your app tree with `ConsentManager` so all routes/components can access consent state.
|
|
82
|
-
|
|
83
|
-
```tsx
|
|
84
|
-
import { ConsentManager } from '@/components/consent-manager';
|
|
85
|
-
|
|
86
|
-
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
87
|
-
return (
|
|
88
|
-
<html lang="en">
|
|
89
|
-
<body>
|
|
90
|
-
<ConsentManager>{children}</ConsentManager>
|
|
91
|
-
</body>
|
|
92
|
-
</html>
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
5. **Verify it works** Start your development server and confirm:
|
|
98
|
-
|
|
99
|
-
1. A **consent banner** appears at the bottom of the page
|
|
100
|
-
2. Clicking **"Customize"** opens a dialog with toggles for each consent category
|
|
101
|
-
3. After accepting or rejecting, the banner dismisses and your choice persists across page reloads
|
|
102
|
-
|
|
103
|
-
> ℹ️ **Info:**
|
|
104
|
-
> Want better performance and static-route support? See Optimization for rewrites, prefetching, and network tuning. If you want server-side data prefetching, see Server-Side Data Fetching.
|
|
105
|
-
|
|
106
|
-
## Optional: Add DevTools
|
|
107
|
-
|
|
108
|
-
Install DevTools only if you want a runtime inspector while building and debugging:
|
|
109
|
-
|
|
110
|
-
<PackageCommandTabs mode="install" command="@c15t/dev-tools" />
|
|
111
|
-
|
|
112
|
-
Then add it inside your existing provider:
|
|
113
|
-
|
|
114
|
-
```tsx title="components/consent-manager/provider.tsx"
|
|
115
|
-
import { DevTools } from '@c15t/dev-tools/react';
|
|
116
|
-
|
|
117
|
-
// ...
|
|
118
|
-
|
|
119
|
-
<ConsentManagerProvider options={...}>
|
|
120
|
-
<ConsentBanner />
|
|
121
|
-
<ConsentDialog />
|
|
122
|
-
{process.env.NODE_ENV !== 'production' && <DevTools />}
|
|
123
|
-
{children}
|
|
124
|
-
</ConsentManagerProvider>
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
> ℹ️ **Info:**
|
|
128
|
-
> Want to understand what's happening under the hood? See Initialization Flow for the lifecycle and Cookie Management for script/cookie behavior and revocation handling.
|
|
129
|
-
|
|
130
|
-
## Optional: AI Agents
|
|
131
|
-
|
|
132
|
-
Install c15t agent skills to let AI agents help with styling, i18n, scripts & other configuration.
|
|
133
|
-
|
|
134
|
-
<PackageCommandTabs command="@c15t/cli skills" />
|
|
135
|
-
|
|
136
|
-
See [AI Agents](/docs/ai-agents) for bundled package docs and agent skills.
|
|
137
|
-
|
|
138
|
-
## Next steps
|
|
139
|
-
|
|
140
|
-
* [Optimization](/docs/frameworks/next/optimization)
|
|
141
|
-
* [Script Loader](/docs/frameworks/next/script-loader)
|
|
142
|
-
* [Styling](/docs/frameworks/next/styling/overview)
|
|
143
|
-
* [Consent Categories](/docs/frameworks/next/concepts/consent-categories)
|
|
144
|
-
* [Components](/docs/frameworks/next/components/consent-banner)
|
|
145
|
-
* [AI Agents](/docs/ai-agents)
|
|
41
|
+
Try the [runnable Next.js example](https://c15t.com/docs/examples) with both routers, a gated
|
|
42
|
+
YouTube video, PostHog, X Pixel and custom banner designs. The router guides use
|
|
43
|
+
the same script configuration. After setup, [verify requests and persistence](../../guides/verify-consent.md);
|
|
44
|
+
a visible banner alone does not establish that analytics wait for consent.
|