Next.js SDK (Vercel Flags)
This documentation is intended for implementing the GrowthBook adapter for Vercel's Flags SDK in Next.js back-end or hybrid environments. For front-end-only GrowthBook implementations, please see our React docs.
Installation
Install with a package manager
- npm
- Yarn
- pnpm
npm install --save @flags-sdk/growthbook
yarn add @flags-sdk/growthbook
pnpm add @flags-sdk/growthbook
Adapter Usage
Import the Default Adapter
A default adapter is available for use, assuming the appropriate environment variables are set
import { growthbookAdapter } from '@flags-sdk/growthbook';
Environment Variables
The default adapter automatically uses following environment variables:
# Required
GROWTHBOOK_CLIENT_KEY="sdk-abc123"
# Optional for cloud customers, required for self-hosted
GROWTHBOOK_API_HOST="https://api.your-growthbook-instance.io"
# Optional, self-hosted only
GROWTHBOOK_APP_ORIGIN="https://app.your-growthbook-instance.io" # For Flags Explorer integration
# Edge Config (Optional)
EXPERIMENTATION_CONFIG="your-vercel-edge-config" # for native Vercel integrations
# or
GROWTHBOOK_EDGE_CONNECTION_STRING="your-edge-connection-string"
# Optional: Edge Config is keyed by `clientKey` by default. To override, set:
GROWTHBOOK_EDGE_CONFIG_ITEM_KEY="gb_payload"
Create a Custom Adapter
You can provide custom configuration by using createGrowthBookAdapter
:
import { createGrowthBookAdapter } from '@flags-sdk/growthbook';
const myGrowthBookAdapter = createGrowthBookAdapter({
clientKey: process.env.GROWTHBOOK_CLIENT_KEY!,
apiHost: process.env.GROWTHBOOK_API_HOST, // optional
appOrigin: process.env.GROWTHBOOK_APP_ORIGIN, // optional
edgeConfig: {
connectionString: process.env.GROWTHBOOK_EDGE_CONNECTION_STRING!,
itemKey: process.env.GROWTHBOOK_EDGE_CONFIG_ITEM_KEY, // optional
},
trackingCallback: (experiment, result) => {
// Back-end exposure logging
},
clientOptions: {}, // GrowthBook ClientOptions (optional)
initOptions: {}, // GrowthBook InitOptions (optional)
stickyBucketService: undefined, // Optional
});
User Identification
GrowthBook uses Attributes to evaluate feature flags and experiments. You should write an identify function providing these Attributes to GrowthBook flags:
import { dedupe, flag } from 'flags/next';
import type { Identify } from 'flags';
import { growthbookAdapter, type Attributes } from '@flags-sdk/growthbook';
const identify = dedupe((async ({ headers, cookies }) => {
return {
id: cookies.get('user_id')?.value,
// etc...
};
}) satisfies Identify<Attributes>);
export const myFeatureFlag = flag({
key: 'my_feature_flag',
identify,
adapter: growthbookAdapter.feature<boolean>(),
});
Dedupe is used above to ensure that the Attributes are computed once per request.
Adapter Methods and Properties
.feature<T>()
This method implements the Adapter interface for a GrowthBook feature:
const myFlag = flag({
key: 'my_flag',
adapter: growthbookAdapter.feature<boolean>(),
identify,
});
Option | Default | Description |
---|---|---|
exposureLogging | true | Enable/disable exposure logging. |
If your flag returns a type other than boolean
, you can provide a type argument to the feature
method.
.initialize()
Initializes the GrowthBook SDK. This is done on-demand when a growthbook flag is evaluated, and is not required to be called manually:
const growthbookClient = await growthbookAdapter.initialize();
.setTrackingCallback()
Set a back-end callback to handle experiment exposures. This allows you to log exposures to your analytics platform:
import { growthbookAdapter } from '@flags-sdk/growthbook';
import { after } from 'next/server';
growthbookAdapter.setTrackingCallback((experiment, result) => {
// Safely fire and forget async calls (Next.js)
after(async () => {
console.log('Viewed Experiment', {
experimentId: experiment.key,
variationId: result.key,
});
});
});
Front-end experiment tracking is also supported, although it requires additional manual setup. See client-side tracking for more information.
.setStickyBucketService()
Sticky bucketing ensures that users see the same experiment variant, even when user session, user login status, or experiment parameters change. See the Sticky Bucketing docs for more information. If your organization and experiment supports sticky bucketing, you must implement an instance of the StickyBucketService
to use Sticky Bucketing.
import { growthbookAdapter } from '@flags-sdk/growthbook';
import { RedisStickyBucketService } from '@growthbook/growthbook';
import Redis from 'ioredis';
const redis = new Redis(process.env.REDIS_CONNECTION_URL);
const redisStickyBucketService = new RedisStickyBucketService({ redis });
growthbookAdapter.setStickyBucketService(redisStickyBucketService);
.growthbook
You may access the underlying GrowthBook instance. Specifically, our Flags SDK adapter wraps the GrowthBookClient
class read more. All user evaluation options (attributes, tracking callbacks, sticky buckets) are applied at the userContext
level (not globally).
.stickyBucketService
If you have set a sticky bucket service, you may retrieve its instance here.
Edge Config
The adapter can load your SDK payload from Vercel^s Edge Config to lower the latency of feature flag evaluation:
- Set
GROWTHBOOK_EDGE_CONNECTION_STRING
and (optionally)GROWTHBOOK_EDGE_CONFIG_ITEM_KEY
in your environment. - Or pass
edgeConfig
directly to the adapter.
If Edge Config is not set, the adapter will fetch configuration from GrowthBook's API.
Vercel's Edge Config is subject to storage size limitations. If your SDK payload is excessively large, you may not be able to populate the your Edge Config. Read more about limitations here.
Additional Configuration
- Initialization: The adapter auto-initializes when a flag is evaluated. To pre-initialize, call
initialize()
manually. - Exposure Logging: By default, exposures are logged when flags are evaluated. You can disable this with
exposureLogging: false
or provide a custom tracking callback (applicable to back-end tracking only).
Flags Explorer Integration
To expose GrowthBook data to the Flags Explorer, use the getProviderData
function in your API route:
import { getProviderData, createFlagsDiscoveryEndpoint } from 'flags/next';
import { getProviderData as getGrowthBookProviderData } from '@flags-sdk/growthbook';
import { mergeProviderData } from 'flags';
import * as flags from '../../../../flags';
export const GET = createFlagsDiscoveryEndpoint(async (request) => {
return mergeProviderData([
getProviderData(flags),
getGrowthBookProviderData({
// Add any required options here
}),
]);
});
You will also need to provide a FLAGS_SECRET
environment variable. See Vercel's Flags Explorer guide.
Client-side Tracking
When using the Flags SDK, we strongly encourage using server-side tracking when possible. However, some event trackers are best suited for client-side implementation. Additionally, some user attributes may only be available in a front-end context.
If you need to implement client side tracking, follow the example implementation here .
This example is implemented using some glue components:
- A
<GrowthbookTracking>
server component which takes a list of evaluated feature ids and prepares the data necessary to hydrate the tracking calls for the client. It embeds a<GrowthbookTrackingClient>
client component. - A
<GrowthbookTrackingClient>
client component responsible for executing and deduping your tracking calls in the browser. You will need to define a client-side tracking callback within this component. Under the hood, this component works by replaying all of the experiment evaluations in a client context. - You must include
<GrowthbookTracking>
in any component which evaluates a feature flag (or specifically: all referenced flags that may trigger experiment tracking callbacks).