AB testing with Adobe Target

The demo showcases multiple ways in which Adobe Target can be used in Next.js pages, using different data fetching and rendering strategies:

The differences between the pages are:

  • Pages under Next.js Middleware take advantage of the Vercel Edge Network, rewrites should be very fast if the request hits the Target Edge Network
  • The difference between /static-rewrites and /ssg is only that the latter is using dynamic routes over predefined pages
  • Pages that have at.js will have a larger JS footprint as it takes 33.7kb to load it.
  • If the page is blocking until the experiment is ready, like in /csr/at-blocking or /ssr, TTFB and FCP are worse than in non-blocking pages
  • Pages that call an API route instead of using at.js are less likely to get adblocked because the API routes live in the same domain. The API route takes more time to send an event as it's an intermediary, but analytics reporting shouldn't be affecting performance

There are also measurable differences in performance between CSR, SSR, and Static + Middleware rewrites, the links below are using Lighthouse Metrics:

Based on the lighthouse results above, we can conclude the following:

  • Static + Middleware rewrites scores better CWV (Core Web Vitals - LCP, TTI, TBT) results than other pages, this is due to it being completely static and not using at.js, while still being able to handle per request experimentation
  • The blocking behavior of /csr/at-blocking gives it worse performance over/csr/at
  • /ssr/at has better performance than /csr/at-blocking even though it has to wait for the page to be generated by a serverless function. This has to do with the performance hit introduced by waiting on at.js and blocking the paint of the page until the experiment is ready
  • The difference between /ssr/at and /csr/at is less noticeable, in this case case it's more of a tradeoff, CSR paints faster but it has a layout shift while the experiment loads, SSR loads with the experiment ready but it's a serverless function and can't be cached globally if it depends on request data