Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
October 26, 2021 08:34 pm GMT

A/B Testing with the new Next.js 12 Middleware

Today, Vercel released Next.js 12 which adds a number of exciting performance improvements as well as a new beta feature - Middleware. Middleware has many uses, but I'm going to focus in this post on A/B Testing.

You've always been able to run A/B tests on Next.js applications, but until this latest release there have been some major strings attached. For example, on static pages, there would often be a "flash" where users would see the original page for a split second before your variation popped in and replaced it. And on server-rendered pages, you would need to completely disable caching since two users on the same URL could get two different HTML responses.

Next.js middleware fixes these issues in an elegant way. You can create two different pages for a single URL and route traffic between them with a middleware function. The middleware is run at the edge, so it's globally distributed and super fast for your users.

Let's start with a simple Next.js app structure:

pages/|  index.tsx|  index_new.tsx|  _middleware.tslib/|  abtesting.ts

Our existing homepage (pages/index.tsx) is kind of boring:

/* pages/index.tsx */import Link from "next/link"export default function HomePage() {  return <>    <h1>My Site</h1>    <Link href="/signup"><a>Sign Up</a></Link>  </>}

We want to see if we can increase signups, so we clone the existing homepage into a new file (pages/index_new.tsx) and change the text to be more exiciting:

/* pages/index_new.tsx */import Link from "next/link"export default function HomePageVariant() {  return <>    <h1>Welcome to My Site!</h1>    <Link href="/signup"><a>Get Started Today!</a></Link>  </>}

Now the real magic happens in the pages/_middleware.ts file:

/* pages/_middleware.ts */import { NextRequest, NextResponse } from 'next/server'import {   initRequest,  getExperimentContext,  trackRequest} from "../lib/abtesting";export function middleware(req: NextRequest) {  initRequest(req)  // Default to normal Next.js routing  let res = NextResponse.next()  // If the user is on the homepage, run the experiment  const { pathname } = req.nextUrl;  if (pathname === "/") {    const ctx = getExperimentContext(req)    const { value: newPath } = ctx.run({      key: "homepage-copy-experiment",      variations: ["/", "/index_new"]    })    // Route to the assigned page path    res = NextResponse.rewrite(newPath)  }  // Server-side analytics tracking  trackRequest(req, res)  return res}

The middleware file references a few helper functions in lib/abtesting.ts. For dependencies, I'm using GrowthBook to run the A/B tests and Mixpanel for analytics tracking. Feel free to swap these out with other libraries if you want.

/* lib/abtesting.ts */import { GrowthBook } from "@growthbook/growthbook"import { NextRequest, NextResponse } from "next/server"import Mixpanel from "mixpanel"const COOKIE_NAME = 'distinct_id'const mixpanel = Mixpanel.init(process.env.MIXPANEL_TOKEN)// Get the user's ip and distinct_id from the request// Generate a new distinct_id if it doesn't exist yetlet distinct_id: string, ip: stringexport function initRequest(req: NextRequest) {  distinct_id = req.cookies[COOKIE_NAME] || crypto.randomUUID()  ip = req.ip}// Function to get the GrowthBook A/B testing clientexport function getExperimentContext(req: NextRequest) {  return new GrowthBook({    user: {id: distinct_id},    trackingCallback: (experiment, result) => {      mixpanel.track("Experiment Viewed", {        distinct_id,        ip,        experimentId: experiment.key,        variationId: result.variationId,      })    }  })}export function trackRequest(req: NextRequest) {  // Track the page view in Mixpanel  mixpanel.track("Page View", {    distinct_id,    ip,    path: req.nextUrl.pathname  })  // Persist the distinct_id in a cookie for future requests  if (!req.cookies[COOKIE_NAME]) {    res.cookie(COOKIE_NAME, distinct_id)  }}

That's all we need! Now, when a user visits your site, the following will happen:

  1. If there is no distinct_id cookie yet, we generate a new UUID.
  2. If the user is requesting the homepage, we randomly assign them a variation - either / or /index_new - and overwrite the default Next.js routing to use the assigned path.
  3. We track the page view (and which variation the user was assigned) in Mixpanel.
  4. If we needed to generate a new UUID in step 1, we store it in a cookie in the response.

Hopefully in future releases, Next.js expands on this feature to make A/B testing even more powerful. Imagine, for example, that middleware could inject props into your pages, similar to getServerSideProps. Then you wouldn't need to create new temporary pages every time you wanted to run an A/B test!


Original Link: https://dev.to/jdorn/ab-testing-with-the-new-nextjs-12-middleware-54j6

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To