Watch Webinar: Figma - Design to Code in 80% Less Time

Announcing Visual Copilot - Figma to production in half the time logo
Talk to Us
Talk to Us










Visual CMS

Drag-and-drop visual editor and headless CMS for any tech stack

Theme Studio for Shopify

Build and optimize your Shopify-hosted storefront, no coding required



Get StartedLogin

‹ Back to blog

A/B testing & personalization

A/B Testing and Personalization with Next.js Edge Middleware

October 11, 2022

Written By Steve Sewell

77% of people choose, recommend, or pay more for brands that provide personalized experiences [source]. Customers have come to expect white-glove service from their favorite brands — both in-store and online experiences.

Personalization has come a long way, especially during the pandemic. Thanks to evolving technology across A/B testing, webpage heat maps, and audience segmentation, websites can now show you pages that are uniquely yours, with products and content that suit your needs the best.

But traditional solutions to personalization and A/B testing can come at a major cost. We often call this the “personalization paradox” — how many will layer on tools to personalize pages, tools that heavily rely on javascript and slow down your site. This performance penalty can cost you more conversions than you gain by personalization if you don’t approach things right.

<!-- ❌ the wrong way -->
<script src="/blocking-js-of-doom-to-inject-personalization.js"></script>

Luckily, now with Edge Middleware, we can personalize without the performance penalty, using the edge, instead of client side javascript, to deliver personalized experiences. Here’s why you need high-speed personalization on your website — and we’re going to show you how to get it done with Next.js and edge middleware.

// ✅ the right way
import { NextResponse, NextRequest } from 'next/server'
import { getPersonlizedURL } from ''

export default function middleware(request: NextRequest) {
  const rewrite = getPersonlizedURL(request)
  return NextResponse.rewrite(rewrite)

Why you need personalization and A/B testing

Personalized experiences have become a necessity. Plenty of us depend on the internet to tell us what we need next, based on our preferences and patterns. In fact, 71% percent of consumers expect companies to deliver personalized interactions. And 76% get frustrated when this doesn’t happen. This is a missed opportunity not only if you’re looking to attract new customers but also if you want to retain your existing customers: Nearly half of consumers say they will likely become repeat buyers after a personalized shopping experience with a retail brand.

In other words, personalization is a better customer experience that drives profit and performance for a brand. Companies that grow faster drive 40% more of their revenue from personalization than other slower-growing brands.

On top of that, introducing A/B testing can allow you to learn from real data and experimentation, so you can remove the guesswork around what will truly convert your visitors.

Why traditional approaches to personalization and A/B testing fail

The crucial thing to remember here is that, no matter what swanky new features you introduce into your digital experiences (including personalization), you cannot compromise on speed and performance. Time is extremely valuable — and this is especially true for all modern businesses. Leaving a user waiting for more than a few milliseconds could mean high bounce rates, low conversion rates, more ad spend, and poor user experience overall. Not only that, a study in the UK showed that businesses are losing roughly $80 billion in unrealized sales due to slow-loading websites.

The good news is personalization is not some far-fetched science fiction concept. It’s very much reality — and surprisingly easy to achieve. But here’s the catch: Traditional solutions to personalization and A/B testing are slow.

  • Server-side personalization requires multiple roundtrips to servers. For server-side personalization to work, you’d have to send your request all the way around the world and the server would have to assemble your pages on the fly — all while users are still waiting.
  • JavaScript might seem like the ideal solution at first glance, but blocking JavaScript adds up to 1-2 seconds of mobile load times. You may deliver a generic page quickly, but the JavaScript might prevent the page from being visible at all. Then it fetches more content that’s unique to the visitor and injects it into the HTML. Apart from the general inefficiency, JavaScript also doesn’t work well with modern stacks like React. Ultimately, you don’t want to be fighting your component-rendering system and some external injection system.
  • Static site generators (SSGs) are slightly faster than the above options, but personalized content must lazy load. You can use static site generation to deliver the unpersonalized parts of a page quickly; however, when you want to have unique parts per visitor, you end up fetching that in the client. This means you're still only seeing parts of a page, and then, while downloading JavaScript, you're making another fetch, and the re-render leads to layout shifts. All in all, not the best experience for the user.

Fortunately, we have a much better solution.

Using Next.js and edge middleware for high-performance personalization and A/B testing

Here’s the quick and dirty summary: A cached response, locally, from the CDN edge network to eliminate travel time between the edge server and your visitor.

All you have to do is rewrite a page at the edge with the page along with a hash of personalized attributes. The rewrite takes key value pairs of information about the user, like their age, demographics, browsing behavior, and so on, and adds that to the end of the URL as the cache key.

For instance, if you have a pages/page.tsx, you can rename it to pages/page/[hash].tsx, and add it to be included into the rewriting middleware to add the personalized hash at the end.

You can now have your page return personalized content based on what is in the hash, and this is purely automatic via what personalization.* cookies are present.

You can set these cookies to be triggered based on any factor. For example:

Cookies.set('personalization.returnVisitor', 'true')

And now your /page will be rewritten to /page/returnVisitor=true when that cookie is present, and be handled accordingly.

Behind the scenes, Next.js is performing incremental static regeneration (ISR) using the fallback: true option. As a result, any unique new combination of parameters for the page path is fetched and cached at the edge, so that it’s served instantly to subsequent users.

This means that instead of serving generic content to all your users, you’re able to serve dynamic, highly customized pages. And the best part? There’s no performance cost.

For more detail, check out our blog post, Using Query Params and Cookies in Next.js Static Pages.

Try it yourself

Head over to our example repo to try an end to end example yourself.


Personalization is crucial to stand out from your competitors, win over your customers, and increase conversions. But traditional solutions to personalization and a/b testing are painfully slow. Instead, using Next.js and edge middleware helps you create bespoke experiences from scratch for each of your users, run personalized tests, show different images or products by locale, schedule them to publish live, and more.


Hand written text that says "A drag and drop headless CMS?"

Introducing Visual Copilot:

A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

Like our content?

Join Our Newsletter

Continue Reading
Web Development12 MIN
Figma to Angular: Convert Designs to Clean Angular Code in a Click
WRITTEN BYVishwas Gopinath
May 16, 2024
Web Development18 MIN
Getting Started with Mitosis: Creating a Cross-Framework Design System
WRITTEN BYVishwas Gopinath
May 7, 2024
Company News3 MIN closes $20 million in funding led by M12, Microsoft’s Venture Fund
WRITTEN BYSteve Sewell
April 24, 2024