A Next.js 16 storefront powered by Storyblok for content management
and Croct for real-time personalization.
Storyblok published a great tutorial on personalization with Next.js that walks through building personalized experiences using cookies, middleware rewrites, and manually defined content variants. It's a solid starting point for understanding the concepts.
In practice, though, that approach requires custom code for every new audience segment, manual variant wiring in the CMS, and has no built-in support for AB testing or analytics. As the number of pages and segments grows, it becomes hard to maintain.
This project is a fork of the original demo that replaces the manual personalization logic with Croct. With Croct, any content already managed in Storyblok becomes personalizable and ready for AB testing, without changing how you structure or deliver your pages.
Croct is a headless platform for conversion optimization that pairs nicely with Storyblok. Using Croct, you get:
- Server-side AB testing support with real-time audience segmentation
- Server-side content personalization based on location, behavior, or custom rules
- Visitor profile explorer so you can dive deeper and analyze the user journey using out-of-the-box events.
- Built-in analytics and Bayesian analysis for every variant and experience
- Seamless compatibility with your existing Storyblok schemas
- Fast implementation with zero CMS migration
With Croct, any content already managed in Storyblok becomes personalizable and ready for AB testing, without changing how you structure or deliver it.
Unlike currently available plugins, you can run experiments at the component level rather than the field level. Croct replaces static module content with dynamic content, allowing you to manage everything directly on the UI while using Storyblok content as a fallback.
Since it comes with built-in audience segmentation and analytics, there's no need to add extra integrations with CDPs to segment visitors or with analytics tools to gather insights.
A fashion store demo that shows how Storyblok and Croct work together in a Next.js App Router project. Storyblok manages all the content, while Croct makes it personalizable and trackable without any changes to the content structure.
- CMS-managed pages — announcement bar, homepage hero, feature strips, split features, and product catalog are all Storyblok stories
- Personalized content — Croct delivers targeted variants for any Storyblok component, with no extra CMS configuration
- Interest tracking — browsing behavior (category views, style quiz answers) is captured in real-time to build user profiles
- Event-driven analytics — funnel events like cart views, checkouts, and purchases are tracked through Croct for personalization and analytics
- Concierge widget — an interactive style quiz that collects preferences and feeds them into Croct for immediate personalization
Follow these steps to run the project locally. You'll need access to a Storyblok space and optionally a Croct workspace.
- Node.js 18+
- A Storyblok space with the demo content
- A Croct workspace (or use the pre-configured one)
git clone <repo-url>
cd storyblok-next-personalization
npm installCreate a .env.local file with your Storyblok access token:
NEXT_PUBLIC_STORYBLOK_CONTENT_API_ACCESS_TOKEN=<your-token>Run the Croct CLI to configure the app ID and API key automatically:
npx croct initnpm run devOpen http://localhost:3000.
Adding Croct to an existing Storyblok + Next.js project takes three small changes — no restructuring of your content or pages required. Check the commit history to see the exact diff.
1. Wrap the Storyblok init with withCroct
// lib/storyblok.ts
import {withCroct} from '@croct/plug-storyblok/next';
export const getStoryblokApi = storyblokInit(withCroct({
accessToken: '...',
use: [apiPlugin],
components: { ... },
}));2. Add the <CroctProvider>
// app/layout.tsx
import {CroctProvider} from '@croct/plug-next/CroctProvider';
<CroctProvider>
{children}
</CroctProvider>3. Export the proxy middleware
// proxy.ts
export {proxy} from '@croct/plug-next/proxy';That's it. No extra config, no migration. Once integrated, any content managed in Storyblok becomes personalizable and ready for AB testing and personalization through Croct.
For the full integration guide, see the Storyblok SDK documentation.
The project follows a standard Next.js App Router layout. The integration-relevant parts are organized as follows:
lib/storyblok.ts— Storyblok SDK initialization wrapped withwithCroctto enable personalization on all storiesapp/layout.tsx— Root layout with<CroctProvider>and<StoryblokProvider>proxy.ts— Exports the Croct proxy middleware for server-side personalizationcomponents/blocks/— Storyblok content block components (hero, catalog, announcement bar, feature strips, etc.), each usingstoryblokEditablefor visual editing
The app tracks user behavior across the entire funnel through Croct, enabling personalization rules and analytics based on real interactions.
| Event | Trigger | Source |
|---|---|---|
cartViewed |
Page loaded | /cart |
cartModified |
Item added, removed, or updated | /cart |
checkoutStarted |
Page loaded | /checkout |
orderPlaced |
Order confirmed | /confirmation |
interestShown |
Category page viewed | /catalog/[category] |
interestShown |
Quiz answer selected | Site-wide |
leadGenerated |
Newsletter subscribed | / |
userSignedUp |
Account created | /signin |
goalCompleted |
Hero CTA clicked | / |
goalCompleted |
Announcement bar clicked | / |
goalCompleted |
Item added to cart | /product/[slug] |
goalCompleted |
Coupon redeemed | /cart |
goalCompleted |
Checkout started | /checkout |
goalCompleted |
Purchase completed | /confirmation |
goalCompleted |
Newsletter subscribed | / |
goalCompleted |
Account created | /signin |
goalCompleted |
Concierge started | Site-wide |
goalCompleted |
Concierge completed | Site-wide |
The project is ready to deploy on any platform that supports Next.js. Click the button below to deploy directly to Vercel.
Make sure to set the environment variables listed above in your hosting provider's dashboard.
For more details on the tools used in this project, refer to the official documentation: