The Contentful plugin for Amplitude Experiment enables businesses to create variations of content in Contentful, and use Experiment to control which variant users experience, and track performance of those variants.
To use the plugin, ensure you have the following:
https://app.amplitude.com/experiment/<ORG_URL>/dashboardComplete the following steps in Contentful and Amplitude to add and activate the Contentful plugin for Amplitude Experiment.
When you enable the plugin, a Variant Container content model appears on the Content Model tab.
The variant container in Contentful works with Amplitude Experiment to decide which variant of your experiment displays to each user.
For best results, Amplitude recommends you a Reference content type to hold experiments. In the Reference content type
Hero Banner or Demo CTA.After you configure the variant container and reference field, open the page on which you want to add an experiment.
Contentful returns JSON when a user requests the page.
{
"__typename": "PageLanding",
"sys": {
"id": "2cayfg7wVF5WezADCHgSgL",
"spaceId": "4y4crvvoco9a"
},
"internalName": "Homepage",
"heroBanner": {
"__typename": "VariationContainer",
"experiment": {
"id": "183980",
"key": "contentful-hero-banner",
"name": "contentful-hero-banner",
"tags": [],
"state": "running",
"deleted": false,
"enabled": true,
"endDate": null,
"decision": null,
"variants": [
{
"key": "control"
},
{
"key": "treatment"
}
],
"projectId": "289220",
"startDate": "2024-02-22",
"deployments": ["14"],
"description": "",
"bucketingKey": "amplitude_id",
"bucketingSalt": "28fWNw1M",
"bucketingUnit": "User",
"decisionReason": null,
"evaluationMode": "remote",
"experimentType": "hypothesis-testing",
"rolloutWeights": {
"control": 1,
"treatment": 1
},
"targetSegments": [],
"stickyBucketing": false,
"rolledOutVariant": null,
"rolloutPercentage": 0
},
"experimentId": "contentful-hero-banner",
"meta": {
"control": "6rmYK8YKYtTkKcFRY9Pf2w",
"treatment": "kwDjI2f2vKE2GvQoeqq1d"
},
"variationsCollection": {
"items": [
{
"__typename": "Hero",
"sys": {
"id": "6rmYK8YKYtTkKcFRY9Pf2w",
"spaceId": "4y4crvvoco9a"
},
"preHeadline": "Organic Products",
"headline": "100% Fresh Food",
"cta": "Shop Now",
"description": "Whatever you want from your local stores, brought right to your door. \t\t\t\t\t\t\t",
"image": {
"__typename": "Asset",
"sys": {
"id": "6PkraSxWWd96AU6FTYVssd"
},
"title": "Fresh food",
"description": "",
"width": 2560,
"height": 960,
"url": "https://images.ctfassets.net/4y4crvvoco9a/6PkraSxWWd96AU6FTYVssd/69b8d7f7cabb9f578097d50f2bf8aa70/Hero-3-1-scaled.jpg",
"contentType": "image/jpeg"
}
},
{
"__typename": "Hero",
"sys": {
"id": "kwDjI2f2vKE2GvQoeqq1d",
"spaceId": "4y4crvvoco9a"
},
"preHeadline": "Exclusive Offer",
"headline": "Loyalty Program",
"cta": "Get Free Shipping",
"description": "We missed you! Finish your order today and get free shipping when you join our loyalty program.",
"image": {
"__typename": "Asset",
"sys": {
"id": "6WFOK0460CwrW7aChl1QjM"
},
"title": "Loyalty Green",
"description": "",
"width": 1920,
"height": 720,
"url": "https://images.ctfassets.net/4y4crvvoco9a/6WFOK0460CwrW7aChl1QjM/e52fb2129b848203f6006ff9881309d9/Hero-_-loyalty-green.jpg",
"contentType": "image/jpeg"
}
}
]
}
}
}
The experiment object contains helpful metadata about the experiment. To render the front end and include the experiment, use the meta and variationsCollection objects. Amplitude Experiment delivers the variant identifier, and matches it to an option in the meta object. After you set the variant, you can:
variationsCollection object to show the variation with the matching ID.For more information, review the following React / Typescript example:
import React, { useEffect, useState } from 'react';
import { Experiment } from '@amplitude/experiment-js-client';
import sdk from 'contentful-sdk';
// --- Types (adjust to your schema) ---
type Hero = {
__typename: 'Hero';
sys: { id: string };
// ...other fields you render
};
type HeroBanner = {
experimentId?: string; // key you use in Amplitude Experiment
meta?: Record<string, string>; // maps variant key -> variation id
variationsCollection?: { items: Array<Hero | null | undefined> };
};
// --- Experiment init ---
const CLIENT_KEY = process.env.NEXT_PUBLIC_AMPLITUDE_EXPERIMENT_CLIENT_KEY ?? '';
export const experiment = Experiment.initialize(CLIENT_KEY, {
// Only enable verbose logging in dev if you like:
debug: process.env.NODE_ENV !== 'production',
});
// --- Component hook snippet ---
export function useHeroVariant(userId: string | undefined) {
const [hero, setHero] = useState<Hero | null>(null);
useEffect(() => {
// Skip until we have a user id
if (!userId) return;
let isMounted = true;
(async () => {
try {
// 1) Fetch variants for this user
await experiment.fetch({ user_id: userId });
// 2) Load the banner/experiment mapping from Contentful
const heroBanner = await sdk.getEntry<HeroBanner>('ENTRY_ID_HERE');
if (!heroBanner) return;
// 3) Resolve the variant key from the experiment
const experimentKey = heroBanner.experimentId ?? 'control';
const { value: variantKey } = experiment.variant(experimentKey);
if (!variantKey) return;
// 4) Map the variant key -> variation id via Contentful metadata
const variationId = heroBanner.meta?.[variantKey];
if (!variationId) return;
// 5) Find the matching Hero item
const match = heroBanner.variationsCollection?.items.find(
(item): item is Hero =>
!!item &&
item.__typename === 'Hero' &&
item.sys?.id === variationId
) ?? null;
if (isMounted) setHero(match);
} catch (err) {
// Consider forwarding to your logger
console.error('Failed to resolve hero variant', err);
if (isMounted) setHero(null);
}
})();
return () => {
isMounted = false;
};
}, [userId]); // Note: don't include heroBanner (it's local) or setHero
return hero;
}
Be sure to account for cases where users receive off as the value that experiment.variant() returns.
June 16th, 2024
Need help? Contact Support
Visit Amplitude.com
Have a look at the Amplitude Blog
Learn more at Amplitude Academy
© 2025 Amplitude, Inc. All rights reserved. Amplitude is a registered trademark of Amplitude, Inc.