A/B testing has become essential for modern web applications, helping teams optimize user experience and increase conversion rates through data-driven decisions. dotCMS provides a powerful experiments feature that integrates seamlessly with headless applications through the @dotcms/experiments library.
To demonstrate what we'll be building, watch how experiments work in a real dotCMS headless application:
IMAGE VARIANT A
IMAGE VARIANT B
The dotCMS experiments library enables seamless A/B testing where:
Users are automatically directed to different variants of your pages
The experience remains consistent throughout their session
All interactions are tracked automatically for analysis
In this guide, we'll walk through how to implement this functionality in your own headless application.
Prerequisites
Before starting this integration, ensure you have:
A running dotCMS instance with Analytics and Experiments properly configured
An Analytics API Key (contact your dotCMS administrator if you don't have one)
A headless application (React/Next.js)
Solution Introduction
dotCMS's @dotcms/experiments library simplifies A/B testing in headless applications by providing a Higher-Order Component approach. This design choice is particularly powerful because it allows the experiments functionality to wrap around your existing components without requiring significant changes to your application's structure. The library handles all the complex aspects of A/B testing, from user assignment to analytics tracking, while maintaining the performance and flexibility that headless architectures are known for.
Step-by-Step Guide
1. Understanding the Example Project
Let's examine our official example that demonstrates how to build a headless application using Next.js integrated with dotCMS. This example showcases the best practices for implementing experiments in a real-world headless architecture:
# Clone the dotCMS repository
git clone https://github.com/dotCMS/core.git
cd core/examples/nextjs
# Install dependencies
npm install
# Start the development
server npm run dev
This example provides a complete implementation that you can use as a reference. The most important file for our experiments integration is located at /src/components/my-page.js. This file contains the pre-configured setup for experiments and demonstrates how to integrate them with dotCMS, which will be discussed below.
2. Setting Up the Integration
The integration process begins with installing the experiments library:
npm install @dotcms/experiments
Next, you'll need to set up your environment variables. Create an .env.local file in the root of your project and add the following variables:
# .env.local
NEXT_PUBLIC_EXPERIMENTS_API_KEY=your-api-key-here
NEXT_PUBLIC_DOTCMS_HOST=https://your-dotcms-instance.com
NEXT_PUBLIC_EXPERIMENTS_DEBUG=true # Optional, set to true for detailed logging
Once installed, navigate to your main page component. In our example, this is the aforementioned /src/components/my-page.js. Here you'll find the experiments configuration already set up:
const experimentConfig = {
apiKey: process.env.NEXT_PUBLIC_EXPERIMENTS_API_KEY,
server: process.env.NEXT_PUBLIC_DOTCMS_HOST,
debug: process.env.NEXT_PUBLIC_EXPERIMENTS_DEBUG
};
These environment variables are crucial for the experiments functionality:
NEXT_PUBLIC_EXPERIMENTS_API_KEY: Your Analytics API key for authentication
NEXT_PUBLIC_DOTCMS_HOST: The URL of your dotCMS instance
NEXT_PUBLIC_EXPERIMENTS_DEBUG: Optional flag to enable detailed logging
Remember that the .env.local file should never be committed to your repository as it contains sensitive information. Make sure it's included in your .gitignore file!
3. Implementing the HOC Pattern
The core of the integration lies in how we wrap our layout component with the experiments functionality:
import { withExperiments } from "@dotcms/experiments";
import { useRouter } from 'next/router';
const experimentConfig = {
apiKey: process.env.NEXT_PUBLIC_EXPERIMENTS_API_KEY,
server: process.env.NEXT_PUBLIC_DOTCMS_HOST,
debug: process.env.NEXT_PUBLIC_EXPERIMENTS_DEBUG
};
function MyPage({ pageAsset, nav }) {
const { replace } = useRouter();
// Conditional wrapping based on API key presence
const DotLayoutComponent = experimentConfig?.apiKey
? withExperiments(DotcmsLayout, {
...experimentConfig,
redirectFn: replace, // Provide navigation function
})
: DotcmsLayout;
...
....
return (
<DotLayoutComponent>
<Component {...pageProps} />
</DotLayoutComponent>
);
}
Let's break down what's happening here:
Configuration Setup: The experimentConfig object contains essential information:
apiKey: Authenticates requests to dotCMS Analytics
server: Specifies your dotCMS instance URL
Conditional Wrapping: We only apply the experiments wrapper when an API key is present. This approach:
Enables easy development without experiments
Prevents unnecessary API calls in development
Allows graceful fallback if configuration is missing
Navigation Integration: The redirectFn property receives Next.js's router replace function, allowing the experiments library to handle redirects seamlessly when users need to be shown different variants.
4. Running and Testing Your Implementation
After setting up your environment variables and implementing the HOC, you can start your development server:
npm run dev
Your application will now start with experiments enabled. You can verify the integration is working by:
Checking your browser's console for experiment-related logs (if debug mode, mentioned above, is enabled)
Visiting pages with active experiments to see variant assignments
Monitoring your dotCMS Experiment dashboard for incoming pageview data
How It Works Behind the Scenes
When a user visits your application, the experiments integration performs several important tasks:
User Assignment The library first checks if the user has been assigned to any experiment variants. This check happens automatically and uses browser storage to maintain consistency across sessions.
Variant Management If the user needs to see a specific variant, the library handles this through the provided redirectFn. This ensures users consistently see the same variant throughout their session, which is crucial for gathering reliable test data.
Analytics Integration Every pageview is automatically tracked and sent to dotCMS Analytics, providing you with data about how different variants are performing.
Key Benefits
Seamless Integration: The HOC pattern allows for non-invasive integration with existing applications
Performance Optimized: Conditional wrapping ensures experiments only run when needed
Automatic Handling: User assignment and tracking happen without manual intervention
Flexible Implementation: Works with any React-based application, with special optimization for Next.js
Conclusion
The @dotcms/experiments library provides a sophisticated yet straightforward way to implement A/B testing in headless applications. By using the HOC pattern and handling complex operations automatically, it allows developers to focus on creating and testing content variants rather than worrying about the implementation details of A/B testing.