Note: Refer to this documentation if you are using Wingify's Feature Experimentation app to manage content variations in Contentful. If you're looking to perform standard A/B testing with Wingify Feature Experimentation and Contentful without feature flag functionality, please refer to this documentation, which uses Wingify's Feature Experimentation SDK for content experimentation.
This article covers the following:
- Overview
- Before You Begin
- Create a Contentful Connection in Wingify
- Install Wingify App in Contentful and Create Variations' Content
- Configure the Feature Flag Inside Wingify to Run Test and Personalization Campaigns
- Use Wingify Feature Experimentation SDK for Filtering the Content
- Troubleshooting
- Best Practices
- FAQs
Overview
Wingify integration with Contentful using Feature Flags in Feature Experimentation simplifies content testing and personalization. By linking Wingify with Contentful, you can manage content variations using feature flags, ensuring the right content is shown to different user segments. This integration automates the synchronization of these variations between Contentful and Wingify, streamlining the A/B testing process, minimizing manual setup, and making content experimentation more efficient and effective.
Before You Begin
- Ensure you have active accounts with both Wingify and Contentful.
- Install the Wingify - Feature Experimentation app from the Contentful Marketplace.
Create a Contentful Connection in Wingify
To create the Wingify-Contentful connection for your Wingify account:
- Log in to your Wingify account.
- From the left panel, navigate to Configurations > Integrations.
- Click the Contentful integration tile and click Create Connection.
- Enter a name in the Connection Name field.
- Enter your Contentful Auth Token in the Auth Token field.
- Click Create Connection.
Once enabled, you will get to see the auth token for enabling this integration in Contentful.
ATTENTION: This token will be visible only once and cannot be accessed later. Hence, you can copy this token and paste it elsewhere for use when setting up the integration in Contentful.
Install Wingify App in Contentful and Create Variations’ Content
To install the Wingify app in Contentful and create content for your variations:
1. Install the Wingify - Feature Experimentation: Use this link to install the Wingify - Feature Experimentation app in Contentful. Enter your Wingify Account ID and API Key which you have copied in the previous step.
2. Navigate to Contentful Entry: Go to the Content section in Contentful and open the entry you want to test. For example, the Agency Home Page as shown in the below screenshot.
3. Replace Existing Content with VWO Feature Experimentation Wrapper: Remove the existing content section you wish to test and click + Add content. Select VWO Feature Experimentation Wrapper from the dropdown.
4. Create Feature Flag: Within the VWO Feature Experimentation Wrapper, create a new feature flag. Give the feature flag a descriptive name (e.g., Hero Section Content).
5. Set Default (Control) Variation: Link the original content you removed in step 3 as the default (Control) variation.
6. Create Variations: Click Add Variation to create new variations for your test. Give each variation a descriptive name (e.g., Variation-1, Variation-2). Create the content for each variation within Contentful.
7. Publish Changes in Contentful: Publish the changes to your Contentful entry. This will automatically synchronize the variations and variable data with Wingify.
Configure the Feature Flag Inside Wingify to Run Test and Personalization campaigns
After doing the necessary configurations inside Contentful, you can switch to Wingify to set up the campaign parameters like metrics, audience targeting, and other settings.
1. Configure Wingify Feature Flag: Access the feature flag in Wingify to add metrics, integrations, or further refine settings.
2. Create Testing Rule in Wingify: Go to the Rules section and create a new A/B testing rule. Select the variations you want to test and define the traffic allocation.
3. Activate the rule
Use Wingify Feature Experimentation SDK for Filtering the Content
Once you have published your content, the Contentful API returns data in the following format:
{
"sys": {
"space": {
"sys": {
"type": "Link",
"linkType": "Space",
"id": "eux74tkyi6"
}
},
"id": "35kjlsbp234sdickjh4koijkj",
"type": "Entry",
"createdAt": "2024-11-18T07:35:50.761Z",
"updatedAt": "2024-11-18T07:52:31.421Z",
"environment": {
"sys": {
"id": "master",
"type": "Link",
"linkType": "Environment"
}
},
"publishedVersion": 15,
"revision": 4,
"contentType": {
"sys": {
"type": "Link",
"linkType": "ContentType",
"id": "variationFmeContainer"
}
},
"locale": "en-US"
},
"fields": {
"title": "Testing hero section",
"meta": {
"1": "34A1uFceIaHg8QrjbU1234",
"2": "5MRl1T8TpttvcpkuNg1234",
"3": "2h07aeAdahQmF2Jklr1234"
},
"featureFlag": {
"id": 91,
"name": "Testing hero section",
"accountId": 123456,
"createdOn": 1731915289,
"modifiedOn": 1731915313,
"createdBy": {
"name": "FME Account",
"imageUrl": "//gravatar.com/avatar?s=24&d=https%3A%2F%2Fapp.vwo.com%2Fassets%2Fimage%2Favatar-3.png"
},
"featureKey": "contentful_7WB9rp7MBmj7wBzcD1vq7G",
"description": "testing app e2e ",
"version": 2,
"featureType": "PERMANENT",
"variables": [
{
"id": 1,
"variableName": "vwoContentful",
"dataType": "string",
"defaultValue": "34A1uFceIaHg8QrjbU1234"
}
],
"variations": [
{
"id": 3,
"name": "Variation-2",
"key": "3",
"createdAt": "2024-11-18 07:35:30",
"jsonContent": [
{
"variableId": 1,
"value": "2h07aeAdahQmF2Jklr1234"
}
]
},
{
"id": 2,
"name": "Variation-1",
"key": "2",
"createdAt": "2024-11-18 07:35:17",
"jsonContent": [
{
"variableId": 1,
"value": "5MRl1T8TpttvcpkuNg1234"
}
]
},
{
"id": 1,
"name": "Default",
"key": "default",
"createdAt": "2024-11-18 07:34:49",
"jsonContent": [
{
"variableId": 1,
"value": "34A1uFceIaHg8QrjbU1234"
}
]
}
],
"type": "feature-flag"
}
}
}
Integrating Wingify SDK to Display Contentful Variations: Add the provided custom code snippet to your website to integrate the Wingify SDK. This code will fetch the correct variation for each user and display the corresponding content from Contentful.
Example of Node SDK:
import { init } from 'vwo-fme-node-sdk';
import { createClient } from 'contentful';
const fmeClient = await init({
accountId: '123456', // Enter VWO account ID here
sdkKey: '' // You can find sdkKey in feature flag > Rules > Environments
});
// You can find spaceID and accessToken in Settings > API keys. If you don't have one, create one on clicking 'Add API key' under Settings > API keys
const contentfulClient = contentful.createClient({
space: 'spaceID',
accessToken: 'accessToken'
});
// Replace your_flag_id with your Feature flag id
// You can find it in Feature flag > Configuration > Settings > Key
// Find more about userContext here
const flag = await fmeClient.getFlag('your_flag_id', userContext);
// Always use vwoContentful as variable name
const variationToBeServed = flag.getVariable('vwoContentful'); // entryId => '6hDfbnInEpiab896VpBueJ'
// Fetch the entry using variationToBeServed as an entryId and display the content
const contentToBeDisplayed = await contentfulClient.getEntry(variationToBeServed);Example For Android mobile applications -
Kotlin:
fun init(){
val vwoInitOptions = VWOInitOptions()
vwoInitOptions.sdkKey = SDK_KEY
vwoInitOptions.accountId = ACCOUNT_ID
vwoInitOptions.context = context
VWO.init(vwoInitOptions, object : IVwoInitCallback {
override fun vwoInitSuccess(vwo: VWO, message: String) {
this@SdkManager.vwo = vwo
initContentfulApp()
}
override fun vwoInitFailed(message: String) {
//log the error
}
}
}
private fun contentfulApp(): Boolean {
val contentfulCDAClient = CDAClient.builder()
.setSpace(spaceKey)
.setToken(accessToken)
.build()
val entry: CDAEntry? = contentfulCDAClient?.fetch(CDAEntry::class.java)
?.include(3)
?.where("sys.id", contentId)?.one(contentId)
val heroSection =
entry?.getField<CDAEntry>("vwoContentful")?.getField<Map<Any, Any>>("featureFlag")
val hero = heroSection?.get("featureKey") as? String
vwo?.getFlag(hero, userContext, object : IVwoListener {
override fun onSuccess(data: Any) {
featureFlag = data as? GetFlag
val isFeatureFlagEnabled = featureFlag?.isEnabled()
val variable2 = featureFlag.getVariable(variableName,"default-value")
val contentToBeShown = contentfulCDAClient?.fetch(CDAEntry::class.java)
?.include(3)
?.where("sys.id", variable)?.one(variable)
}
override fun onFailure(message: String) {
//log the error
}
})
}Java:
public void init() {
VWOInitOptions vwoInitOptions = new VWOInitOptions();
vwoInitOptions.setSdkKey(SDK_KEY);
vwoInitOptions.setAccountId(ACCOUNT_ID);
vwoInitOptions.setContext(context);
VWO.init(vwoInitOptions, new IVwoInitCallback() {
@Override
public void vwoInitSuccess(WWO vwo, String message) {
SdkManager.this.vwo = vwo;
initContentfulApp();
}
@Override
public void vwoInitFailed(String message) {
// Log the error
}
});
}
private void initContentfulApp() {
CDAClient contentfulCDAClient = CDAClient.builder()
.setSpace(spaceKey)
.setToken(accessToken)
.build();
CDAEntry entry = contentfulCDAClient.fetch(CDAEntry.class)
.include(3)
.where("sys.id", contentId)
.one(contentId);
if (entry != null) {
Map<String, Object> heroSection = entry.getField("vwoContentful");
if (heroSection != null) {
Map<String, Object> featureFlagData = (Map<String, Object>) heroSection.get("featureFlag");
if (featureFlagData != null) {
String hero = (String) featureFlagData.get("featureKey");
vwo.getFlag(hero, userContext, new IVwoListener() {
@Override
public void onSuccess(Object data) {
featureFlag = (GetFlag) data;
if (featureFlag != null) {
boolean isFeatureFlagEnabled = featureFlag.isEnabled();
String variable2 = featureFlag.getVariable(variableName, "default-value");
// Fetch additional content based on variable
CDAEntry additionalContent = contentfulCDAClient.fetch(CDAEntry.class)
.include(3)
.where("sys.id", variable)
.one(variable);
}
}
@Override
public void onFailure(String message) {
// Log the error
}
});
}
}
}
}Troubleshooting
If you encounter issues while implementing the Wingify-Contentful integration, here are some common problems and their solutions:
- Variations Not Showing: Verify that the feature flag is enabled in both Contentful and Wingify. Check the Wingify SDK implementation on your website for any errors.
- Synchronization Issues: Ensure that the Wingify Feature Experimentation app in Contentful is correctly configured with your Account ID and API Key.
- Content Not Updating: Confirm that you have published the changes in Contentful after creating or modifying variations.
If the steps mentioned above do not solve the issue, reach out to support@wingify.com.
Best Practices
- Use descriptive names for feature flags and variations to maintain clarity.
- Regularly monitor the performance of your variations in Wingify to identify winning strategies.
FAQs
- Can I use existing Contentful content for variations? Yes, you can link existing Contentful entries as variations within the Wingify Feature Experimentation Wrapper.
- What happens if I delete a feature flag in Contentful? Deleting a feature flag in Contentful will not automatically delete it in Wingify. You will need to manually delete it in Wingify if required.
- Can I personalize content based on user attributes? Yes, you can create personalization rules in Wingify to target specific user segments based on various attributes.
Need more help?
For more information or further assistance, contact Wingify Support.