@cookieyes/nextjs 0.3.0 → 0.5.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/README.md +143 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/server.cjs +2 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.ts +80 -0
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -0
- package/package.json +16 -10
package/README.md
CHANGED
|
@@ -160,6 +160,142 @@ import { CookieBanner, CookiePreferences, CookieOptOut, RecallButton } from "@co
|
|
|
160
160
|
</>
|
|
161
161
|
```
|
|
162
162
|
|
|
163
|
+
## Region-based regulation (server-detected)
|
|
164
|
+
|
|
165
|
+
Pick the banner's regulation from the visitor's region. On the server you read the location
|
|
166
|
+
header your host adds (Cloudflare/Vercel) with `regionFromHeaders`, pass it to your client
|
|
167
|
+
component, and wrap the banner in `<CookieYesProvider>` — so the **correct banner is
|
|
168
|
+
server-rendered for each visitor**, on the first paint, with no post-hydration flicker.
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
// app/layout.tsx — a Server Component
|
|
172
|
+
import { headers } from "next/headers";
|
|
173
|
+
import { regionFromHeaders } from "@cookieyes/nextjs";
|
|
174
|
+
import { CookieYesRoot } from "./cookieyes-root"; // your "use client" module
|
|
175
|
+
|
|
176
|
+
export default async function RootLayout({ children }) {
|
|
177
|
+
const region = regionFromHeaders(await headers()); // "US-CA" | "DE" | undefined
|
|
178
|
+
return (
|
|
179
|
+
<html>
|
|
180
|
+
<body>
|
|
181
|
+
<CookieYesRoot region={region} />
|
|
182
|
+
{children}
|
|
183
|
+
</body>
|
|
184
|
+
</html>
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
// cookieyes-root.tsx — "use client"
|
|
191
|
+
"use client";
|
|
192
|
+
import { initCookieYes, CookieYesProvider, CookieBanner, CookieOptOut } from "@cookieyes/nextjs";
|
|
193
|
+
|
|
194
|
+
const map = { "US-CA": "CCPA", DE: "GDPR" } as const;
|
|
195
|
+
|
|
196
|
+
export function CookieYesRoot({ region }: { region?: string }) {
|
|
197
|
+
const regionConfig = { detect: () => region, map };
|
|
198
|
+
initCookieYes({ mode: "cookie-only", region: regionConfig });
|
|
199
|
+
return (
|
|
200
|
+
<CookieYesProvider region={regionConfig}>
|
|
201
|
+
<CookieBanner />
|
|
202
|
+
<CookieOptOut /> {/* render this too if any region maps to CCPA */}
|
|
203
|
+
</CookieYesProvider>
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
- **What it reads:** by default the well-known Vercel (`x-vercel-ip-country` + `-region`) and
|
|
209
|
+
Cloudflare (`cf-ipcountry`) headers. Pass `regionFromHeaders(h, { header: "x-your-header" })`
|
|
210
|
+
to read a custom one.
|
|
211
|
+
- `headers()` is `await`ed on Next.js 15+ and synchronous on 14 — use whichever your version needs.
|
|
212
|
+
- **First paint:** with the provider, the server resolves the region per request and renders the
|
|
213
|
+
right banner directly into the HTML — a US visitor gets CCPA, an EU visitor gets GDPR, on the
|
|
214
|
+
first byte. The provider resolves the same value on the client, so there's no hydration mismatch.
|
|
215
|
+
(Without the provider, the banner still works but is corrected after hydration rather than
|
|
216
|
+
server-rendered per request.)
|
|
217
|
+
- **GPC:** on a CCPA banner, the browser's "do not sell" signal (`navigator.globalPrivacyControl`)
|
|
218
|
+
starts the visitor **opted out** — non-required categories denied, so gated scripts/iframes never
|
|
219
|
+
load — until they choose otherwise. It's read in the browser (the server can't see it), so it
|
|
220
|
+
applies right after hydration; it never changes *which* banner shows. Set `region.honorGpc: false`
|
|
221
|
+
to ignore it.
|
|
222
|
+
|
|
223
|
+
## Returning visitors — no banner flash
|
|
224
|
+
|
|
225
|
+
By default the server doesn't know whether a visitor has already chosen, so it renders the
|
|
226
|
+
banner for everyone and the client removes it after hydration. A returning visitor **sees the
|
|
227
|
+
banner appear and then vanish**, which reads as a bug rather than as a remembered choice.
|
|
228
|
+
|
|
229
|
+
Read their decision from the request and pass it to the provider, and the banner is never in
|
|
230
|
+
their HTML at all — nothing to hide, so nothing flashes:
|
|
231
|
+
|
|
232
|
+
```tsx
|
|
233
|
+
// app/layout.tsx — a Server Component
|
|
234
|
+
import { CookieYesProvider } from "@cookieyes/nextjs";
|
|
235
|
+
import { getServerConsent } from "@cookieyes/nextjs/server";
|
|
236
|
+
import { CookieYesRoot } from "./cookieyes-root";
|
|
237
|
+
|
|
238
|
+
export default async function RootLayout({ children }) {
|
|
239
|
+
const initialConsent = await getServerConsent({ regulation: "GDPR" });
|
|
240
|
+
return (
|
|
241
|
+
<html lang="en">
|
|
242
|
+
<body>
|
|
243
|
+
<CookieYesProvider regulation="GDPR" initialConsent={initialConsent}>
|
|
244
|
+
<CookieYesRoot />
|
|
245
|
+
</CookieYesProvider>
|
|
246
|
+
{children}
|
|
247
|
+
</body>
|
|
248
|
+
</html>
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
- **Import from `@cookieyes/nextjs/server`,** not the main entry. It reads `next/headers` and is
|
|
254
|
+
server-only; the main entry is `"use client"`.
|
|
255
|
+
- **Returns `null` when the banner should show** — a first-time visitor, a cookie recording no
|
|
256
|
+
choice yet, a corrupt cookie, or one written against a different category taxonomy (which the
|
|
257
|
+
client re-requests too). Passing `null` renders exactly as before, so this is safe to add
|
|
258
|
+
everywhere.
|
|
259
|
+
- **`initialConsent` is a provider prop, never an `initCookieYes` option.** The consent runtime is
|
|
260
|
+
a module-level singleton shared across concurrent requests, so per-visitor state there would leak
|
|
261
|
+
between visitors — the same reason `region`/`regulation` go through the provider.
|
|
262
|
+
- Combine it with `region` from the section above; both are per-request and both belong on the
|
|
263
|
+
provider.
|
|
264
|
+
- `getServerConsent()` calls `cookies()`, which opts the route into **dynamic rendering**, as any
|
|
265
|
+
`cookies()` call does. On a statically rendered route there's no request to read, so the banner
|
|
266
|
+
is server-rendered for everyone and hidden on the client as before.
|
|
267
|
+
- Framework-agnostic alternative: `readServerConsent(cookieHeader, options)` from
|
|
268
|
+
`@cookieyes/core` takes the raw `Cookie` header, for Pages Router `getServerSideProps`,
|
|
269
|
+
middleware, or any other SSR setup.
|
|
270
|
+
|
|
271
|
+
## Google Consent Mode (GA4, Ads, GTM)
|
|
272
|
+
|
|
273
|
+
Google tags need a Consent Mode **deny-by-default** set before any tag runs and
|
|
274
|
+
before the SDK boots — so a returning visitor's saved choice applies from first
|
|
275
|
+
paint. Render `<GoogleConsentMode />` high in your root layout:
|
|
276
|
+
|
|
277
|
+
```tsx
|
|
278
|
+
// app/layout.tsx
|
|
279
|
+
import { CookieYesProvider } from "@cookieyes/nextjs";
|
|
280
|
+
import { GoogleConsentMode } from "@cookieyes/nextjs/server";
|
|
281
|
+
|
|
282
|
+
export default function RootLayout({ children }) {
|
|
283
|
+
return (
|
|
284
|
+
<html lang="en">
|
|
285
|
+
<body>
|
|
286
|
+
<GoogleConsentMode />
|
|
287
|
+
<CookieYesProvider regulation="GDPR">{children}</CookieYesProvider>
|
|
288
|
+
</body>
|
|
289
|
+
</html>
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Then load the tags on the client with a preset from
|
|
295
|
+
[`@cookieyes/scripts`](https://github.com/cookieyes/cookieyes/tree/main/sdk/scripts)
|
|
296
|
+
— `ga4()`, `googleAds()`, or `googleTagManager()`. The SDK broadcasts each
|
|
297
|
+
consent change to Google as a Consent Mode `update`; you don't wire that up.
|
|
298
|
+
|
|
163
299
|
## API
|
|
164
300
|
|
|
165
301
|
This package re-exports the entire `@cookieyes/react` surface — the setup function
|
|
@@ -167,6 +303,13 @@ This package re-exports the entire `@cookieyes/react` surface — the setup func
|
|
|
167
303
|
`RecallButton`, `GatedScript`, `GatedFrame`), headless primitives (`Banner`, `Preferences`,
|
|
168
304
|
`OptOut`), and all hooks (`useConsent`, `useConsentActions`, …).
|
|
169
305
|
|
|
306
|
+
It also adds **server-only** exports on their own subpath, kept out of the `"use client"` barrel:
|
|
307
|
+
|
|
308
|
+
| Import | Export | Purpose |
|
|
309
|
+
|---|---|---|
|
|
310
|
+
| `@cookieyes/nextjs/server` | `getServerConsent(options?)` | Reads the request's cookies and returns a returning visitor's stored decision (or `null`), for `<CookieYesProvider initialConsent>` |
|
|
311
|
+
| `@cookieyes/nextjs/server` | `<GoogleConsentMode />` | Renders the Google Consent Mode deny-by-default into the page `<head>` (see below) |
|
|
312
|
+
|
|
170
313
|
- Full option reference: **[Configuration](https://github.com/cookieyes/cookieyes/blob/main/docs/configuration.md)**.
|
|
171
314
|
- Component/hook reference: the **[`@cookieyes/react` README](https://github.com/cookieyes/cookieyes/tree/main/sdk/react#readme)**.
|
|
172
315
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
"use strict";var e=require("@cookieyes/react");Object.defineProperty(exports,"Banner",{enumerable:!0,get:function(){return e.Banner}}),Object.defineProperty(exports,"CookieBanner",{enumerable:!0,get:function(){return e.CookieBanner}}),Object.defineProperty(exports,"CookieOptOut",{enumerable:!0,get:function(){return e.CookieOptOut}}),Object.defineProperty(exports,"CookiePreferences",{enumerable:!0,get:function(){return e.CookiePreferences}}),Object.defineProperty(exports,"DEFAULT_CATEGORIES",{enumerable:!0,get:function(){return e.DEFAULT_CATEGORIES}}),Object.defineProperty(exports,"GatedFrame",{enumerable:!0,get:function(){return e.GatedFrame}}),Object.defineProperty(exports,"GatedScript",{enumerable:!0,get:function(){return e.GatedScript}}),Object.defineProperty(exports,"OptOut",{enumerable:!0,get:function(){return e.OptOut}}),Object.defineProperty(exports,"Preferences",{enumerable:!0,get:function(){return e.Preferences}}),Object.defineProperty(exports,"RecallButton",{enumerable:!0,get:function(){return e.RecallButton}}),Object.defineProperty(exports,"ReloadNotice",{enumerable:!0,get:function(){return e.ReloadNotice}}),Object.defineProperty(exports,"createCookieYes",{enumerable:!0,get:function(){return e.createCookieYes}}),Object.defineProperty(exports,"defaultTranslations",{enumerable:!0,get:function(){return e.defaultTranslations}}),Object.defineProperty(exports,"getCookieYes",{enumerable:!0,get:function(){return e.getCookieYes}}),Object.defineProperty(exports,"getOrCreateConsentRuntime",{enumerable:!0,get:function(){return e.getOrCreateConsentRuntime}}),Object.defineProperty(exports,"initCookieYes",{enumerable:!0,get:function(){return e.initCookieYes}}),Object.defineProperty(exports,"registerStopHandler",{enumerable:!0,get:function(){return e.registerStopHandler}}),Object.defineProperty(exports,"resetConsentRuntime",{enumerable:!0,get:function(){return e.resetConsentRuntime}}),Object.defineProperty(exports,"resetCookieYes",{enumerable:!0,get:function(){return e.resetCookieYes}}),Object.defineProperty(exports,"resolveBuiltInIntegration",{enumerable:!0,get:function(){return e.resolveBuiltInIntegration}}),Object.defineProperty(exports,"resolveCategories",{enumerable:!0,get:function(){return e.resolveCategories}}),Object.defineProperty(exports,"resolveTranslations",{enumerable:!0,get:function(){return e.resolveTranslations}}),Object.defineProperty(exports,"useBannerVisibility",{enumerable:!0,get:function(){return e.useBannerVisibility}}),Object.defineProperty(exports,"useCategories",{enumerable:!0,get:function(){return e.useCategories}}),Object.defineProperty(exports,"useConsent",{enumerable:!0,get:function(){return e.useConsent}}),Object.defineProperty(exports,"useConsentActions",{enumerable:!0,get:function(){return e.useConsentActions}}),Object.defineProperty(exports,"useConsentCategory",{enumerable:!0,get:function(){return e.useConsentCategory}}),Object.defineProperty(exports,"useConsentRuntime",{enumerable:!0,get:function(){return e.useConsentRuntime}}),Object.defineProperty(exports,"useOptOutOpen",{enumerable:!0,get:function(){return e.useOptOutOpen}}),Object.defineProperty(exports,"usePreferencesOpen",{enumerable:!0,get:function(){return e.usePreferencesOpen}}),Object.defineProperty(exports,"useRegulation",{enumerable:!0,get:function(){return e.useRegulation}}),Object.defineProperty(exports,"useReloadNotice",{enumerable:!0,get:function(){return e.useReloadNotice}}),Object.defineProperty(exports,"useTranslations",{enumerable:!0,get:function(){return e.useTranslations}});
|
|
2
|
+
"use strict";var e=require("@cookieyes/react");Object.defineProperty(exports,"Banner",{enumerable:!0,get:function(){return e.Banner}}),Object.defineProperty(exports,"CY_PART",{enumerable:!0,get:function(){return e.CY_PART}}),Object.defineProperty(exports,"CY_STATE",{enumerable:!0,get:function(){return e.CY_STATE}}),Object.defineProperty(exports,"CookieBanner",{enumerable:!0,get:function(){return e.CookieBanner}}),Object.defineProperty(exports,"CookieOptOut",{enumerable:!0,get:function(){return e.CookieOptOut}}),Object.defineProperty(exports,"CookiePreferences",{enumerable:!0,get:function(){return e.CookiePreferences}}),Object.defineProperty(exports,"CookieYesProvider",{enumerable:!0,get:function(){return e.CookieYesProvider}}),Object.defineProperty(exports,"DEFAULT_CATEGORIES",{enumerable:!0,get:function(){return e.DEFAULT_CATEGORIES}}),Object.defineProperty(exports,"GatedFrame",{enumerable:!0,get:function(){return e.GatedFrame}}),Object.defineProperty(exports,"GatedScript",{enumerable:!0,get:function(){return e.GatedScript}}),Object.defineProperty(exports,"OptOut",{enumerable:!0,get:function(){return e.OptOut}}),Object.defineProperty(exports,"Preferences",{enumerable:!0,get:function(){return e.Preferences}}),Object.defineProperty(exports,"RecallButton",{enumerable:!0,get:function(){return e.RecallButton}}),Object.defineProperty(exports,"ReloadNotice",{enumerable:!0,get:function(){return e.ReloadNotice}}),Object.defineProperty(exports,"createCookieYes",{enumerable:!0,get:function(){return e.createCookieYes}}),Object.defineProperty(exports,"defaultTranslations",{enumerable:!0,get:function(){return e.defaultTranslations}}),Object.defineProperty(exports,"getCookieYes",{enumerable:!0,get:function(){return e.getCookieYes}}),Object.defineProperty(exports,"getOrCreateConsentRuntime",{enumerable:!0,get:function(){return e.getOrCreateConsentRuntime}}),Object.defineProperty(exports,"getTextDirection",{enumerable:!0,get:function(){return e.getTextDirection}}),Object.defineProperty(exports,"initCookieYes",{enumerable:!0,get:function(){return e.initCookieYes}}),Object.defineProperty(exports,"mergeTranslations",{enumerable:!0,get:function(){return e.mergeTranslations}}),Object.defineProperty(exports,"readGpc",{enumerable:!0,get:function(){return e.readGpc}}),Object.defineProperty(exports,"readServerConsent",{enumerable:!0,get:function(){return e.readServerConsent}}),Object.defineProperty(exports,"regionFromHeaders",{enumerable:!0,get:function(){return e.regionFromHeaders}}),Object.defineProperty(exports,"registerStopHandler",{enumerable:!0,get:function(){return e.registerStopHandler}}),Object.defineProperty(exports,"resetConsentRuntime",{enumerable:!0,get:function(){return e.resetConsentRuntime}}),Object.defineProperty(exports,"resetCookieYes",{enumerable:!0,get:function(){return e.resetCookieYes}}),Object.defineProperty(exports,"resolveBuiltInIntegration",{enumerable:!0,get:function(){return e.resolveBuiltInIntegration}}),Object.defineProperty(exports,"resolveCategories",{enumerable:!0,get:function(){return e.resolveCategories}}),Object.defineProperty(exports,"resolveRegion",{enumerable:!0,get:function(){return e.resolveRegion}}),Object.defineProperty(exports,"resolveTranslations",{enumerable:!0,get:function(){return e.resolveTranslations}}),Object.defineProperty(exports,"useBannerVisibility",{enumerable:!0,get:function(){return e.useBannerVisibility}}),Object.defineProperty(exports,"useCategories",{enumerable:!0,get:function(){return e.useCategories}}),Object.defineProperty(exports,"useConsent",{enumerable:!0,get:function(){return e.useConsent}}),Object.defineProperty(exports,"useConsentActions",{enumerable:!0,get:function(){return e.useConsentActions}}),Object.defineProperty(exports,"useConsentCategory",{enumerable:!0,get:function(){return e.useConsentCategory}}),Object.defineProperty(exports,"useConsentRuntime",{enumerable:!0,get:function(){return e.useConsentRuntime}}),Object.defineProperty(exports,"useLanguage",{enumerable:!0,get:function(){return e.useLanguage}}),Object.defineProperty(exports,"useOnConsentChange",{enumerable:!0,get:function(){return e.useOnConsentChange}}),Object.defineProperty(exports,"useOptOutOpen",{enumerable:!0,get:function(){return e.useOptOutOpen}}),Object.defineProperty(exports,"usePreferencesOpen",{enumerable:!0,get:function(){return e.usePreferencesOpen}}),Object.defineProperty(exports,"useRegion",{enumerable:!0,get:function(){return e.useRegion}}),Object.defineProperty(exports,"useRegulation",{enumerable:!0,get:function(){return e.useRegulation}}),Object.defineProperty(exports,"useReloadNotice",{enumerable:!0,get:function(){return e.useReloadNotice}}),Object.defineProperty(exports,"useTranslations",{enumerable:!0,get:function(){return e.useTranslations}});
|
|
3
3
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { ActiveUI, AnyStopHandler, Banner, Builder, BuiltInIntegration, CategoryDef, ColorScheme, ColorSchemePref, ConsentActions, ConsentBackend, ConsentCategory, ConsentChangePayload, ConsentConfig, ConsentManager, ConsentPayload, ConsentRuntime, ConsentRuntimeMode, ConsentRuntimeOptions, ConsentSnapshot, ConsentStore, ConsentStoreState, CookieBanner, CookieOptOut, CookiePreferences, CookieYesConfig, CookieYesOfflineConfig, CookieYesRuntime, CookieYesSelfHostedConfig, CookieYesSnapshot, DEFAULT_CATEGORIES, GatedFrame, GatedScript, GoogleConsentSignal, I18nConfig, OptOut, Preferences, RecallButton, Regulation, ReloadNotice, ReloadNoticeState, ReloadOnlyHandler, ResolvedCategories, RuntimeMode, ScriptEntry, StopHandler, ThemeConfig, TranslationMap, UseReloadNoticeResult, createCookieYes, defaultTranslations, getCookieYes, getOrCreateConsentRuntime, initCookieYes, registerStopHandler, resetConsentRuntime, resetCookieYes, resolveBuiltInIntegration, resolveCategories, resolveTranslations, useBannerVisibility, useCategories, useConsent, useConsentActions, useConsentCategory, useConsentRuntime, useOptOutOpen, usePreferencesOpen, useRegulation, useReloadNotice, useTranslations } from '@cookieyes/react';
|
|
1
|
+
export { ActiveUI, AnyStopHandler, Banner, Builder, BuiltInIntegration, CY_PART, CY_STATE, CategoryDef, CategoryText, ColorScheme, ColorSchemePref, ConsentActions, ConsentBackend, ConsentCategory, ConsentChangePayload, ConsentConfig, ConsentEventListener, ConsentEventOptions, ConsentEventPayload, ConsentEventType, ConsentManager, ConsentPayload, ConsentRuntime, ConsentRuntimeMode, ConsentRuntimeOptions, ConsentSnapshot, ConsentStore, ConsentStoreState, CookieBanner, CookieBannerProps, CookieOptOut, CookieOptOutProps, CookiePreferences, CookiePreferencesProps, CookieYesConfig, CookieYesOfflineConfig, CookieYesProvider, CookieYesProviderProps, CookieYesRuntime, CookieYesSelfHostedConfig, CookieYesSnapshot, CyPart, CyState, DEFAULT_CATEGORIES, GatedFrame, GatedScript, GoogleConsentSignal, HeaderSource, I18nConfig, LanguageInfo, OptOut, PartialTranslations, Preferences, RecallButton, RegionConfig, RegionDecision, RegionDetector, RegionSource, Regulation, ReloadNotice, ReloadNoticeState, ReloadOnlyHandler, ResolvedCategories, RuntimeMode, ScriptEntry, ServerConsentOptions, StopHandler, TextDirection, ThemeConfig, TranslationMap, UseLanguageResult, UseReloadNoticeResult, createCookieYes, defaultTranslations, getCookieYes, getOrCreateConsentRuntime, getTextDirection, initCookieYes, mergeTranslations, readGpc, readServerConsent, regionFromHeaders, registerStopHandler, resetConsentRuntime, resetCookieYes, resolveBuiltInIntegration, resolveCategories, resolveRegion, resolveTranslations, useBannerVisibility, useCategories, useConsent, useConsentActions, useConsentCategory, useConsentRuntime, useLanguage, useOnConsentChange, useOptOutOpen, usePreferencesOpen, useRegion, useRegulation, useReloadNotice, useTranslations } from '@cookieyes/react';
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
export{Banner,CookieBanner,CookieOptOut,CookiePreferences,DEFAULT_CATEGORIES,GatedFrame,GatedScript,OptOut,Preferences,RecallButton,ReloadNotice,createCookieYes,defaultTranslations,getCookieYes,getOrCreateConsentRuntime,initCookieYes,registerStopHandler,resetConsentRuntime,resetCookieYes,resolveBuiltInIntegration,resolveCategories,resolveTranslations,useBannerVisibility,useCategories,useConsent,useConsentActions,useConsentCategory,useConsentRuntime,useOptOutOpen,usePreferencesOpen,useRegulation,useReloadNotice,useTranslations}from"@cookieyes/react";
|
|
2
|
+
export{Banner,CY_PART,CY_STATE,CookieBanner,CookieOptOut,CookiePreferences,CookieYesProvider,DEFAULT_CATEGORIES,GatedFrame,GatedScript,OptOut,Preferences,RecallButton,ReloadNotice,createCookieYes,defaultTranslations,getCookieYes,getOrCreateConsentRuntime,getTextDirection,initCookieYes,mergeTranslations,readGpc,readServerConsent,regionFromHeaders,registerStopHandler,resetConsentRuntime,resetCookieYes,resolveBuiltInIntegration,resolveCategories,resolveRegion,resolveTranslations,useBannerVisibility,useCategories,useConsent,useConsentActions,useConsentCategory,useConsentRuntime,useLanguage,useOnConsentChange,useOptOutOpen,usePreferencesOpen,useRegion,useRegulation,useReloadNotice,useTranslations}from"@cookieyes/react";
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/server.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var e=require("@cookieyes/core"),r=require("react/jsx-runtime"),t=require("@cookieyes/scripts");exports.GoogleConsentMode=function(e={}){return r.jsx("script",{dangerouslySetInnerHTML:{__html:t.googleConsentModeSnippet(e)}})},exports.getServerConsent=async function(r={}){const{cookies:t}=await import("next/headers"),o=(await t()).getAll().map(e=>`${e.name}=${e.value}`).join("; ");return e.readServerConsent(o,r)};
|
|
2
|
+
//# sourceMappingURL=server.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.cjs","sources":["../src/google-consent-mode.tsx","../src/server.ts"],"sourcesContent":["import { type ConsentModeOptions, googleConsentModeSnippet } from \"@cookieyes/scripts\";\n\n/**\n * Renders the Google Consent Mode **deny-by-default** as an inline `<script>`,\n * to be placed high in your root layout — before any Google tag and before the\n * SDK boots. This is what lets a returning visitor's saved choice (which the SDK\n * broadcasts as a Consent Mode `update`) land on top of a clean default, instead\n * of the visitor being stuck denied until they act again.\n *\n * The `<script>` is inline and synchronous, so it runs in document order before\n * the client bundle (and before `gtag.js`, which the `ga4()`/`googleAds()`\n * loaders inject). Pass it the same {@link ConsentModeOptions} as the loaders if\n * you need to change the defaults.\n *\n * ```tsx\n * // app/layout.tsx\n * import { GoogleConsentMode } from \"@cookieyes/nextjs/server\";\n *\n * export default function RootLayout({ children }) {\n * return (\n * <html lang=\"en\">\n * <body>\n * <GoogleConsentMode />\n * {children}\n * </body>\n * </html>\n * );\n * }\n * ```\n *\n * Then load the tags on the client with a preset from `@cookieyes/scripts`:\n * `initCookieYes({ integrations: [ga4({ measurementId: \"G-XXXX\" })] })`.\n */\nexport function GoogleConsentMode(props: ConsentModeOptions = {}) {\n return (\n <script\n // biome-ignore lint/security/noDangerouslySetInnerHtml: an inline Consent Mode default is the standard, documented Google pattern.\n dangerouslySetInnerHTML={{ __html: googleConsentModeSnippet(props) }}\n />\n );\n}\n","import {\n type ConsentSnapshot,\n readServerConsent,\n type ServerConsentOptions,\n} from \"@cookieyes/core\";\n\nexport { GoogleConsentMode } from \"./google-consent-mode.js\";\n\n/**\n * Read a returning visitor's stored consent from the incoming request, in a\n * Server Component, Route Handler or middleware.\n *\n * Pass the result to `<CookieYesProvider initialConsent={…}>` and the banner is\n * never sent to a visitor who has already chosen — instead of being sent to\n * everyone and removed on the client, which the visitor sees as the banner\n * appearing and then vanishing.\n *\n * ```tsx\n * // app/layout.tsx\n * import { CookieYesProvider } from \"@cookieyes/nextjs\";\n * import { getServerConsent } from \"@cookieyes/nextjs/server\";\n *\n * export default async function RootLayout({ children }) {\n * const initialConsent = await getServerConsent({ regulation: \"GDPR\" });\n * return (\n * <html lang=\"en\">\n * <body>\n * <CookieYesProvider regulation=\"GDPR\" initialConsent={initialConsent}>\n * {children}\n * </CookieYesProvider>\n * </body>\n * </html>\n * );\n * }\n * ```\n *\n * Returns `null` when there is no decision on record — a first-time visitor, a\n * cookie recording no choice yet, or one written against a different category\n * taxonomy — in which case the banner renders as usual.\n *\n * This module is server-only: it imports `next/headers`, so keep it out of client\n * components. It lives in `@cookieyes/nextjs/server` rather than the main entry\n * for exactly that reason — the main entry is `\"use client\"`.\n *\n * Reading cookies opts the route into dynamic rendering, as any `cookies()` call\n * does. A statically rendered route has no request to read, so there the banner\n * is server-rendered for everyone and hidden on the client as before.\n */\nexport async function getServerConsent(\n options: ServerConsentOptions = {},\n): Promise<ConsentSnapshot | null> {\n // Imported lazily so merely importing this module doesn't pull `next/headers`\n // into a build that never calls it.\n const { cookies } = await import(\"next/headers\");\n const store = await cookies();\n const header = store\n .getAll()\n .map((c) => `${c.name}=${c.value}`)\n .join(\"; \");\n return readServerConsent(header, options);\n}\n"],"names":["props","jsx","dangerouslySetInnerHTML","__html","googleConsentModeSnippet","async","options","cookies","import","header","getAll","map","c","name","value","join","readServerConsent"],"mappings":"uIAiCO,SAA2BA,EAA4B,IAC5D,OACEC,EAAAA,IAAC,SAAA,CAECC,wBAAyB,CAAEC,OAAQC,EAAAA,yBAAyBJ,KAGlE,2BCQAK,eACEC,EAAgC,IAIhC,MAAMC,QAAEA,SAAkBC,OAAO,gBAE3BC,SADcF,KAEjBG,SACAC,IAAKC,GAAM,GAAGA,EAAEC,QAAQD,EAAEE,SAC1BC,KAAK,MACR,OAAOC,EAAAA,kBAAkBP,EAAQH,EACnC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { ServerConsentOptions, ConsentSnapshot } from '@cookieyes/core';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { ConsentModeOptions } from '@cookieyes/scripts';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Renders the Google Consent Mode **deny-by-default** as an inline `<script>`,
|
|
7
|
+
* to be placed high in your root layout — before any Google tag and before the
|
|
8
|
+
* SDK boots. This is what lets a returning visitor's saved choice (which the SDK
|
|
9
|
+
* broadcasts as a Consent Mode `update`) land on top of a clean default, instead
|
|
10
|
+
* of the visitor being stuck denied until they act again.
|
|
11
|
+
*
|
|
12
|
+
* The `<script>` is inline and synchronous, so it runs in document order before
|
|
13
|
+
* the client bundle (and before `gtag.js`, which the `ga4()`/`googleAds()`
|
|
14
|
+
* loaders inject). Pass it the same {@link ConsentModeOptions} as the loaders if
|
|
15
|
+
* you need to change the defaults.
|
|
16
|
+
*
|
|
17
|
+
* ```tsx
|
|
18
|
+
* // app/layout.tsx
|
|
19
|
+
* import { GoogleConsentMode } from "@cookieyes/nextjs/server";
|
|
20
|
+
*
|
|
21
|
+
* export default function RootLayout({ children }) {
|
|
22
|
+
* return (
|
|
23
|
+
* <html lang="en">
|
|
24
|
+
* <body>
|
|
25
|
+
* <GoogleConsentMode />
|
|
26
|
+
* {children}
|
|
27
|
+
* </body>
|
|
28
|
+
* </html>
|
|
29
|
+
* );
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* Then load the tags on the client with a preset from `@cookieyes/scripts`:
|
|
34
|
+
* `initCookieYes({ integrations: [ga4({ measurementId: "G-XXXX" })] })`.
|
|
35
|
+
*/
|
|
36
|
+
declare function GoogleConsentMode(props?: ConsentModeOptions): react.JSX.Element;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Read a returning visitor's stored consent from the incoming request, in a
|
|
40
|
+
* Server Component, Route Handler or middleware.
|
|
41
|
+
*
|
|
42
|
+
* Pass the result to `<CookieYesProvider initialConsent={…}>` and the banner is
|
|
43
|
+
* never sent to a visitor who has already chosen — instead of being sent to
|
|
44
|
+
* everyone and removed on the client, which the visitor sees as the banner
|
|
45
|
+
* appearing and then vanishing.
|
|
46
|
+
*
|
|
47
|
+
* ```tsx
|
|
48
|
+
* // app/layout.tsx
|
|
49
|
+
* import { CookieYesProvider } from "@cookieyes/nextjs";
|
|
50
|
+
* import { getServerConsent } from "@cookieyes/nextjs/server";
|
|
51
|
+
*
|
|
52
|
+
* export default async function RootLayout({ children }) {
|
|
53
|
+
* const initialConsent = await getServerConsent({ regulation: "GDPR" });
|
|
54
|
+
* return (
|
|
55
|
+
* <html lang="en">
|
|
56
|
+
* <body>
|
|
57
|
+
* <CookieYesProvider regulation="GDPR" initialConsent={initialConsent}>
|
|
58
|
+
* {children}
|
|
59
|
+
* </CookieYesProvider>
|
|
60
|
+
* </body>
|
|
61
|
+
* </html>
|
|
62
|
+
* );
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* Returns `null` when there is no decision on record — a first-time visitor, a
|
|
67
|
+
* cookie recording no choice yet, or one written against a different category
|
|
68
|
+
* taxonomy — in which case the banner renders as usual.
|
|
69
|
+
*
|
|
70
|
+
* This module is server-only: it imports `next/headers`, so keep it out of client
|
|
71
|
+
* components. It lives in `@cookieyes/nextjs/server` rather than the main entry
|
|
72
|
+
* for exactly that reason — the main entry is `"use client"`.
|
|
73
|
+
*
|
|
74
|
+
* Reading cookies opts the route into dynamic rendering, as any `cookies()` call
|
|
75
|
+
* does. A statically rendered route has no request to read, so there the banner
|
|
76
|
+
* is server-rendered for everyone and hidden on the client as before.
|
|
77
|
+
*/
|
|
78
|
+
declare function getServerConsent(options?: ServerConsentOptions): Promise<ConsentSnapshot | null>;
|
|
79
|
+
|
|
80
|
+
export { GoogleConsentMode, getServerConsent };
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{readServerConsent as e}from"@cookieyes/core";import{jsx as o}from"react/jsx-runtime";import{googleConsentModeSnippet as r}from"@cookieyes/scripts";function t(e={}){return o("script",{dangerouslySetInnerHTML:{__html:r(e)}})}async function i(o={}){const{cookies:r}=await import("next/headers"),t=(await r()).getAll().map(e=>`${e.name}=${e.value}`).join("; ");return e(t,o)}export{t as GoogleConsentMode,i as getServerConsent};
|
|
2
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sources":["../src/google-consent-mode.tsx","../src/server.ts"],"sourcesContent":["import { type ConsentModeOptions, googleConsentModeSnippet } from \"@cookieyes/scripts\";\n\n/**\n * Renders the Google Consent Mode **deny-by-default** as an inline `<script>`,\n * to be placed high in your root layout — before any Google tag and before the\n * SDK boots. This is what lets a returning visitor's saved choice (which the SDK\n * broadcasts as a Consent Mode `update`) land on top of a clean default, instead\n * of the visitor being stuck denied until they act again.\n *\n * The `<script>` is inline and synchronous, so it runs in document order before\n * the client bundle (and before `gtag.js`, which the `ga4()`/`googleAds()`\n * loaders inject). Pass it the same {@link ConsentModeOptions} as the loaders if\n * you need to change the defaults.\n *\n * ```tsx\n * // app/layout.tsx\n * import { GoogleConsentMode } from \"@cookieyes/nextjs/server\";\n *\n * export default function RootLayout({ children }) {\n * return (\n * <html lang=\"en\">\n * <body>\n * <GoogleConsentMode />\n * {children}\n * </body>\n * </html>\n * );\n * }\n * ```\n *\n * Then load the tags on the client with a preset from `@cookieyes/scripts`:\n * `initCookieYes({ integrations: [ga4({ measurementId: \"G-XXXX\" })] })`.\n */\nexport function GoogleConsentMode(props: ConsentModeOptions = {}) {\n return (\n <script\n // biome-ignore lint/security/noDangerouslySetInnerHtml: an inline Consent Mode default is the standard, documented Google pattern.\n dangerouslySetInnerHTML={{ __html: googleConsentModeSnippet(props) }}\n />\n );\n}\n","import {\n type ConsentSnapshot,\n readServerConsent,\n type ServerConsentOptions,\n} from \"@cookieyes/core\";\n\nexport { GoogleConsentMode } from \"./google-consent-mode.js\";\n\n/**\n * Read a returning visitor's stored consent from the incoming request, in a\n * Server Component, Route Handler or middleware.\n *\n * Pass the result to `<CookieYesProvider initialConsent={…}>` and the banner is\n * never sent to a visitor who has already chosen — instead of being sent to\n * everyone and removed on the client, which the visitor sees as the banner\n * appearing and then vanishing.\n *\n * ```tsx\n * // app/layout.tsx\n * import { CookieYesProvider } from \"@cookieyes/nextjs\";\n * import { getServerConsent } from \"@cookieyes/nextjs/server\";\n *\n * export default async function RootLayout({ children }) {\n * const initialConsent = await getServerConsent({ regulation: \"GDPR\" });\n * return (\n * <html lang=\"en\">\n * <body>\n * <CookieYesProvider regulation=\"GDPR\" initialConsent={initialConsent}>\n * {children}\n * </CookieYesProvider>\n * </body>\n * </html>\n * );\n * }\n * ```\n *\n * Returns `null` when there is no decision on record — a first-time visitor, a\n * cookie recording no choice yet, or one written against a different category\n * taxonomy — in which case the banner renders as usual.\n *\n * This module is server-only: it imports `next/headers`, so keep it out of client\n * components. It lives in `@cookieyes/nextjs/server` rather than the main entry\n * for exactly that reason — the main entry is `\"use client\"`.\n *\n * Reading cookies opts the route into dynamic rendering, as any `cookies()` call\n * does. A statically rendered route has no request to read, so there the banner\n * is server-rendered for everyone and hidden on the client as before.\n */\nexport async function getServerConsent(\n options: ServerConsentOptions = {},\n): Promise<ConsentSnapshot | null> {\n // Imported lazily so merely importing this module doesn't pull `next/headers`\n // into a build that never calls it.\n const { cookies } = await import(\"next/headers\");\n const store = await cookies();\n const header = store\n .getAll()\n .map((c) => `${c.name}=${c.value}`)\n .join(\"; \");\n return readServerConsent(header, options);\n}\n"],"names":["GoogleConsentMode","props","jsx","dangerouslySetInnerHTML","__html","googleConsentModeSnippet","async","getServerConsent","options","cookies","import","header","getAll","map","c","name","value","join","readServerConsent"],"mappings":"0JAiCO,SAASA,EAAkBC,EAA4B,IAC5D,OACEC,EAAC,SAAA,CAECC,wBAAyB,CAAEC,OAAQC,EAAyBJ,KAGlE,CCQAK,eAAsBC,EACpBC,EAAgC,IAIhC,MAAMC,QAAEA,SAAkBC,OAAO,gBAE3BC,SADcF,KAEjBG,SACAC,IAAKC,GAAM,GAAGA,EAAEC,QAAQD,EAAEE,SAC1BC,KAAK,MACR,OAAOC,EAAkBP,EAAQH,EACnC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cookieyes/nextjs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Next.js App Router adapter for the CookieYes consent SDK",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cookie consent",
|
|
@@ -33,6 +33,11 @@
|
|
|
33
33
|
"types": "./dist/index.d.ts",
|
|
34
34
|
"import": "./dist/index.js",
|
|
35
35
|
"require": "./dist/index.cjs"
|
|
36
|
+
},
|
|
37
|
+
"./server": {
|
|
38
|
+
"types": "./dist/server.d.ts",
|
|
39
|
+
"import": "./dist/server.js",
|
|
40
|
+
"require": "./dist/server.cjs"
|
|
36
41
|
}
|
|
37
42
|
},
|
|
38
43
|
"main": "./dist/index.cjs",
|
|
@@ -56,19 +61,20 @@
|
|
|
56
61
|
"react-dom": ">=18.0.0"
|
|
57
62
|
},
|
|
58
63
|
"dependencies": {
|
|
59
|
-
"@cookieyes/core": "0.
|
|
60
|
-
"@cookieyes/react": "0.
|
|
64
|
+
"@cookieyes/core": "0.4.0",
|
|
65
|
+
"@cookieyes/react": "0.5.0",
|
|
66
|
+
"@cookieyes/scripts": "0.1.0"
|
|
61
67
|
},
|
|
62
68
|
"devDependencies": {
|
|
63
|
-
"@types/node": "^
|
|
64
|
-
"@types/react": "^19.2.
|
|
69
|
+
"@types/node": "^26.1.1",
|
|
70
|
+
"@types/react": "^19.2.17",
|
|
65
71
|
"@types/react-dom": "^19.2.3",
|
|
66
|
-
"@vitest/coverage-v8": "^4.1.
|
|
67
|
-
"next": "^16.2.
|
|
68
|
-
"react": "^19.2.
|
|
69
|
-
"react-dom": "^19.2.
|
|
72
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
73
|
+
"next": "^16.2.11",
|
|
74
|
+
"react": "^19.2.7",
|
|
75
|
+
"react-dom": "^19.2.7",
|
|
70
76
|
"typescript": "^6.0.3",
|
|
71
|
-
"vitest": "^4.1.
|
|
77
|
+
"vitest": "^4.1.10"
|
|
72
78
|
},
|
|
73
79
|
"scripts": {
|
|
74
80
|
"build": "rm -rf dist && rollup -c",
|