In the previous part of this blog series, we took a step by step approach to integrating Amplience and Dynamic Yield to deliver A/B testing in a headless architecture. This article picks up where the last one left off and shows you how to implement content targeting capabilities using content managed by Amplience. We’ll take a look at two different integration patterns: using Dynamic Content delivery keys and slots, so you can choose the approach that suits you best.
I will assume that you already have the environment set up, including the content variants, we created in the previous post.
You will learn how to:
Use keys as user friendly alternatives to IDs for associating content items to Dynamic Yield campaigns
Use slots that map to Dynamic Yield campaigns
Join Amplience and Dynamic Yield to deliver content targeted at audiences
Content targeting with Amplience and Dynamic Yield using Dynamic Content Delivery Keys
A delivery key is a unique name given to a piece of content in the Amplience Headless CMS that can be used to retrieve the content by the live content delivery service. This feature enables business users to themselves create a human readable ID to retrieve the content ,simplifies the process and can be used to facilitate more seamless integrations through naming conventions.
Setup the audiences in Dynamic Yield
Building on the Dynamic Yield Pet shop tutorial from the last blog post, add a new audience for those die-hard canine lovin' users who've added dog-related products to cart over the last month. Set the condition to “Products added to cart” and the category to “Dogs” as shown below.
Create a targeted Dynamic Yield Campaign
We will set up a new campaign in Dynamic Yield which will choose a home page banner depending on the audience.
Create a new customer API campaign
Name the campaign HP Banner
Change the selector name to HP-Banner (this is the name that is used in the code and will later be used to identify the Amplience key to retrieve our banner – spaces are not acceptable)
Click Next and next again to create an experience for all users
Select the "Amplience Content" template – we will reuse the content variant template from the previous post.
Name the variant "pet promo"
In the variant form enter pet-promo for the Amplience_ID . This variant will be used to get the generic pet promotion banner for non-targeted audiences
Click save
Name the experience Default and save
We now have a campaign with a default experience for targeting non targeted customers. Let’s add the experiences for targeting dog and cat lovers.
Above the default experience click the + icon to create a new experience and name it dog lovers
Under who select Audience and then select belongs to "‘added dog product to cart"
Click save and create a new variation using the Amplience Content template
Name the variant dog promo and give it an Amplience_ID value of dog-promo
Click Save Variation and then Save Experience
Now let’s do the same for targeting cat lovers. Above the dog lover experience click the + icon to create a new experience and name it cat lovers
Under who select Audience and then select belongs to ‘added cat product to cart’
Click save and create a new variation using the Amplience Content template
Name the Variant cat promo and give it an Amplience_ID value of cat-promo
- Click Save Variation and then Save Experience
We now have a campaign with a default experience and targeted experiences for dog and cat lovers.
Setting the content delivery keys in Amplience
For this example I’m going to use a very simple naming convention to map content in Amplience to Dynamic Yield API campaigns and variations. This method should be simpler than using machine generated IDs for business users. We will define the pattern for the content key value for content in two parts, the Dynamic Yield campaign selector and the Amplience_ID value held in the variation, separated by a hyphen.
Pattern
campaign selector- Amplience_ID
Values
HP-Banner-pet-promo
HP-Banner-dog-promo
HP-Banner-cat-promo
To add these keys to the content in Amplience:
- Open Amplience Dynamic Content headless CMS and go to the repository you used to create your content variants in the previous post.
Enter HP-Banner-dog-promo and click Save
Follow the same steps for the cat gift promotion setting the key to HP-Banner-cat-promo
Follow the same steps for the pet gift promotion setting the key to HP-Banner-pet-promo
Publish each content item to push the content with its new delivery key to the live content delivery service
Integrating the Amplience and Dynamic Yield server-side code
We now have a new Dynamic Yield campaign setup up to target dog and cat lovers with different experiences that reference content in Amplience. We have content set with delivery keys so they can be retrieved from the live content delivery API using a key matching the pattern of our Dynamic Yield campaign and variations. Now let’s change the server-side code from the previous post to retrieve the new campaign for the homepage hero and use the content key to retrieve Amplience content.
First we need to create a new function in the amplienceAPI.js file we created in the previous post to retrieve content by its key
Open amplienceAPI.js in your favourite IDE
Copy and paste the function below which takes the key as a parameter, calls the Amplience API with this key and returns a JSON object formatted to work with the Pet Shop tutorial. We discussed this in the previous post.
1// Retrieve content using its ID 2async function getContentItemByKey(contentKey) { 3 let variant = {}; 4 try{ 5 const response = await client.getContentItemByKey(contentKey); 6 variant= response.body; 7 //build a dynamic image URL from the JSON 8 variant.image = response.body.image.url().build();; 9 console.log("Amplience content variant: "+JSON.stringify(variant)); 10 }catch(error){ 11 console.log('Amplience content not found', error); 12 } 13 return variant; 14} 15 16module.exports = { 17 getContentItemById, 18 getContentItemByKey 19};
The next step is to wire together the new campaign. We need to make some changes to the homepage handler to fetch Amplience content using its key.
- Open
Change the value in the1routes/homepage.js
in the1DYAPI.choose
function to call the 'HP-Banner’ campaign we have just setup1getPageContent
1const apiResponse = await DYAPI.choose(req.userId, req.sessionId, req.dyContext, ['HP-Banner']);
- Make a new const to hold our Amplience Key formed from the campaign selector and the Amplience_ID returned from the choose call.
1const amplienceKey = 'HP-Banner-' + apiResponse['HP-Banner'].amplienceID;
- Change the Amplience call to get content using its key
1const amplienceResponse = await AmplienceAPI.getContentItemByKey(amplienceKey);
The new getPageContent function will look something like this:
1async function getPageContent(req) { 2 req.dyContext.page.type = 'HOMEPAGE'; 3 4//CHANGES 5 const apiResponse = await DYAPI.choose(req.userId, req.sessionId, req.dyContext, 6 ['HP-Banner']); 7 const amplienceKey = 'HP-Banner-' + apiResponse['HP-Banner'].amplienceID; 8 const amplienceResponse = await AmplienceAPI.getContentItemByKey(amplienceKey); 9//END CHANGES 10 11 const content = { 12 heroBanner: amplienceResponse || defaultHeroBanner, // <== Here! 13 recommendations: defaultRecommendations, 14 }; 15 if (req.originalUrl.includes('SALE')) { 16 content.overlay = defaultOverlay; 17 } 18 return content; 19}
That’s it. We are all ready to target content to specific audiences: pet, dog and cat lovers.
- Open a browser and navigate to http://localhost:3000
The homepage banner looks something like this:
Scroll down the page and click on a crazy cat product
Add the product to the basket and return to the homepage.
The homepage banner now looks something like this:
- To get the result for dog lovers, open a new browser window in incognito mode and follow the same process adding dog products. You will be presented with the dog lovers banner like this one:
Content targeting with Amplience and Dynamic Yield using Dynamic Content Slots
So far, we have used Dynamic Yield campaigns to decide at a granular level which item of content to display by referencing Amplience content using its machine generated content ID, or a user defined delivery key. The latter facilitates an approach using naming convention to tie both systems together, and although this is easy for business users to understand, it’s more prone to error. Another approach is to model the Dynamic Yield campaign in Amplience as a slot or series of slots. A slot in Amplience is a specialized piece of content that’s purpose is to represent an area in your user experience where you would like to place content.
As with any item of Amplience content, a slot is defined using JSON Schema. This gives slots the flexibility to be a simple structure that references an item of content, or a more sophisticated structure that references multiple pieces of content, and can even have its own content managed attributes.
For this example, we will create a slot that contains a list of objects with a placeholder for content and a field for what you want to target. Business users can add the three banners we created earlier and associate them to the target audience defined in Dynamic Yield. During a live request, our server side code will get the target from Dynamic Yield and use it to decide which piece of content to use in the slot.
To keep things simple, we will reuse and won’t change the Dynamic Yield Campaign or the content items we have already created.
Create an Amplience slot for content targeting
First of all we need to create a new content type to represent a slot for the homepage banner. We basically want the slot to deliver the follow JSON structure which represents the Dynamic Yield Campaign, which looks something like this:
1{ experiences:[ 2 {content:”…”,target:”dog-promo”}, 3 {content:”…”,target:”cat-promo”}, 4 {content:”…”,target:”pet-promo”} 5 ] 6}
To do this In Amplience Dynamic Content you need to follow these steps
Select the Development tab and click content schemas and then click the Create Schema button.
Select code from scratch
Enter a name for your slot schema. For this example I used https://example.amplience.com/dy-slot
Set the validation level to Slot and click Create schema
1 "properties": { 2 "experiences": { 3 "title": "Dynamic Yield Targeted Experience", 4 "description": "description", 5 "type": "array", 6 "minItems": 1, 7 "maxItems": 10, 8 "items": { 9 "title": "Dynamic Yield Targeted Experience", 10 "type": "object", 11 "properties": { 12 "target": { 13 "title": "target", 14 "description": "The target name passed from dynamic yield", 15 "type": "string", 16 "minLength": 0, 17 "maxLength": 250 18 }, 19 "content": { 20 "title": "content", 21 "allOf": [ 22 { "$ref": "http://bigcontent.io/cms/schema/v1/core#/definitions/content-link" }, 23 { 24 "properties": { 25 "contentType": { 26 "enum": [ 27 "http://example.amplience.com/DY-Banner" 28 ] 29 } 30 } 31 } 32 ] 33 } 34 35 }, 36 "propertyOrder": ["target","content"] 37 } 38 } 39 }
What this JSON schema does is as follows
It defines an experiences property of type array, which will hold a list of JSON objects.
Then we define the structure of object that can be contained in the array.
It has two properties: a content link and target.
The content link allows business users to add content items created with a DY-Banner schema
The target string allows business users to enter the target value that will be passed from Dynamic Yield and associated to the content.
Once the schema is complete Save and register it as a content type.
A content schema defines the shape of the JSON object, but a content type allows the schema to be used by business users in the Amplience Headless CMS.\ To complete the content type, simply give it a name (e.g. Dynamic Yield Slot Example) and assign it to the slot repository where you want business users to create slots for this demo.
Setup the Slot in Amplience for Dynamic Yield Personalization and targeting
For this demo we are going to setup a single slot to represent the area on the homepage where the banner lives. To do this go to the repository which has the Dynamic Yield Slot Example Content Type enabled and click the Create content button. You will be presented with a dialog showing all the content types you have created. Select the Dynamic Yield Slot Example content type.
The slot content form will start with one Dynamic Yield Targeted Experience to complete. We will complete this and add two additional ones to cover all the target variations.
In the target field enter dog-promo – this is the target we will receive from the Dynamic Yield campaign
Click the big + in the content field and choose the dog gift promotion content item we created previously
Now click the Add Dynamic Yield Targeted Experiences button
In the target field enter cat-promo. This is the target we will receive from the Dynamic Yield campaign
Click the big + in the content field and choose the dog gift promotion content item we created previously
Now click the Add Dynamic Yield Targeted Experiences button again
In the target field enter pet-promo. This is the target we will receive from the Dynamic Yield campaign
Click the big + in the content field and choose the pet gift promotion content item we created previously
The slot configuration should look something like this:
When you’ve finished click Save
One final step to complete the slot setup is to click the blue dropdown on the top right and select delivery key. Enter the delivery key as hp-banner.
Integrating the Amplience Slot and Dynamic Yield server-side code
To integrate the Amplience slot we configured with fields to map to Dynamic Yield targets, we will create a new Amplience API helper function that will retrieve the slot configuration from the Amplience Content Delivery service, and then extract the content from the slot that matches the target sent by Dynamic Yield.
To demonstrate the principles of how this works we will keep things simple by keeping the API calls in sequence. An advantage of this approach is it can be optimised to make the Amplience and Dynamic Yield calls in parallel.
Let’s start by creating our new function in the amplienceAPI.js file to get a slot using a delivery key and choose the content from the slot based on its Dynamic Yield target.
Open amplienceAPI.js in your favourite IDE
Copy and paste the function below. This takes the key as a parameter, calls the Amplience API with this key and returns a JSON object formatted to work with the Pet Shop tutorial.
1async function getContentFromSlotByKeyAndTarget(contentKey,target) { 2 let variant = {}; 3 try{ 4 const response = await client.getContentItemByKey(contentKey); 5 //get content item matching the dy target 6 variant= response.body.experiences.filter(item => item.target==target)[0].content; 7 //build a dynamic image URL from the JSON 8 variant.image = variant.image.url().build(); 9 console.log("Amplience content variant: "+JSON.stringify(variant)); 10 }catch(error){ 11 console.log('Amplience content not found', error); 12 } 13 return variant; 14} 15 16module.exports = { 17 getContentItemById, 18 getContentItemByKey, 19 getContentFromSlotByKeyAndTarget 20};
To wire together the campaign and the Amplience slot you’ll use the new function.
Open
1routes/homepage.js
We no longer need a const for the Amplience delivery key as this will be sent as a parameter to the helper function. Delete or comment out this line as you choose
1const amplienceKey = 'HP-Banner-' + apiResponse['HP-Banner'].amplienceID;
- Change the Amplience call to the new helper function. Pass in ‘hp-banner’ for the slots delivery key and the amplienceID from the Dynamic Yield API response for the target
1const amplienceResponse = await AmplienceAPI.getContentFromSlotByKeyAndTarget('hp-banner',apiResponse['HP-Banner'].amplienceID);
- The new get page content function will look something like this:
1async function getPageContent(req) { 2 req.dyContext.page.type = 'HOMEPAGE'; 3 const apiResponse = await DYAPI.choose(req.userId, req.sessionId, req.dyContext,['HP-Banner']); 4 const amplienceResponse = await AmplienceAPI.getContentFromSlotByKeyAndTarget('hp-banner',apiResponse['HP-Banner'].amplienceID); 5 const content = { 6 heroBanner: amplienceResponse || defaultHeroBanner, // <== Here! 7 recommendations: defaultRecommendations, 8 }; 9 if (req.originalUrl.includes('SALE')) { 10 content.overlay = defaultOverlay; 11 } 12 return content; 13}
That’s it. As with the previous approach, we can personalize content for specific audiences: pet, dog and cat lovers.
Open a browser and navigate to http://localhost:3000
The homepage Banner looks something like this:
Scroll down the page and click on a crazy cat product
Add the product to the basket and return to the homepage.
The homepage banner now looks something like this:
- To get the result for dog lovers open a new browser window in incognito mode and follow the same process adding dog products. You will be presented with the dog lovers banner like this one.
Where to go from here
In the first article we demonstrated how you can A/B test using Amplience and Dynamic Yield through server-side integration- fundamental for building headless architectures. This article demonstrated how you can personalise experiences using content targeting by using Dynamic Yield as the personalization engine and Amplience to deliver content through its headless content delivery APIs. This article also presented alternative integration patterns using delivery keys and Amplience slots to make the implementation easier for business users to understand. These approaches can also be applied to A/B testing ,or be expanded further to give even greater flexibility.
One of the challenges I faced at this point with Dynamic Yield was the lack of back office APIs in the version used now. If Dynamic Yield open the platform further, the integration could be expanded by creating extension points in Amplience that will make it possible for users to see audiences and campaigns in Amplience while configuring slots and content. Despite these constraints it is possible to take advantage of the combined power of Amplience and Dynamic Yield.