Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update statsig template to require fewer env vars #1044

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions edge-middleware/ab-testing-statsig/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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?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
joe-statsig marked this conversation as resolved.
Show resolved Hide resolved
demoUrl: https://edge-ab-testing-statsig.vercel.app
relatedTemplates:
- ab-testing-google-optimize
Expand All @@ -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?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)

### Clone and Deploy

Expand Down
27 changes: 16 additions & 11 deletions edge-middleware/ab-testing-statsig/lib/statsig-api.ts
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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 []
}
},
}

Expand Down
25 changes: 20 additions & 5 deletions edge-middleware/ab-testing-statsig/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,18 @@ 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.EDGE_CONFIG || !process.env.EDGE_CONFIG_ITEM_KEY
const missingConsoleApiEnvVars = !process.env.STATSIG_CONSOLE_API_KEY

if (!missingEdgeConfigEnvVars) {
const edgeConfigClient = createClient(process.env.EDGE_CONFIG)
dataAdapter = new EdgeConfigDataAdapter({
edgeConfigClient,
edgeConfigItemKey: process.env.EDGE_CONFIG_ITEM_KEY!,
})
}

export const config = {
matcher: '/',
Expand Down Expand Up @@ -75,6 +82,14 @@ export async function middleware(req: NextRequest, event: NextFetchEvent) {
const url = req.nextUrl.clone()
url.pathname = `/${bucket}`

if (missingEdgeConfigEnvVars) {
url.searchParams.set('missingEdgeConfigEnvVars', 'true');
}

if (missingConsoleApiEnvVars) {
url.searchParams.set('missingConsoleApiEnvVars', 'true');
}

// Response that'll rewrite to the selected bucket
const res = NextResponse.rewrite(url)

Expand Down
51 changes: 39 additions & 12 deletions edge-middleware/ab-testing-statsig/pages/[bucket].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const getStaticPaths: GetStaticPaths<{ bucket: string }> = async () => {
}

function BucketPage({ bucket }: Props) {
const { reload } = useRouter()
const { query, reload } = useRouter()

function resetBucket() {
Cookie.remove(UID_COOKIE)
Expand All @@ -52,23 +52,14 @@ function BucketPage({ bucket }: Props) {
return (
<Page className="flex flex-col gap-12">
<section className="flex flex-col gap-6">
<Text variant="h1">Performant experimentation with Statsig</Text>
<Text variant="h1">Experimentation with Statsig</Text>
<Text>
In this demo we use Statsig&apos;s Server SDK at the edge to pull
experiment variants and show the resulting allocation. We leverage the{' '}
<Link href="https://vercel.com/integrations/statsig" target="_blank">
edge config integration
</Link>{' '}
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.
</Text>
<Text>
Buckets are statically generated at build time in a{' '}
<Code>/[bucket]</Code> page so its fast to rewrite to them. Take a
look at the <Code>middleware.ts</Code> file to know more.
</Text>
<Text>
You can reset the bucket multiple times to get a different bucket
assigned. You can configure your experiments, see diagnostics and
Expand Down Expand Up @@ -101,6 +92,42 @@ function BucketPage({ bucket }: Props) {
/>
</section>

<section className="flex flex-col gap-6">
<Text variant="h1">Leveraging Edge Config For Performance</Text>
{
query.missingEdgeConfigEnvVars ?
<Text>
You can leverage the {' '}
<Link href="https://vercel.com/integrations/statsig" target="_blank">
edge config integration
</Link>{' '} to pull Statsig configurations from the edge to improve performance. Follow the README for more information.
</Text> :
<Text>
We leverage the{' '}
<Link href="https://vercel.com/integrations/statsig" target="_blank">
edge config integration
</Link>{' '}
to pull Statsig configurations from the edge.
</Text>
}

{
query.missingConsoleApiEnvVars ?
<Text>
Set the STATSIG_CONSOLE_API_KEY env variable to leverage static page
generation. The sample pre-renders pages at build time in a{' '}
<Code>/[bucket]</Code> page based on the experiment variants
so its fast to rewrite to them. Take a look at the
<Code>middleware.ts</Code> file to know more.
</Text> :
<Text>
Buckets are statically generated at build time in a{' '}
<Code>/[bucket]</Code> page so its fast to rewrite to them. Take a
look at the <Code>middleware.ts</Code> file to know more.
</Text>
}
</section>

<section className="flex flex-col gap-6">
<Text variant="h2">Using metrics in your experiments</Text>
<Text>
Expand Down