worried-night-96863
07/21/2025, 8:13 PMhandsome-lighter-25056
07/21/2025, 8:36 PMstrong-mouse-55694
07/21/2025, 8:45 PMgetDeferredTrackingCalls is empty, it likely means that the experiment wasn't evaluated. For SSR, you need to ensure that you're also evaluating server-side. Otherwise, there won't be any data to forward. Also, when using getDeferredTrackingCalls, you'll also be firing the callback on the client.
Sharing more of your setup will also help provide us more guidanceworried-night-96863
07/21/2025, 8:56 PMhandsome-lighter-25056
07/21/2025, 9:04 PMstrong-mouse-55694
07/21/2025, 9:09 PMgb.isOn or similar to generate the data for the deferred tracking call.
• This also requires you to be setting up a user id. If there isn't a user id, then assignment won't happen.
• The experiment in GB needs to be active and configured.
• Are you debugging this locally? Or do you have anything other parts of your setup that should be noted?
• Also, what are you using for event tracking? Have you tried just using console.log() to see if you anything fires?worried-night-96863
07/21/2025, 9:12 PMhandsome-lighter-25056
07/21/2025, 9:45 PMstrong-mouse-55694
07/22/2025, 12:49 PMhandsome-lighter-25056
07/22/2025, 1:50 PMworried-night-96863
07/22/2025, 2:42 PMexport default async function Page({ params, searchParams }: PageProps<true>) {
const { slug } = await params;
const urlPath = `/${slug?.join('/') || ''}`;
const cookieStore = await cookies();
const headerStore = await headers();
const rawSearchParams = await searchParams;
const gbAttributes = getGrowthBookAttributes(headerStore, cookieStore);
// for server side pages with growthbook devtools (refresh page to see changes)
const { gb, trackingData } = await initGrowthBook({
attributes: gbAttributes,
plugins: [
devtoolsNextjsPlugin({
requestCookies: cookieStore,
searchParams: rawSearchParams as { _gbdebug?: string | undefined },
}),
],
});
console.log(gbAttributes);
const isInTest = gb.isOn('redirect-n1-to-ed-questions');
console.log('trackingData in page', trackingData);
const isBmN1 = urlPath === '/bm/n1';
if (isInTest && isBmN1) {
return (
<>
<EdQuestions />
<GrowthBookTracking data={trackingData} />
</>
);
}
const filteredSearchParams = rawSearchParams
? filterUndefined(rawSearchParams)
: undefined;
const content = await fetchOneEntry({
apiKey: BUILDER_API_KEY,
model: 'page',
options: getBuilderSearchParams(filteredSearchParams),
userAttributes: { urlPath },
});
const canShowContent = content || isPreviewing(filteredSearchParams);
if (!canShowContent) {
notFound();
}
return (
<>
<Content
apiKey={BUILDER_API_KEY}
content={content}
customComponents={customComponents}
model="page"
/>
<GrowthBookTracking data={trackingData} />
</>
);
}worried-night-96863
07/22/2025, 2:43 PMexport function growthBookInstance(options?: GrowthBookInstanceOptions) {
return new GrowthBook({
clientKey:
env.NEXT_PUBLIC_VERCEL_ENV === 'production'
? env.NEXT_PUBLIC_GROWTHBOOK_CLIENT_KEY
: 'sdk-0HcTwbYopRHy3HwL',
enableDevMode: true,
...options,
});
}
export default async function initGrowthBook(
options?: GrowthBookInstanceOptions,
) {
setPolyfills({
fetch: (
url: Parameters<typeof fetch>[0],
opts: Parameters<typeof fetch>[1],
) =>
fetch(url, {
...opts,
cache: 'no-store',
}),
});
configureCache({ disableCache: true });
const gb = growthBookInstance({ ...options });
const { error } = await gb.init({ timeout: 1000 });
if (error) {
console.error(error);
}
const payload = gb.getDecryptedPayload();
const trackingData = gb.getDeferredTrackingCalls();
console.log('payload', payload);
console.log('trackingData', trackingData);
return { gb, payload, trackingData };
}handsome-lighter-25056
07/22/2025, 3:41 PMhandsome-lighter-25056
07/22/2025, 5:42 PMworried-night-96863
07/22/2025, 7:50 PMbrief-honey-45610
07/22/2025, 9:13 PMstrong-mouse-55694
07/22/2025, 9:20 PMinitGrowthbook abstraction is the issue. If you move const trackingData = gb.getDeferredTrackingCalls(); into the component, after the feature call, then it you'll see the data as expected. (If you don't need to fire your event tracking clientside, then you could replace the deferred calls with a tracking callback in your GrowthBook initialization.)
However, let me think about that function to determine if it's a good approach.worried-night-96863
07/22/2025, 9:25 PMstrong-mouse-55694
07/22/2025, 9:34 PMgb.getDeferredTrackingCalls()?worried-night-96863
07/22/2025, 9:35 PMstrong-mouse-55694
07/22/2025, 9:40 PMimport { GrowthBookTracking } from "@/lib/GrowthBookTracking";
import { GB_UUID_COOKIE } from "@/middleware";
import { cookies } from "next/headers";
import gbInit from "./gbInit";
export default async function ServerDynamic() {
// configureServerSideGrowthBook();
const id = cookies().get(GB_UUID_COOKIE)?.value || "";
const { gb, payload } = await gbInit(id);
// Evaluate any feature flags
const feature1Enabled = gb.isOn("feature1");
const trackingData = gb.getDeferredTrackingCalls();
// Cleanup
gb.destroy();
return (
<div>
<h2>Dynamic Server Rendering</h2>
<p>
This page renders dynamically for every request. You can use feature
flag targeting and run A/B experiments entirely server-side.
</p>
<ul>
<li>
feature1: <strong>{feature1Enabled ? "ON" : "OFF"}</strong>
</li>
</ul>
{/* <RevalidateMessage /> */}
<GrowthBookTracking data={trackingData} />
</div>
);
}
and the version of the init function
import {
GrowthBook,
setPolyfills,
configureCache,
} from "@growthbook/growthbook";
export function growthBookInstance(id: string) {
return new GrowthBook({
apiHost: process.env.NEXT_PUBLIC_GROWTHBOOK_API_HOST,
clientKey: process.env.NEXT_PUBLIC_GROWTHBOOK_CLIENT_KEY,
enableDevMode: true,
attributes: {
id,
},
});
}
export default async function initGrowthBook(id: string) {
setPolyfills({
fetch: (
url: Parameters<typeof fetch>[0],
opts: Parameters<typeof fetch>[1]
) =>
fetch(url, {
...opts,
cache: "no-store",
}),
});
configureCache({ disableCache: true });
const gb = growthBookInstance(id);
const { error } = await gb.init({ timeout: 1000 });
if (error) {
console.error(error);
}
const payload = gb.getDecryptedPayload();
return { gb, payload };
}worried-night-96863
07/22/2025, 9:55 PMworried-night-96863
07/22/2025, 9:56 PMstrong-mouse-55694
07/22/2025, 10:02 PMstrong-mouse-55694
07/22/2025, 10:02 PMconst payload = gb.getDecryptedPayload();
console.log(payload);strong-mouse-55694
07/22/2025, 10:03 PM{
status: 200,
features: {
flag_internetmd___headline_cta: { defaultValue: false },
flag_internetmd___headline_cta_2: { defaultValue: false },
flag_internetmd___headline_cta_23: { defaultValue: false },
feature1: { defaultValue: false, rules: [Array] }
},
experiments: [],
dateUpdated: '2025-07-22T20:54:12.531Z'
}worried-night-96863
07/22/2025, 10:04 PM{
"status": 200,
"features": {
"recommended_strength_variant": {
"defaultValue": "high",
"rules": [
{
"id": "fr_19g624mbyqadh1",
"condition": {
"url": {
"$regex": "rugiet-men-ed"
}
},
"coverage": 1,
"hashAttribute": "id",
"seed": "5bbb2ec7-3e55-4707-b910-ca3b64f603a0",
"hashVersion": 2,
"variations": [
"high",
"max",
"medium",
"low"
],
"weights": [
0.25,
0.25,
0.25,
0.25
],
"key": "recommended_strength_variant",
"meta": [
{
"key": "0",
"name": "high"
},
{
"key": "1",
"name": "very_high"
},
{
"key": "2",
"name": "medium"
},
{
"key": "3",
"name": "low"
}
],
"phase": "3",
"name": "recommended_strength_variant"
}
]
},
"recommended_quantity_variant": {
"defaultValue": 2,
"rules": [
{
"id": "fr_19g621mbyn73bk",
"condition": {
"url": {
"$regex": "rugiet-men-ed"
}
},
"coverage": 1,
"hashAttribute": "id",
"seed": "df600dc2-b529-40db-9a47-618c96b02de6",
"hashVersion": 2,
"variations": [
6,
12,
18,
24
],
"weights": [
0.25,
0.25,
0.25,
0.25
],
"key": "recommended_quantity_variant",
"meta": [
{
"key": "0",
"name": "1"
},
{
"key": "1",
"name": "2"
},
{
"key": "2",
"name": "3"
},
{
"key": "3",
"name": "4"
}
],
"phase": "3",
"name": "recommended_quantity_variant"
}
]
},
"product_intro": {
"defaultValue": false
},
"test-pdm": {
"defaultValue": "false"
},
"redirect-n1-to-ed-questions": {
"defaultValue": false,
"rules": [
{
"id": "fr_19g624md7r3s83",
"condition": {
"url": {
"$regex": "utm_source=(fb|facebook|ig)"
}
},
"coverage": 0.2,
"hashAttribute": "id",
"bucketVersion": 1,
"seed": "3f394707-b979-471c-997e-fb3d63d09e8b",
"hashVersion": 2,
"variations": [
false,
true
],
"weights": [
0.5,
0.5
],
"key": "social-lp-bmn1-vs-ed-questions",
"meta": [
{
"key": "0",
"name": "Control"
},
{
"key": "1",
"name": "Variation 1"
}
],
"phase": "4",
"name": "Social LP bm/n1 vs ed-questions"
}
]
},
"rugiet-lp-comparison-chart": {
"defaultValue": "CONTROL"
}
},
"experiments": [],
"dateUpdated": "2025-07-17T22:10:33.405Z"
}worried-night-96863
07/22/2025, 10:05 PMworried-night-96863
07/22/2025, 10:05 PMstrong-mouse-55694
07/22/2025, 10:17 PMexport function growthBookInstance(id: string) {
return new GrowthBook({
apiHost: process.env.NEXT_PUBLIC_GROWTHBOOK_API_HOST,
clientKey: process.env.NEXT_PUBLIC_GROWTHBOOK_CLIENT_KEY,
enableDevMode: true,
attributes: {
id,
},
trackingCallback: (data) => {
console.log("trackingCallback", data);
},
});
}
and then what's the value if you:
const isInTest = gb.isOn('redirect-n1-to-ed-questions');
console.log(isInTest)
and you change the ID. Do you get different values?strong-mouse-55694
07/22/2025, 10:38 PMworried-night-96863
07/23/2025, 2:54 PMworried-night-96863
07/23/2025, 2:57 PMstrong-mouse-55694
07/23/2025, 3:54 PMgb.debug = true This will console log a lot more info
2. Create a minimal example. Right now, you're doing some redirect stuff. It's unclear whether that's impacting the experiment. I'd try a really basic component/page and see if you encounter the same issue. There's something in how you're setting up your page and/or configuring GrowthBook that's preventing the experiment evaluation from happening properly.
3. Do you see different values for gb.ison when the user id changes?worried-night-96863
07/23/2025, 4:06 PMSkip because of coverage { id: 'social-lp-bmn1-vs-ed-questions-testing' }
Use default value { id: 'redirect-n1-to-ed-questions', value: false }
GET /bm/n1 200 in 466ms
Skip because of coverage { id: 'social-lp-bmn1-vs-ed-questions-testing' }
Use default value { id: 'redirect-n1-to-ed-questions', value: false }
when I change the user id I got the test experiment which gave me a lot of output including the logs from the trackingCallback:
trackingCallback called on server side
experiment {
variations: [ false, true ],
key: 'social-lp-bmn1-vs-ed-questions-testing',
coverage: 0.2,
weights: [ 0.5, 0.5 ],
hashAttribute: 'id',
meta: [ { key: '0', name: 'Control' }, { key: '1', name: 'Variation 1' } ],
name: 'Social LP bm/n1 vs ed-questions (Testing)',
phase: '0',
seed: '3f394707-b979-471c-997e-fb3d63d09e8b',
hashVersion: 2
}
result {
key: '1',
featureId: 'redirect-n1-to-ed-questions',
inExperiment: true,
hashUsed: true,
variationId: 1,
value: true,
hashAttribute: 'id',
hashValue: 'SnvrzILKYO7Eda9L7miUX',
stickyBucketUsed: false,
name: 'Variation 1',
bucket: 0.5601
}
In experiment { id: 'social-lp-bmn1-vs-ed-questions-testing', variation: 1 }
GET /bm/n1 200 in 331ms
trackingCallback called on server side
experiment {
variations: [ false, true ],
key: 'social-lp-bmn1-vs-ed-questions-testing',
coverage: 0.2,
weights: [ 0.5, 0.5 ],
hashAttribute: 'id',
meta: [ { key: '0', name: 'Control' }, { key: '1', name: 'Variation 1' } ],
name: 'Social LP bm/n1 vs ed-questions (Testing)',
phase: '0',
seed: '3f394707-b979-471c-997e-fb3d63d09e8b',
hashVersion: 2
}
result {
key: '1',
featureId: 'redirect-n1-to-ed-questions',
inExperiment: true,
hashUsed: true,
variationId: 1,
value: true,
hashAttribute: 'id',
hashValue: 'SnvrzILKYO7Eda9L7miUX',
stickyBucketUsed: false,
name: 'Variation 1',
bucket: 0.5601
}
In experiment { id: 'social-lp-bmn1-vs-ed-questions-testing', variation: 1 }worried-night-96863
07/23/2025, 4:12 PMworried-night-96863
07/23/2025, 4:15 PMworried-night-96863
07/23/2025, 4:18 PMstrong-mouse-55694
07/23/2025, 6:31 PMworried-night-96863
07/23/2025, 6:37 PMhandsome-lighter-25056
07/23/2025, 6:53 PM