diff --git a/edge-middleware/ab-testing-statsig/README.md b/edge-middleware/ab-testing-statsig/README.md index 53527f27ab..d4c23b929e 100644 --- a/edge-middleware/ab-testing-statsig/README.md +++ b/edge-middleware/ab-testing-statsig/README.md @@ -8,7 +8,7 @@ useCase: - Edge Middleware - Documentation css: Tailwind -deployUrl: https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fexamples%2Ftree%2Fmain%2Fedge-middleware%2Fab-testing-statsig&project-name=ab-testing-statsig&repository-name=ab-testing-statsig&integration-ids=oac_NAO87zzp3ADxj2ZUh3vikLip&env=STATSIG_SERVER_API_KEY,NEXT_PUBLIC_STATSIG_CLIENT_KEY,STATSIG_CONSOLE_API_KEY,EDGE_CONFIG,EDGE_CONFIG_ITEM_KEY&envDescription=Statsig%20API%20keys%20and%20Edge%20Config%20settings&envLink=https%3A%2F%2Fdocs.statsig.com%2Fguides%2Ffirst-feature +deployUrl: https://vercel.com/new/clone?demo-description=Reduce+CLS+and+improve+performance+from+client-loaded+experiments+at+the+edge+with+Statsig&demo-image=%2F%2Fimages.ctfassets.net%2Fe5382hct74si%2F3iWLIPxEQc7e5plRHDW5Nd%2Fdf781629a2e72f6ae5d05879787c4c79%2Fvercel_statsig.png&demo-title=Experimentation+with+Statsig&demo-url=https%3A%2F%2Fedge-ab-testing-statsig.vercel.app&envLink=https%3A%2F%2Fdocs.statsig.com%2Fguides%2Ffirst-feature&project-name=ab-testing-statsig&repository-name=ab-testing-statsig&repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fexamples%2Ftree%2Fmain%2Fedge-middleware%2Fab-testing-statsig&products=%5B%7B%22integrationSlug%22%3A%22statsig%22%2C%22productSlug%22%3A%22statsig%22%2C%22type%22%3A%22integration%22%2C%22protocol%22%3A%22experimentation%22%7D%5D demoUrl: https://edge-ab-testing-statsig.vercel.app relatedTemplates: - ab-testing-google-optimize @@ -31,7 +31,7 @@ You can choose from one of the following two methods to use this repository: Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=vercel-examples): -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fexamples%2Ftree%2Fmain%2Fedge-middleware%2Fab-testing-statsig&project-name=ab-testing-statsig&repository-name=ab-testing-statsig&integration-ids=oac_NAO87zzp3ADxj2ZUh3vikLip&env=STATSIG_SERVER_API_KEY,NEXT_PUBLIC_STATSIG_CLIENT_KEY,STATSIG_CONSOLE_API_KEY,EDGE_CONFIG,EDGE_CONFIG_ITEM_KEY&envDescription=Statsig%20API%20keys%20and%20Edge%20Config%20settings&envLink=https%3A%2F%2Fdocs.statsig.com%2Fguides%2Ffirst-feature) +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?demo-description=Reduce+CLS+and+improve+performance+from+client-loaded+experiments+at+the+edge+with+Statsig&demo-image=%2F%2Fimages.ctfassets.net%2Fe5382hct74si%2F3iWLIPxEQc7e5plRHDW5Nd%2Fdf781629a2e72f6ae5d05879787c4c79%2Fvercel_statsig.png&demo-title=Experimentation+with+Statsig&demo-url=https%3A%2F%2Fedge-ab-testing-statsig.vercel.app&envLink=https%3A%2F%2Fdocs.statsig.com%2Fguides%2Ffirst-feature&project-name=ab-testing-statsig&repository-name=ab-testing-statsig&repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fexamples%2Ftree%2Fmain%2Fedge-middleware%2Fab-testing-statsig&products=%5B%7B%22integrationSlug%22%3A%22statsig%22%2C%22productSlug%22%3A%22statsig%22%2C%22type%22%3A%22integration%22%2C%22protocol%22%3A%22experimentation%22%7D%5D) ### Clone and Deploy diff --git a/edge-middleware/ab-testing-statsig/lib/statsig-api.ts b/edge-middleware/ab-testing-statsig/lib/statsig-api.ts index 902a1a7f89..2af9a18063 100644 --- a/edge-middleware/ab-testing-statsig/lib/statsig-api.ts +++ b/edge-middleware/ab-testing-statsig/lib/statsig-api.ts @@ -1,5 +1,5 @@ const STATSIG_URL = 'https://statsigapi.net' -const STATSIG_CONSOLE_API_KEY = process.env.STATSIG_CONSOLE_API_KEY! +const STATSIG_CONSOLE_API_KEY = process.env.STATSIG_CONSOLE_API_KEY ?? '' /** * Fetch wrapper for the Statsig API @@ -44,17 +44,22 @@ async function statsig( const api = { async getBuckets(experiment: string) { - // https://docs.statsig.com/console-api/experiments#get-/experiments/-experiment_id- - const experimentConfig = await statsig( - `/console/v1/experiments/${experiment}`, - 'GET', - { apiKey: STATSIG_CONSOLE_API_KEY } - ) + try { + // https://docs.statsig.com/console-api/experiments#get-/experiments/-experiment_id- + const experimentConfig = await statsig( + `/console/v1/experiments/${experiment}`, + 'GET', + { apiKey: STATSIG_CONSOLE_API_KEY } + ) - return experimentConfig.data.groups.map( - (group: { parameterValues: { bucket: string } }) => - group.parameterValues.bucket - ) + return experimentConfig.data.groups.map( + (group: { parameterValues: { bucket: string } }) => + group.parameterValues.bucket + ) + } catch (e) { + console.error('Failed to fetch buckets from Statsig', e) + return [] + } }, } diff --git a/edge-middleware/ab-testing-statsig/middleware.ts b/edge-middleware/ab-testing-statsig/middleware.ts index 53a56c2e06..bfdc525a20 100644 --- a/edge-middleware/ab-testing-statsig/middleware.ts +++ b/edge-middleware/ab-testing-statsig/middleware.ts @@ -7,11 +7,17 @@ import { EXPERIMENT, UID_COOKIE, GROUP_PARAM_FALLBACK } from './lib/constants' // We'll use this to validate a random UUID const IS_UUID = /^[0-9a-f-]+$/i -const edgeConfigClient = createClient(process.env.EDGE_CONFIG) -const dataAdapter = new EdgeConfigDataAdapter({ - edgeConfigClient, - edgeConfigItemKey: process.env.EDGE_CONFIG_ITEM_KEY!, -}) +let dataAdapter: EdgeConfigDataAdapter; + +const missingEdgeConfigEnvVars = !process.env.EXPERIMENTATION_CONFIG || !process.env.EXPERIMENTATION_CONFIG_ITEM_KEY + +if (!missingEdgeConfigEnvVars) { + const edgeConfigClient = createClient(process.env.EXPERIMENTATION_CONFIG) + dataAdapter = new EdgeConfigDataAdapter({ + edgeConfigClient, + edgeConfigItemKey: process.env.EXPERIMENTATION_CONFIG_ITEM_KEY!, + }) +} export const config = { matcher: '/', diff --git a/edge-middleware/ab-testing-statsig/pages/[bucket].tsx b/edge-middleware/ab-testing-statsig/pages/[bucket].tsx index a71711ba77..bf6cc6d8a0 100644 --- a/edge-middleware/ab-testing-statsig/pages/[bucket].tsx +++ b/edge-middleware/ab-testing-statsig/pages/[bucket].tsx @@ -18,12 +18,16 @@ import exampleScreenshot from '../public/example_experiment.png' interface Props { bucket: string + missingEdgeConfigEnvVars: boolean + missingConsoleApiEnvVars: boolean } export const getStaticProps: GetStaticProps = async ({ params }) => { return { props: { bucket: params?.bucket as string, + missingEdgeConfigEnvVars: !process.env.EXPERIMENTATION_CONFIG || !process.env.EXPERIMENTATION_CONFIG_ITEM_KEY, + missingConsoleApiEnvVars: !process.env.STATSIG_CONSOLE_API_KEY, }, } } @@ -35,12 +39,12 @@ export const getStaticPaths: GetStaticPaths<{ bucket: string }> = async () => { .filter(Boolean) return { - paths: groups.map((group) => ({ params: { bucket: group } })), + paths: groups.map((group) => ({ params: { bucket: group, missingEdgeConfigEnvVars: !process.env.EXPERIMENTATION_CONFIG || !process.env.EXPERIMENTATION_CONFIG_ITEM_KEY, missingConsoleApiEnvVars: !process.env.STATSIG_CONSOLE_API_KEY } })), fallback: 'blocking', } } -function BucketPage({ bucket }: Props) { +function BucketPage({ bucket, missingEdgeConfigEnvVars, missingConsoleApiEnvVars }: Props) { const { reload } = useRouter() function resetBucket() { @@ -52,23 +56,14 @@ function BucketPage({ bucket }: Props) { return (
- Performant experimentation with Statsig + Experimentation with Statsig In this demo we use Statsig's Server SDK at the edge to pull - experiment variants and show the resulting allocation. We leverage the{' '} - - edge config integration - {' '} - to pull Statsig configurations from the edge. As long as you have a + experiment variants and show the resulting allocation. As long as you have a bucket assigned you will always see the same result, otherwise you will be assigned a bucket to mantain the odds specified in the experiment. - - Buckets are statically generated at build time in a{' '} - /[bucket] page so its fast to rewrite to them. Take a - look at the middleware.ts file to know more. - You can reset the bucket multiple times to get a different bucket assigned. You can configure your experiments, see diagnostics and @@ -90,8 +85,8 @@ function BucketPage({ bucket }: Props) { In order to set this demo up yourself, in the Statsig console - , create a new experiment called "statsig_example". - Create experiment groups, each with a "bucket" parameter. + , create a new experiment called "statsig_example". + Create experiment groups, each with a "bucket" parameter. Make sure to start the experiment, and from there this example will display the bucket that the user was assigned to. See the screenshot below for an example experiment setup. @@ -101,6 +96,42 @@ function BucketPage({ bucket }: Props) { />
+
+ Leveraging Edge Config For Performance + { + missingEdgeConfigEnvVars ? + + You can leverage the {' '} + + edge config integration + {' '} to pull Statsig configurations from the edge to improve performance. Follow the README for more information. + : + + We leverage the{' '} + + edge config integration + {' '} + to pull Statsig configurations from the edge. + + } + + { + missingConsoleApiEnvVars ? + + Set the STATSIG_CONSOLE_API_KEY env variable to leverage static page + generation. The sample pre-renders pages at build time in a{' '} + /[bucket] page based on the experiment variants + so its fast to rewrite to them. Take a look at the + middleware.ts file to know more. + : + + Buckets are statically generated at build time in a{' '} + /[bucket] page so its fast to rewrite to them. Take a + look at the middleware.ts file to know more. + + } +
+
Using metrics in your experiments