How to get Sitecore Personalize Decision Model result on my Sitecore Backend code

by Freddy Rueda Barros , @freddy rueda on Slack

The problem

As we know, Sitecore Personalize (hereinafter referred to as Personalize) is a powerful tool to give unique experiences to users based on what marketers want to show, commonly used for campaigns, offers, and advertisements, all of those should be HTML injected via Personalize JavaScript Library.

But sometimes we already have all our components, components, and markups running and all we have to do is know how to show them to certain groups of users. We can use the personalization embedded on Sitecore, but it may not be enough if we need more specific segmentation, for example, if we need to segment users based on the last visited pages on the current session or the number of clicks on an image, and so on, and based on that segment show content that Marketing team creates on the Sitecore CMS.

The solution

Here’s where Personalize comes to help us, but, how? This is my experience, and I want to share it with you. I assume that we have a little experience working with Sitecore CDP and Sitecore Personalize and that we know about Web Experiences.

Create a Decision Model

The first step is to create our decision model, which will have the logic to segment our users based on the last visited page, so, on Sitecore Personalize, menu Decisioning->Decision Models, click on Create Decision Model button, name your Decision Model.

Use the Guest or Session data input depending on your situation, set a Programable node and pick a Decision Table node and choose a Decision Table node that will provide the information that will be taken into our backend code.

In the programmable node, we set the logic to obtain what we need and send it to the decision table. In this example I’m searching for the type of services my users visit, if they visit cloud services pages they will belong to segment 1, and if they visit on-premises solutions they will belong to segment 2, here the JavaScript code for this:

(function () {
 
    var session = guest.sessions[0];
    var cloudServices = 'cloud-services';
    var onPremiseSolutions = 'solutions-onpremise';
    
    
    if(session){
    
     if(session.status === 'OPEN') {
            
        for (var j = 0; j < session.events.length; j++) {
            
            if(session.events[j].type === 'VIEW'){
                var event = session.events[j].arbitraryData;
                
                if(event.page.contains(cloudServices)){
                  return "1" ;
                }
                else if(event.page.contains(onPremiseSolutions)){
                    return "2";
                }
            }
        }

        return "3"; //Default
    }
    }
})();

With the return value of the function we set the Decision Table rules, to do that, we have to create an input column, select the programmable node we set before, and an output column.

In the decision table, we create rules that match the return of the programmable node and with those values, we are going to work in our backend code. Don’t forget to give a meaningful name to the columns and the decision table name. In this case, the table will return the segment name based on the result on the programmable node, the segments will be «Cloud», «OnPremises», «Unsegmented».

To test if everything is ok we use the Test Canvas feature by clicking the button on the top right side of the Decision Model page. With the guest ref info, we can run the test, but how to find the guest info? Go to Dev Tools and in the console, type Engage, you will see the following:

With the guest ref info, go to test canvas and search, we will see the Request info.

Run the Test Canvas and see the Response tab info. Pay attention to the «outputs» on the «decisionModelResultNodes», it says «segmentName» : «Cloud», so, our rule is working fine because the programmable node returns «1».

Create a Web Experience

The second step is to create a web experience that consumes our decision model, we need to use a web experience with an empty template, this is because we don’t need to inject any HTML on our site, and on the Decisioning section we need to choose our Decision Model.

Once the empty template is created and the decision model selected, go to Edit in the Content section. Then go to the API tab and paste the following code:

{
  <#assign MyVariable = getDecisionModelResultNode("Get Segment")>
   <#if (MyVariable)??>
     "visitorSegment": {"segment": "${MyVariable.outputs[0].segmentName}"}
   </#if>
}

The key here is to set correctly the name of the Decision Table node, in this case, «Get Segment», and the JSON attribute «segmentName» which is on the response info when we run the Test Canvas before. The explanation of this code is: we call the decision model, get the result of the decision table and then create a JSON object with the info of the segment name.

To test if everything is correct, let’s use the Preview API button, then use the Guest Ref that we used before and click on Send request. We can see on the Preview API window, on the Response tab, the JSON we create on the API tab of the web experience. That JSON is the result that we need on our backend code, but how to get it? We’ll see on the next step.

Connect to the Sitecore Personalize API

The third step, to get the decision model result on our backend code, is to call the Sitecore Personalize API, to do that first let’s test the API request with Postman (or any other API testing tool) and see what we need as parameters and the response. The API will call a method that retrieves the web experience response, the same one we set in the last step, so, the friendly id of the web experience is the key parameter to get what we want, the input JSON is as follows:

{
    "clientKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "channel": "WEB",
    "language": "en",
    "currencyCode": "USD",
    "pointOfSale": "xxxxxxx",
    "browserId": "5b7dfae8-576a-4dd3-bc00-01c9fb4150cb",
    "friendlyId": "demo"
}

To get the browserId go to the console and execute Engage.getBrowserId().

Set a Postman POST call to the API Url based on your location, I use the US location, so the Url is: https://api-engage-us.sitecorecloud.io/v2/callFlows

One thing to keep in mind is that the Web Experience on Personalize has to be started, if is paused the API will return a «No flow executed» message.

The result will be:

After that, the only thing that we need to do is to call the API from our Backend code, in my case, I’m working with Sitecore 10, so, I created a Foundation.Personalize project and create a class with a method that calls the API and returns the segment, with that we can choose what content to show based on the segment. The gist for this class is here.

        public string GetDecisionModelResult(string experienceId) 
        {
            try
            {
                SiteContext site = Sitecore.Context.Site;
                HttpCookie cookie;
                string bid = string.Empty;

                if (site != null)
                {
                    cookie = System.Web.HttpContext.Current.Request.Cookies["bid_" + Settings.GetSetting("ClientKey")];
                    if (cookie != null)
                    {
                        bid = cookie.Value;

                        var experience = new Experience
                        {
                            ClientKey =  Settings.GetSetting("ClientKey"),
                            Channel = "WEB",
                            Language = "en",
                            CurrencyCode = "USD",
                            PointOfSale = Settings.GetSetting("PointOfSale"),
                            BrowserId = bid,
                            FriendlyId = experienceId
                        };

                        var json = JsonConvert.SerializeObject(experience);
                        var data = new StringContent(json, Encoding.UTF8, "application/json");
                        var url = Settings.GetSetting("ApiUrl");
                        var client = new HttpClient();
                        var response = client.PostAsync(url, data);
                        var result = response.Result.Content.ReadAsStringAsync();
                        dynamic JSONdata = JObject.Parse(result.Result);

                        var segment = JSONdata.visitorSegment.brand;

                        if (segment == "Unsegmented")
                            segment = string.Empty;

                        return segment;
                    }
                }                
            }
            catch (Exception ex) { 
                Log.Error("There was an issue on connecting the Personalize API " + ex.Message, this);
            }
            return string.Empty;
        }

This method uses an HttpClient to call an API, with the parameters we saw before in the Postman call, but the particular thing here is how to know the browserId for each user, to find that value, we need to read a cookie that Sitecore Personalize creates on the browser of each user, the name of the cookie is bid_[clientId]. As good practice, we have to set in a config file the values for the clientId, the Url, and the PointOfSale parameters.

Now and then, we can call this method sending as a parameter the friendly Id of the web experience we want to get the response.

With this example now we know how to retrieve the result of a Sitecore Personalize Decision Model, used in a Web Experience, and then that result is used in our Sitecore 9 or 10 backend code.

Hope that this blog will be helpful in your Sitecore Personalize journey.

Deja un comentario

Diseña un sitio como este con WordPress.com
Comenzar