How to Deliver Targeted Content Using Amplience and Dynamic Yield

John WIlliams
December 2, 2020
10 mins
EngineeringGuidesEcommerce

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.

To make things interesting we will do the same for the crazy cat lovers.
We now have two audiences to target with content, as well as banners we created in Amplience from the previous post - one for dog lovers and one for cat lovers. We also have a generic pet lover banner for non targeted customers. If you open Amplience Dynamic Content headless CMS and go to the repository you used to create your content variants from the previous post, you will see something like this:

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.
Click the menu for the dog gift promotion and select "Delivery key".
  • 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
    1routes/homepage.js
    Change the value in the
    1DYAPI.choose
    in the
    1getPageContent
    function to call the 'HP-Banner’ campaign we have just setup
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.

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

Replace the properties section in the schema with the code below.
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.

  1. Open amplienceAPI.js in your favourite IDE

  2. 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.