Try the Flags SDK
diff --git a/apps/docs/app/[lang]/home/[code]/purchase-button.tsx b/apps/docs/app/[lang]/home/[code]/purchase-button.tsx
new file mode 100644
index 000000000..2beed3827
--- /dev/null
+++ b/apps/docs/app/[lang]/home/[code]/purchase-button.tsx
@@ -0,0 +1,39 @@
+'use client';
+import { identify, track } from '@vercel/analytics';
+import { Button } from '@vercel/geistdocs/components/button';
+import { useToasts } from '@vercel/geistdocs/components/toasts';
+import { useEffect } from 'react';
+import { USER_ID_COOKIE } from '@/lib/flags/constants';
+
+function readUserId(): string | undefined {
+ const match = document.cookie
+ .split('; ')
+ .find((cookie) => cookie.startsWith(`${USER_ID_COOKIE}=`));
+ return match?.slice(USER_ID_COOKIE.length + 1);
+}
+
+export function PurchaseButton({ label }: { label: string }) {
+ const { success } = useToasts();
+
+ // Exposures are reported with `unitKey: 'user'`, so the browser SDK has to
+ // know the same user id for the purchase event to join to them.
+ useEffect(() => {
+ const userId = readUserId();
+ if (userId) {
+ identify(userId);
+ }
+ }, []);
+
+ return (
+
+ );
+}
diff --git a/apps/docs/components/geistdocs/provider.tsx b/apps/docs/components/geistdocs/provider.tsx
index c33a8705c..7f1189389 100644
--- a/apps/docs/components/geistdocs/provider.tsx
+++ b/apps/docs/components/geistdocs/provider.tsx
@@ -15,6 +15,19 @@ type GeistdocsProviderProps = Omit<
lang?: string;
};
+// Set NEXT_PUBLIC_WEB_ANALYTICS_MODE=production in .env.local to send events
+// from `next dev` to the production project. The script and endpoint are only
+// served from a Vercel deployment, so they have to point at the production
+// domain when running locally.
+const analyticsMode =
+ process.env.NEXT_PUBLIC_WEB_ANALYTICS_MODE === "production"
+ ? "production"
+ : undefined;
+const analyticsOrigin =
+ analyticsMode && process.env.NODE_ENV === "development"
+ ? `https://${process.env.NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL}`
+ : undefined;
+
export const GeistdocsProvider = ({
basePath: _basePath,
className: _className,
@@ -24,7 +37,17 @@ export const GeistdocsProvider = ({
return (
<>
-
+
>
);
diff --git a/apps/docs/flags.ts b/apps/docs/flags.ts
index 13b099b9f..1cef3f822 100644
--- a/apps/docs/flags.ts
+++ b/apps/docs/flags.ts
@@ -1,4 +1,15 @@
import { flag } from 'flags/next';
+import { type Entities, identify } from './lib/flags/identify';
+import { vercelAdapter } from './lib/flags/vercel-adapter';
+
+export const checkoutFlag = flag
({
+ key: 'checkout-flag-vincent',
+ description: 'Experiment-owned flag',
+ defaultValue: false,
+ options: [false, true],
+ identify,
+ adapter: vercelAdapter,
+});
export const enableBannerFlag = flag({
key: 'enable-banner-flag',
@@ -49,6 +60,7 @@ export const installAudienceFlag = flag<'humans' | 'agents'>({
});
export const rootFlags = [
+ checkoutFlag,
enableBannerFlag,
enableHeroTextFlag,
enableDitheredHeroFlag,
diff --git a/apps/docs/lib/flags/constants.ts b/apps/docs/lib/flags/constants.ts
new file mode 100644
index 000000000..65f0a2352
--- /dev/null
+++ b/apps/docs/lib/flags/constants.ts
@@ -0,0 +1,2 @@
+export const USER_ID_COOKIE = 'userId';
+export const USER_ID_HEADER = 'x-user-id';
diff --git a/apps/docs/lib/flags/identify.ts b/apps/docs/lib/flags/identify.ts
new file mode 100644
index 000000000..4ab354a11
--- /dev/null
+++ b/apps/docs/lib/flags/identify.ts
@@ -0,0 +1,43 @@
+import { dedupe } from 'flags/next';
+import { USER_ID_COOKIE, USER_ID_HEADER } from './constants';
+
+export interface Entities {
+ user?: { id: string };
+}
+
+// `baseUrl: "."` in tsconfig makes a bare `flags` import resolve to the local
+// `flags.ts`, so the cookie and header shapes are typed structurally instead
+// of importing `ReadonlyRequestCookies` and `ReadonlyHeaders` from `flags`.
+type CookieReader = { get(name: string): { value: string } | undefined };
+type HeaderReader = Pick;
+
+const generateUserId = dedupe(async () => crypto.randomUUID());
+
+export async function getOrGenerateUserId(
+ cookies: CookieReader,
+ headers: HeaderReader,
+): Promise {
+ const cookieUserId = cookies.get(USER_ID_COOKIE)?.value;
+ if (cookieUserId) {
+ return cookieUserId;
+ }
+
+ const headerUserId = headers.get(USER_ID_HEADER);
+ if (headerUserId) {
+ return headerUserId;
+ }
+
+ return generateUserId();
+}
+
+export const identify = dedupe(
+ async ({
+ cookies,
+ headers,
+ }: {
+ cookies: CookieReader;
+ headers: HeaderReader;
+ }): Promise => {
+ return { user: { id: await getOrGenerateUserId(cookies, headers) } };
+ },
+);
diff --git a/apps/docs/lib/flags/report-exposures.ts b/apps/docs/lib/flags/report-exposures.ts
new file mode 100644
index 000000000..86ac703bc
--- /dev/null
+++ b/apps/docs/lib/flags/report-exposures.ts
@@ -0,0 +1,40 @@
+import { trackExposure } from '@vercel/analytics/server';
+import type { experimental_Exposure as Exposure } from '@vercel/flags-core';
+import type { Entities } from './identify';
+
+/**
+ * Reports Vercel Experiments exposures to Web Analytics.
+ *
+ * Pass it as `experimental_reportExposures` to `createClient` from
+ * `@vercel/flags-core`. The exposure unit is resolved from the `identify()`
+ * entity using the experiment's base path, so conversion events only need to
+ * carry the same unit (for example `visitorId`) to be joined to exposures.
+ */
+// On Vercel the SDK reads request headers from the Vercel request context.
+// `next dev` has no such context, so it needs explicit headers to send at all.
+const localOptions =
+ process.env.NODE_ENV === 'development' ? { headers: {} } : undefined;
+
+export async function reportExposures(
+ exposures: readonly Exposure[],
+ entity: Readonly,
+): Promise {
+ await Promise.all(
+ exposures.map((exposure) => {
+ const unitValue = entity.user?.id ?? '';
+
+ return trackExposure(
+ {
+ experimentId: exposure.experimentId,
+ variantId: exposure.variantId ?? 'override',
+ unitKey: 'user',
+ unitValue,
+ assignmentReason: exposure.assignmentReason,
+ rampId: exposure.rampId,
+ rampPercentage: exposure.rampPercentage,
+ },
+ localOptions,
+ );
+ }),
+ );
+}
diff --git a/apps/docs/lib/flags/vercel-adapter.ts b/apps/docs/lib/flags/vercel-adapter.ts
new file mode 100644
index 000000000..53dd4ca7a
--- /dev/null
+++ b/apps/docs/lib/flags/vercel-adapter.ts
@@ -0,0 +1,10 @@
+import { createVercelAdapter } from '@flags-sdk/vercel';
+import { createClient } from '@vercel/flags-core';
+import type { Entities } from './identify';
+import { reportExposures } from './report-exposures';
+
+export const flagsClient = createClient({
+ experimental_reportExposures: reportExposures,
+});
+
+export const vercelAdapter = createVercelAdapter(flagsClient);
diff --git a/apps/docs/package.json b/apps/docs/package.json
index 7dbece98b..3e8902a92 100644
--- a/apps/docs/package.json
+++ b/apps/docs/package.json
@@ -11,7 +11,9 @@
"translate": "npx @vercel/geistdocs translate"
},
"dependencies": {
- "@vercel/analytics": "^1.6.1",
+ "@flags-sdk/vercel": "workspace:*",
+ "@vercel/analytics": "2.1.0-canary.5",
+ "@vercel/flags-core": "workspace:*",
"@vercel/geistdocs": "2.9.2",
"@vercel/speed-insights": "^1.3.1",
"@vercel/toolbar": "0.2.7",
diff --git a/apps/docs/proxy.ts b/apps/docs/proxy.ts
index cb2ca7dc9..f11eca399 100644
--- a/apps/docs/proxy.ts
+++ b/apps/docs/proxy.ts
@@ -2,6 +2,8 @@ import { createProxy } from "@vercel/geistdocs/proxy";
import { precompute } from "flags/next";
import { NextResponse } from "next/server";
import { rootFlags } from "@/flags";
+import { USER_ID_COOKIE, USER_ID_HEADER } from "@/lib/flags/constants";
+import { getOrGenerateUserId } from "@/lib/flags/identify";
import { config as geistdocsConfig } from "@/lib/geistdocs/config";
import { trackMdRequest } from "@/lib/geistdocs/md-tracking";
@@ -15,10 +17,19 @@ const proxy = createProxy({
return null;
}
+ const userId = await getOrGenerateUserId(
+ request.cookies,
+ request.headers
+ );
const code = await precompute(rootFlags);
- return NextResponse.rewrite(
- new URL(`/${defaultLanguage}/home/${code}`, request.url)
+ const requestHeaders = new Headers(request.headers);
+ requestHeaders.set(USER_ID_HEADER, userId);
+ const response = NextResponse.rewrite(
+ new URL(`/${defaultLanguage}/home/${code}`, request.url),
+ { request: { headers: requestHeaders } }
);
+ response.cookies.set(USER_ID_COOKIE, userId, { path: "/" });
+ return response;
},
});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4c180ac9a..d59c43d68 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -116,9 +116,15 @@ importers:
apps/docs:
dependencies:
+ '@flags-sdk/vercel':
+ specifier: workspace:*
+ version: link:../../packages/adapter-vercel
'@vercel/analytics':
- specifier: ^1.6.1
- version: 1.6.1(@sveltejs/kit@2.70.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.7(@typescript-eslint/types@8.46.1))(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.56.7(@typescript-eslint/types@8.46.1))(typescript@5.9.3)(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)))(next@16.3.8(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(@types/node@24.10.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(svelte@5.56.7(@typescript-eslint/types@8.46.1))
+ specifier: 2.1.0-canary.5
+ version: 2.1.0-canary.5(@sveltejs/kit@2.70.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.7(@typescript-eslint/types@8.46.1))(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.56.7(@typescript-eslint/types@8.46.1))(typescript@5.9.3)(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)))(next@16.3.8(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(@types/node@24.10.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(svelte@5.56.7(@typescript-eslint/types@8.46.1))
+ '@vercel/flags-core':
+ specifier: workspace:*
+ version: link:../../packages/vercel-flags-core
'@vercel/geistdocs':
specifier: 2.9.2
version: 2.9.2(@sveltejs/kit@2.70.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.7(@typescript-eslint/types@8.46.1))(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.56.7(@typescript-eslint/types@8.46.1))(typescript@5.9.3)(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)))(@svta/cml-cta@1.0.1(@svta/cml-structured-field-values@1.0.1(@svta/cml-utils@1.0.1))(@svta/cml-utils@1.0.1))(@svta/cml-structured-field-values@1.0.1(@svta/cml-utils@1.0.1))(@svta/cml-utils@1.0.1)(@types/mdast@4.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@vercel/functions@3.4.3)(lucide-react@0.555.0(react@19.2.4))(micromark-util-types@2.0.2)(micromark@4.0.2)(next@16.3.8(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(@types/node@24.10.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(tailwindcss@4.1.18)(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
@@ -127,7 +133,7 @@ importers:
version: 1.3.1(@sveltejs/kit@2.70.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.7(@typescript-eslint/types@8.46.1))(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.56.7(@typescript-eslint/types@8.46.1))(typescript@5.9.3)(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)))(next@16.3.8(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(@types/node@24.10.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(svelte@5.56.7(@typescript-eslint/types@8.46.1))
'@vercel/toolbar':
specifier: 0.2.7
- version: 0.2.7(2b0acf032569d1902c13370752c13288)
+ version: 0.2.7(cfa22b4c3d3279d362133cf479461783)
class-variance-authority:
specifier: ^0.7.1
version: 0.7.1
@@ -5606,6 +5612,35 @@ packages:
vue-router:
optional: true
+ '@vercel/analytics@2.1.0-canary.5':
+ resolution: {integrity: sha512-zBkf+H2iDlcxgkHYuH3bTeWS5WOad1gWpdbOp0EbNcmY+gnFNpRLKkDj8E1Al15nF/ovge0t/1q6hbj9lftfPw==}
+ peerDependencies:
+ '@remix-run/react': ^2
+ '@sveltejs/kit': ^2.70.2
+ next: '>= 13'
+ nuxt: '>= 3'
+ react: ^18 || ^19 || ^19.0.0-rc
+ svelte: '>= 4'
+ vue: ^3
+ vue-router: ^4 || ^5
+ peerDependenciesMeta:
+ '@remix-run/react':
+ optional: true
+ '@sveltejs/kit':
+ optional: true
+ next:
+ optional: true
+ nuxt:
+ optional: true
+ react:
+ optional: true
+ svelte:
+ optional: true
+ vue:
+ optional: true
+ vue-router:
+ optional: true
+
'@vercel/edge-config-fs@0.1.0':
resolution: {integrity: sha512-NRIBwfcS0bUoUbRWlNGetqjvLSwgYH/BqKqDN7vK1g32p7dN96k0712COgaz6VFizAm9b0g6IG6hR6+hc0KCPg==}
deprecated: This package has been renamed to @vercel/global-config-fs. Install @vercel/global-config-fs instead.
@@ -14165,6 +14200,14 @@ snapshots:
next: 16.3.8(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(@types/node@24.10.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
react: 19.2.4
svelte: 5.56.7(@typescript-eslint/types@8.46.1)
+ optional: true
+
+ '@vercel/analytics@2.1.0-canary.5(@sveltejs/kit@2.70.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.7(@typescript-eslint/types@8.46.1))(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.56.7(@typescript-eslint/types@8.46.1))(typescript@5.9.3)(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)))(next@16.3.8(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(@types/node@24.10.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(svelte@5.56.7(@typescript-eslint/types@8.46.1))':
+ optionalDependencies:
+ '@sveltejs/kit': 2.70.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.7(@typescript-eslint/types@8.46.1))(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.56.7(@typescript-eslint/types@8.46.1))(typescript@5.9.3)(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ next: 16.3.8(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(@types/node@24.10.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ react: 19.2.4
+ svelte: 5.56.7(@typescript-eslint/types@8.46.1)
'@vercel/edge-config-fs@0.1.0': {}
@@ -14346,6 +14389,31 @@ snapshots:
transitivePeerDependencies:
- debug
+ '@vercel/microfrontends@2.4.0(cfa22b4c3d3279d362133cf479461783)':
+ dependencies:
+ '@next/env': 16.0.10
+ '@types/md5': 2.3.6
+ ajv: 8.20.0
+ commander: 12.1.0
+ cookie: 1.0.2
+ fast-glob: 3.3.3
+ http-proxy: 1.18.1
+ jsonc-parser: 3.3.1
+ md5: 2.3.0
+ nanoid: 3.3.18
+ path-to-regexp: 6.3.0
+ semver: 7.7.4
+ optionalDependencies:
+ '@sveltejs/kit': 2.70.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.7(@typescript-eslint/types@8.46.1))(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.56.7(@typescript-eslint/types@8.46.1))(typescript@5.9.3)(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ '@vercel/analytics': 2.1.0-canary.5(@sveltejs/kit@2.70.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.7(@typescript-eslint/types@8.46.1))(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.56.7(@typescript-eslint/types@8.46.1))(typescript@5.9.3)(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)))(next@16.3.8(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(@types/node@24.10.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(svelte@5.56.7(@typescript-eslint/types@8.46.1))
+ '@vercel/speed-insights': 1.3.1(@sveltejs/kit@2.70.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.7(@typescript-eslint/types@8.46.1))(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.56.7(@typescript-eslint/types@8.46.1))(typescript@5.9.3)(vite@8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)))(next@16.3.8(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(@types/node@24.10.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(svelte@5.56.7(@typescript-eslint/types@8.46.1))
+ next: 16.3.8(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(@types/node@24.10.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ react: 19.2.4
+ react-dom: 19.2.4(react@19.2.4)
+ vite: 8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)
+ transitivePeerDependencies:
+ - debug
+
'@vercel/nft@1.10.2(rollup@4.59.0)':
dependencies:
'@mapbox/node-pre-gyp': 2.0.0
@@ -14452,6 +14520,26 @@ snapshots:
- debug
- react-dom
+ '@vercel/toolbar@0.2.7(cfa22b4c3d3279d362133cf479461783)':
+ dependencies:
+ '@tinyhttp/app': 1.3.0
+ '@vercel/microfrontends': 2.4.0(cfa22b4c3d3279d362133cf479461783)
+ chokidar: 3.6.0
+ execa: 5.1.1
+ find-up: 5.0.0
+ get-port: 5.1.1
+ strip-ansi: 6.0.1
+ optionalDependencies:
+ next: 16.3.8(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(@types/node@24.10.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ react: 19.2.4
+ vite: 8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)
+ transitivePeerDependencies:
+ - '@sveltejs/kit'
+ - '@vercel/analytics'
+ - '@vercel/speed-insights'
+ - debug
+ - react-dom
+
'@vimeo/player@2.29.0':
dependencies:
native-promise-only: 0.8.1
From a8cde0662e1782707da77daa1caff49b5f18aaa8 Mon Sep 17 00:00:00 2001
From: Vincent Derks <9963831+vincent-derks@users.noreply.github.com>
Date: Wed, 14 Oct 2026 16:47:07 +0200
Subject: [PATCH 2/2] wip
---
.../[lang]/home/[code]/purchase-button.tsx | 23 ++++++++-----------
apps/docs/components/geistdocs/provider.tsx | 21 +++--------------
apps/docs/lib/flags/report-exposures.ts | 2 +-
apps/docs/next.config.ts | 20 ++++++++++++++++
apps/docs/proxy.ts | 2 +-
5 files changed, 35 insertions(+), 33 deletions(-)
diff --git a/apps/docs/app/[lang]/home/[code]/purchase-button.tsx b/apps/docs/app/[lang]/home/[code]/purchase-button.tsx
index 2beed3827..168feb00a 100644
--- a/apps/docs/app/[lang]/home/[code]/purchase-button.tsx
+++ b/apps/docs/app/[lang]/home/[code]/purchase-button.tsx
@@ -1,8 +1,7 @@
'use client';
-import { identify, track } from '@vercel/analytics';
+import { track } from '@vercel/analytics';
import { Button } from '@vercel/geistdocs/components/button';
import { useToasts } from '@vercel/geistdocs/components/toasts';
-import { useEffect } from 'react';
import { USER_ID_COOKIE } from '@/lib/flags/constants';
function readUserId(): string | undefined {
@@ -15,21 +14,19 @@ function readUserId(): string | undefined {
export function PurchaseButton({ label }: { label: string }) {
const { success } = useToasts();
- // Exposures are reported with `unitKey: 'user'`, so the browser SDK has to
- // know the same user id for the purchase event to join to them.
- useEffect(() => {
- const userId = readUserId();
- if (userId) {
- identify(userId);
- }
- }, []);
-
return (