Orchestrating Multiple Personalization Strategies
Splitting Traffic with Multiple Data Sources
In this recipe, we are building an blog page that includes the blog content along with a set of related blogs that the reader should be interested in reading next. We have three separate sources that can provide a list of recommended related blogs:
- Blogs belonging to the same category in our CMS
- Blogs that have been manually linked to this blog in our CMS
- Blogs that Algolia Recommend has determined using its Related Content model
We're not sure which set of recommended blogs will get the most clicks, so we're going to split the traffic between the three sources using Conscia's multivariant testing capabilities.
This same recipe can be used for product or service recommendations.
Overall Orchestration Flow
We will be using Contentful as our blog post data source, and Algolia Recommend as one source of our related blogs. When the blog page is loaded, it will call Conscia's Experience API with the article id. Conscia will return the full blog content along with the information required to generate tiles for the related posts from one of three sources.
The Orchestration consists of Connections to Contentul and to Algolia Recommend, as well as the necessary Selector and Mapper Components to get both the blog entry data as well as the information required for the related content links. Selector Components retrieve data from a Connection's endpoint, and Mapper Components map, transform, and merge those responses.
The multivariant testing is set in an Experience Rule on a Source Picker Component. The Model component will then provide the response from the appropriate Mapper Component source based on the Picker.
In order for your analytics engine of choice to get the data required to analyze the multivariant testing results, create an Orchestration Template with two Components:
- The Mapper Component that provides the full page content.
- The Picker Component that tells you which related content source has been selected.
Mapping Out DX Engine Elements
- Context: The
articleId
of the main blog entry to load is passed in through Context. - Contentful - Get Fashion Blog and Mapper - Fashion Blog: Selector and Mapper Components for the Contentful blog entry.
- Contentful - Get Fashion Blog - By Category and DTS Mapper - Fashion Blog - Contentful By Category: Selector and Mapper Components for the Contentful blogs from the same category.
- Contentful - Get Fashion Blog - Related Article Ids and Mapper - Fashion Blog - Contentful Related: Selector and Mapper Components for the Contentful blogs linked from the main blog entry.
- Algolia Recommend - Fashion Blogs - Related Content and Mapper - Fashion Blog - Algolia Recommend: Selector and Mapper Components for the Algolia Recommend selected blogs
- Article Recommendations Source: Picker Component for the user to determine which related blog source to use and/or to set up multivariant testing via Experience Rules.
- Model - Related Articles (by source): Model Component to pull the correct related blog entries based on the Picker's selection.
- Mapper - Fashion Blog - Full Page Content: Mapper Component to pull together the blog entry itself along with the related article data, everything required to render the full page content.
The Experience API request will look something like this:
POST {{engineUrl}}/experience/components/_query
X-Customer-Code: {{customerCode}}
Authorization: Bearer {{dxEngineToken}}
{
"componentCodes": ["mapper-fashionblog-fullpagecontent"],
"context": {
"articleId": "90"
}
}
The Experience API response will look something like this:
"blog": {
"title": "London Fashion Week Spring/Summer 2022: The Shows – In Pictures",
"author": "Helen Seamons, Jo Jones and Peter Bevan",
"content": "The first digital-only London Fashion Week brought together a hugely diverse series of shows and subject matter from Syrias Six Day War to Cecil Beatons Bright Young Things. From Ahluwalia to Qasimi …",
"imageUrl": ...,
"published": "2021-06-16T11:18:29Z"
},
"includes": {
"related": [
{
"title": "Elegance Redefined: Female Fashion Trends for 2023",
"articleId": "192",
"imageUrl": ...
},
{
"title": "Dapper and Suave: A Guide to Men's Fashion Suits",
"articleId": "54",
"imageUrl": ...
},
{
"title": "The Digital Runway: How Technology is Transforming Fashion Shows",
"articleId": "85",
"imageUrl": ...
}
]
}
DX Engine Configuration Details
This recipe builds on the Related Articles with Algolia Recommend recipe. You can find instructions for creating the Contentful and Algolia Connections there.
Create a Component to retrieve blog content from Contentful
- Navigate to the Experience Components page (Manage Experiences --> Components)
- Click the + Add Component button.
- Enter the following and click Submit.
Field | Value |
---|---|
Component Code | contentful-get-fashionblog |
Component Name | Contentful - Get Fashion Blog |
No Rules | Checked |
Component Type | Conscia - Universal API Connector |
The DX Engine will create and prepare the Component for further configuration. You should see the new component appear in the Component listing.
- Click Edit.
- Enter the following and click Submit.
Field | Form Tab | Value |
---|---|---|
Connection | Main | Contentful Connection |
Webservice Path | Main | Get value from: JS Expression/entries/${contextField('articleId')} |
Method | Main | GET |
Create a Component to transform blog content from Contentful
- Navigate to the Experience Components page (Manage Experiences --> Components)
- Click the + Add Component button.
- Enter the following and click Submit.
Field | Value |
---|---|
Component Code | mapper-fashionblog |
Component Name | Mapper - Fashion Blog |
No Rules | Checked |
Component Type | Conscia - Object Mapper |
The DX Engine will create and prepare the Component for further configuration. You should see the new component appear in the Component listing.
- Click Edit.
- Create an Object Map as follows and click Submit.
Field | Value |
---|---|
Source Data | Get value from: Component ResponseContentful - Get Fashion Blog |
Expression Type | JMESPath |
Schema | title = fields.title author = fields.author content = fields.content imageUrl = fields.urlToImage published = fields.publishedAt |
Create a Component to retrieve related blog content from Contentful by Category
- Navigate to the Experience Components page (Manage Experiences --> Components)
- Click the + Add Component button.
- Enter the following and click Submit.
Field | Value |
---|---|
Component Code | contentful-get-fashionblog-bycategory |
Component Name | Contentful - Get Fashion Blog - By Category |
No Rules | Checked |
Component Type | Conscia - Universal API Connector |
The DX Engine will create and prepare the Component for further configuration. You should see the new component appear in the Component listing.
- Click Edit.
- Enter the following and click Submit.
Field | Form Tab | Value |
---|---|---|
Connection | Main | Contentful Connection |
Webservice Path | Main | Get value from: Literal/entries |
Method | Main | GET |
Query Parameters | Main | Parameter: content-type Value (Literal): fashion-blog |
Query Parameters | Main | Parameter: fields.category Value (JS Expression): _.head(componentResponse('contentful-get-fashionblog-universal').fields.category) |
In the fields.category
query parameter, we're simply pulling the first category assigned to the main blog article.
Create a Component to transform related blog content from Contentful by Category
- Navigate to the Experience Components page (Manage Experiences --> Components)
- Click the + Add Component button.
- Enter the following and click Submit.
Field | Value |
---|---|
Component Code | dtsmapper-fashionblog-related-contentful-category |
Component Name | Mapper - Fashion Blog - Contentful By Category |
No Rules | Checked |
Component Type | Conscia - Data Transformation Script |
The DX Engine will create and prepare the Component for further configuration. You should see the new component appear in the Component listing.
- Click Edit.
- Create an Object Map as follows and click Submit.
Field | Value |
---|---|
Data to modify | Get value from: JS Expression_.assign({}, {"articles" : componentResponse('contentful-get-fashionblog-bycategory').items, "idToRemove" : contextField('articleId')}) |
Script |
let relatedArticles = data.articles.map((item) => ({
title: item.fields.title,
articleId: item.sys.id,
imageUrl: item.fields.urlToImage,
}));
relatedArticles.forEach( (item, index, object) => {
if (item.articleId === data.idToRemove) {
object.splice(index, 1);
}
});
const related = {"related": relatedArticles};
related;
Create a Component to retrieve related blog content ids from Contentful
- Navigate to the Experience Components page (Manage Experiences --> Components)
- Click the + Add Component button.
- Enter the following and click Submit.
Field | Value |
---|---|
Component Code | contentful-get-fashionblog-related-articleids |
Component Name | Contentful - Get Fashion Blog - Related Article Ids |
No Rules | Checked |
Component Type | Conscia - Universal API Connector |
The DX Engine will create and prepare the Component for further configuration. You should see the new component appear in the Component listing.
- Click Edit.
- Enter the following and click Submit.
Field | Form Tab | Value |
---|---|---|
Connection | Main | Contentful Connection |
Webservice Path | Main | Get value from: JS Expression/entries/${contextField('articleId')} |
Method | Main | GET |
Response Transform | Main | response.fields.relatedArticles.map(e => _.identity({id: e.sys.id})) |
Property Name | Sub Components | relatedArticleDetails |
Component Code | Sub Components | contentfulgetfashionblogrelated |
Context Field for Sub Component | Sub Components | Context Field: relatedArticleId Expression: response.id |
The Response Transform is required to provide an array to the Sub Component in order for it to iterate over the articleIds.
Create a Component to retrieve related blog details by id from Contentful
This Component is used as a Sub Component in the above configuration. For each articleId passed to it from the base Component's response array, it will retrieve the blog details required to generate a tile for related content. The entire set will be returned in a single response in a property called relatedArticleDetails
embedded in the base Component's response.
- Navigate to the Experience Components page (Manage Experiences --> Components)
- Click the + Add Component button.
- Enter the following and click Submit.
Field | Value |
---|---|
Component Code | contentfulgetfashionblogrelated |
Component Name | Contentful - Get Fashion Blog - Related Article Detail |
No Rules | Checked |
Component Type | Conscia - Universal API Connector |
The DX Engine will create and prepare the Component for further configuration. You should see the new component appear in the Component listing.
- Click Edit.
- Enter the following and click Submit.
Field | Form Tab | Value |
---|---|---|
Connection | Main | Contentful Connection |
Webservice Path | Main | Get value from: JS Expression/entries/${contextField('relatedArticleId')} |
Method | Main | GET |
Response Transform | Main | _.assign({'title': response.fields.title, 'articleId': response.sys.id, 'imageUrl': response.fields.urlToImage}) |
The Response Transform is used in lieu of a separate mapper Component to map and transform just the required properties.
Create a Component to transform related blog content from Contentful
- Navigate to the Experience Components page (Manage Experiences --> Components)
- Click the + Add Component button.
- Enter the following and click Submit.
Field | Value |
---|---|
Component Code | mapper-fashionblog-related-contentful |
Component Name | Mapper - Fashion Blog - Contentful Related |
No Rules | Checked |
Component Type | Conscia - Object Mapper |
The DX Engine will create and prepare the Component for further configuration. You should see the new component appear in the Component listing.
- Click Edit.
- Create an Object Map as follows and click Submit.
Field | Value |
---|---|
Source Data | Get value from: Component ResponseContentful - Get Fashion Blog - Related Article Ids |
Expression Type | JMESPath |
Source Array Property Path | $ |
Target Property Path for modified array | related |
Schema | title = relatedArticleDetails.contentfulgetfashionblogrelated.response.title articleId = relatedArticleDetails.contentfulgetfashionblogrelated.response.articleId imageUrl = relatedArticleDetails.contentfulgetfashionblogrelated.response.imageUrl |
Response Transform | _.assign({}, {"related" : response}) |
Create a Component to retrieve related articles from Algolia Recommend
- Navigate to the Experience Components page (Manage Experiences --> Components)
- Click the + Add Component button.
- Enter the following and click Submit:
Field | Value |
---|---|
Component Code | algolia-recommend-fashionblogs-related |
Component Name | Algolia Recommend - Fashion Blog - Related Content |
No Rules | Checked |
Component Type | Conscia - Universal API Connector |
The DX Engine will create and prepare the Component for further configuration. You should see the new component appear in the Component listing.
- Click Edit.
- Enter the following and click Submit.
Field | Form Tab | Value |
---|---|---|
Connection | Main | Algolia Recommend Connection |
Webservice Path | Main | Get value from: Literal/1/indexes/*/recommendations |
Method | Main | POST |
Body | Main | Get value from: JS Expression |
{
"requests": [
{
"indexName": "{index to target}",
"model": "related-products",
"threshold": 45,
"maxRecommendations": 3,
"objectID": "${contextField('articleId')}"
}
]
}
Create a Component to transform related articles from Algolia Recommend
- Navigate to the Experience Components page (Manage Experiences --> Components)
- Click the + Add Component button.
- Enter the following and click Submit.
Field | Value |
---|---|
Component Code | mapper-fashionblog-related-algolia |
Component Name | Mapper - Fashion Blog - Algolia Recommend |
No Rules | Checked |
Component Type | Conscia - Object Mapper |
The DX Engine will create and prepare the Component for further configuration. You should see the new component appear in the Component listing.
- Click Edit.
- Create an Object Map as follows and click Submit.
Field | Value |
---|---|
Source Data | Get value from: Component ResponseAlgolia Recommend - Fashion Blog - Related Content |
Expression Type | JMESPath |
Source Array Property Path | results[0].hits |
Target Property Path for modified array | related |
Schema | title = title articleId = article_id imageUrl = urlToImage |
Create a Component to allow users to select source for related content
- Navigate to the Experience Components page (Manage Experiences --> Components)
- Click the + Add Component button.
- Enter the following and click Submit.
Field | Value |
---|---|
Component Code | related-content-source |
Component Name | Fashion Blog - Related Content Source |
No Rules | Checked |
Component Type | Conscia - Metadata |
Create an Experience Rule to split traffic for related content
- Navigate to the Omnichannel Experience Rules page (Manage Experiences --> Experience).
- Navigate to your Fashion Blog - Related Content Source Component under All Components.
- Click the + Add Experience Rule button.
- Enter the following and click Submit.
Field | Form Tab | Value |
---|---|---|
Rule ID | Main | split-traffic |
Rule Name | Main | Split Traffic |
Priority | Main | 1 |
Is Default | Main | Checked |
Enable A/B Test | Main | Checked |
A/B Test Configuration: Stickiness | Main | Your choice: visitor / session |
Field | Form Tab | Value |
---|---|---|
Active | Experience | Checked |
Dates | Experience | Optional |
- Under Target Experience, add three Weighted Configurations then click Submit.
Field | Value |
---|---|
Control Group | Checked |
Relative Weight | 33 |
Variant Identifier | By Category |
Instructions | Key: recommendationsType Value: Articles by Category |
Field | Value |
---|---|
Control Group | Not Checked |
Relative Weight | 33 |
Variant Identifier | Related |
Instructions | Key: recommendationsType Value: Related Articles from Contentful |
Field | Value |
---|---|
Control Group | Not Checked |
Relative Weight | 34 |
Variant Identifier | Algolia Recommend |
Instructions | Key: recommendationsType Value: Algolia Recommendations |
In this recipe weight is distributed equally across all three options.
Create a Component to select related content
- Navigate to the Experience Components page (Manage Experiences --> Components)
- Click the + Add Component button.
- Enter the following and click Submit.
Field | Value |
---|---|
Component Code | model-related-content |
Component Name | Model - Fashion Blog - Related Content (by source) |
No Rules | Checked |
Component Type | Conscia - Metadata |
The DX Engine will create and prepare the Component for further configuration. You should see the new component appear in the Component listing.
- Click Edit.
- Add the Response Transform expression as follows and click Submit.
Field | Value |
---|---|
Response Transform |
componentResponse('recommendations-source').recommendationsType[0] === 'Algolia Recommendations' ? componentResponse('mapper-fashionblog-related-algolia') : componentResponse('recommendations-source').recommendationsType[0] === 'Related Articles from Contentful' ? componentResponse('mapper-fashionblog-related-contentful') : componentResponse('recommendations-source').recommendationsType[0] === 'Articles by Category' ? componentResponse('dtsmapper-fashionblog-related-contentful-category') : {}
Create a Component to merge blog and related content data
- Navigate to the Experience Components page (Manage Experiences --> Components)
- Click the + Add Component button.
- Enter the following and click Submit:
Field | Value |
---|---|
Component Code | mapper-fashionblog-fullpagecontent |
Component Name | Mapper - Fashion Blog - Full Page Content |
No Rules | Checked |
Component Type | Conscia - Property Mapper |
The DX Engine will create and prepare the Component for further configuration. You should see the new component appear in the Component listing.
- Click Edit.
- Create two Property Maps as follows and click Submit.
Field | Value |
---|---|
Source Data | Get value from: Component ResponseMapper - Fashion Blog |
Expression Type | Javascript |
Mappings | Target property: blog Source expression: data |
Field | Value |
---|---|
Source Data | Get value from: Component ResponseModel - Fashion Blog - Related Content (by source) |
Expression Type | javascript |
Mappings | Target property: includes Source expression: data |