Skip to content
November 25, 2021 / kiranpatils

Sitecore CDP Troubleshooting Guide

While learning Sitecore CDP, I learned a few things. Which I would like to document because of the following reasons:

  1. Before I forget those!
  2. Those become so obvious to me, I don’t want to write about those [As I will assume everyone knows about it 🙂 ]
  3. It helps you during your learning process!

So, if you are new to Sitecore CDP or starting your journey this post might be helpful for you.

  • Boxever.getID() is null and Browser Console is showing follwoing error:

GET https://api-us.boxever.com/v1.2/browser/create.json?client_key=psfu6uh05hsr9c34rptlr06dn864cqrx&message=%7B%7D&callback=jsonp3807209069558803 net::ERR_ABORTED 401 (Unauthorized)

Troubleshooting Steps

1. Review your Initialization Javascript’s _boxever_settings.target property
2. It must be ‘https://api-us.boxever.com/v1.2′
3. Change it to https://api.boxever.com/v1.2

This means that your CDP instance has been set up in the EU and not US/Asia. A simple way to figure this out is. This Target URL’s domain should be the same as your Boxever Portal URL e.g. https://app.boxever.com/

  • Verify CDP is initialized : Verify using boxever cookie and getID() method
  • Would like to see current state of particular guest and would like to get in-depth view of behind the scenes data (Sitecore Developer : Something like “RAW Value” checkbox)

Sitecore CDP Stores everything in JSON format and if you would like to see that JSON data, you can enable the “debug” feature flag (Depends on your role, you might not see this option)

Once you do that you will see a following option in the portal:

When you click on that you will be able to see all under the hood details (You have to click “Show as JSON”)

  • It’s good practice to test your Experience, before making it live:
  • While designing Decision Table none of the offers are getting returned

The first thing to check will be Hit Policy and then try testing it “Test Canvas” feature.

Tip : If you are using a particular user more often for testing then you can bookmark/favorite it by clicking on STAR.

One more thing, if your Programmable Decision Model is using any property which is not populated in the “Request” screen then don’t worry, you can always set it here. For example, during my Abandoned Cart example, I was trying to use an entity.ref property which only gets populated when the Triggered experience happens. But to ensure that it works, I used to set “entity. ref” property to my guest’s refid.

  • Triggered experience is not working

If your triggered experience is not working then the right place to troubleshoot is your Triggered Experience’s “Operational” tab and view the log from “Execution Report”

There is no IDE here where you can attach to process and debug what’s going on :-). But luckily “Test” feature in Sitecore CDP is your friend and you can also write

You can use the print function in your Programmable Decisions

https://doc.sitecore.com/cdp/en/users/sitecore-customer-data-platform/including-print-statements-in-programmable-decisions.html

  • Misc
    • Make sure your Experience/Experiment is not in is live
    • Make sure your expected Decision Model is in Producton
    • If troubleshooting experiment and traffic is divided between variants then make sure you are getting right variant

Web References:

Hope this helps you during your learning process! If you learned something new, please comment on this post, and will incorporate it in this list against your name!

Happy Sitecore CDPing! 🙂

November 25, 2021 / kiranpatils

Customer’s orders tab not showing order while using Sitecore CDP

Challenge

Sitecore CDP allows you to receive Customer’ order data along with all required details. Which helps you to have all information about your customer.

During Training, we faced some challenges getting it integrated end to end as we need to follow a strict order. I will try to share my learnings in this post.

Solution

Let’s see the quick demo first below, Where we are ordering an item using a sample app and checking it out and it’s getting displayed in Orders Tab:

Let’s look at each part in detail:

Note: As this is a sample app, a few things are hardcoded. Please make sure they are modified before production use.

  • Add To Cart : As per my knowlwedge, item_id is important here and you need to pass same ID during Confirm and Checkout
function AddToCart(productid) {
        _boxeverq.push(function () {
            var addEvent = {
                "browser_id": Boxever.getID(),
                "channel": "WEB",
                "type": "ADD",
                "language": "EN", //***IMPORTANT***
                "currency": "USD", //***IMPORTANT***
                "page": "/products",
                "pos": "YOURPOSNAME",
                "product": {
                    "type": "SMARTWATCH",
                    "item_id": "AW" + productid, //***IMPORTANT***
                    "name": "Apple Watch" + productid,
                    "orderedAt": "2015-08-23T16:17:16.000Z",
                    "quantity": 1,
                    "price": 250.00,
                    "productId": "CORRECT_SCORE",
                    "originalPrice": 100.00,
                    "originalCurrencyCode": "USD",
                    "currency": "USD",
                    "referenceId": "BET_001-1"
                }
            };           
            // (<event msg>, <callback function>, <format>)
            Boxever.eventCreate(addEvent, function (data) { }, 'json');
        });
        alert("Added To Cart" + productid);
    }
  • Confirm And Checkout : Please review inline comments
function ConfirmAndCheckout() {
        _boxeverq.push(function () {
            var confirmEvent = {
                "browser_id": Boxever.getID(),
                "channel": "WEB",
                "type": "CONFIRM", //***IMPORTANT ORDER MATTERS***
                "pos": "YOURPOSNAME",
                "language": "EN", //***IMPORTANT***
                "currency": "USD", //***IMPORTANT***
                "page": "/products",
                "product": [{
                    "item_id": "AW7" //***IMPORTANT ITEM ID SHOULD MATCH with ADD TO CART***
                }]
            };

            var checkOutEvent = {
                "browser_id": Boxever.getID(),
                "channel": "WEB",
                "type": "CHECKOUT", //***IMPORTANT ORDER MATTERS***
                "pos": "YOURPOSNAME",
                "language": "EN", //***IMPORTANT***
                "currency": "USD", //***IMPORTANT***
                "page": "/products",
                "reference_id": "11032021B",//***IMPORTANT : Your Order number***
                "status": "PURCHASED" 
            };

            // Invoke event create
            // (<event msg>, <callback function>, <format>)
            Boxever.eventCreate(confirmEvent, function (data) { }, 'json');
            Boxever.eventCreate(checkOutEvent, function (data) { }, 'json');
        });

        alert("Order Confirmed and Checkedout");
    }

If everything goes as per plan then you should also see your order instantly under the “Orders” tab:

Resources:

Happy Customer’s Order Integration with Sitecore CDP!

November 25, 2021 / kiranpatils

Invalid Date in Date Math String error with Computed field in Sitecore with Solr

Recently we came across following exception:

Exception: SolrNet.Exceptions.SolrConnectionException
Message: <?xml version=”1.0″ encoding=”UTF-8″?>
<response>
<lst name=”responseHeader”><int name=”status”>400</int><int name=”QTime”>46</int></lst><lst name=”error”><str name=”msg”>Invalid Date in Date Math String:’2017-03-20T13.56.31Z'</str><int name=”code”>400</int></lst>
</response>

Quick search resulted in to this post : https://briancaos.wordpress.com/2017/10/25/sitecore-solr-error-invalid-date-in-date-math-string/

But mentioned Sitecore fix has been already applied for Sitecore 9.3

After spending couple of hours troubleshooting this we noticed that our Computed field’s name (mycustomfield) was same as Sitecore Field name(MyCustomField):

<field fieldName="mycustomfield" returnType="datetime">SCBasics.Feature.PageContent.Index.MyCustomField,SCBasics.Feature.PageContent</field>

To fix this issue, You can either update your field name in Sitecore or change your computed field name in the Config file (We took the route of updating the computed field name).

It might seem like a small issue. But we had to apply various checks before we learned this. As error message was not super clear. Hope this helps someone save a couple of hours from their day. Which can be given to their loved ones!

Happy Sitecore Development! 🙂

November 25, 2021 / kiranpatils

Send Abandoned Cart email using Sitecore CDP/Personalize

Challenge

Recently as part of Sitecore CDP training (If you are new to this product, you might like my earlier blog), we implemented a feature to send an email to users whenever the cart is abandoned. We could implement this feature in a short time (read: Faster time to market) using the No/Low code power of Sitecore CDP.

Thought to share it with you as well. So, you can also experience the power of the platform!

Solution

To notify Sitecore CDP that the user has abandoned the cart. We need to send the FORCE_CLOSE Event

_boxeverq.push(function () {
            var addEvent = {
                "browser_id": Boxever.getID(),
                "channel": "WEB",
                "type": "FORCE_CLOSE",
                "pos": "YOURPOSNAME",
                "currency": "USD",
                "language": "EN"
            };
            // Invoke event create
            // (<event msg>, <callback function>, <format>)
            Boxever.eventCreate(addEvent, function (data) { }, 'json');
        });

Once you do that and if you go to guest/customer’s interactions timeline. You will be able to see that the user has abandoned the cart with $ value of it. In the real world, this is an opportunity lost for business.

As this is an opportunity lost for business. Business is keen to send an email to the user with a better offer.

Let’s see how we can make this happen:

Step 1 : Create connection to send an email

In this example, we will use https://www.mailjet.com/. But you can use any other email service which supports sending email via API.

Click Add Connection
Select Destination as we are connecting to an email service and sending data to a destination

Go through the wizard and the best thing is you can send a test email using UI. Ensure your email API connectivity is working fine.

Step 2 : Create Decision Model

Once your email connection is configured. The next step will be creating Decision Model. If you are new to Sitecore CDP. Then think of a Decision Model as your Business Logic Layer in Backend architecture. The only difference here is Decision Models are not coded. But they are visually designed first and then if needed code can be added using Server Side Javascript.

I believe Decision Model is the most powerful feature of Sitecore CDP as business logic can be easily visualized and understood by Technical/Non Technical users.

Decisoning -> Decision Models -> Create Decision Model

Your Decision Model will keep evolving with your business needs. So, please make sure you follow the versioning strategy. So, you can easily refer to any version number and can revert (You have to clone) any version based on your need.

Decision Model follows Workflow. Draft and Test are not applicable for your live users. Only whatever version is in “Production” that’s impacting end users!

Decision Model Build Tab
Decision Model Canvas

The above Decision Model is taking Guest/Sessions as input.

Note: Decision Table for Dummy offer has been added as the system had a bug where it’s expecting at least one offer to be returned for your Decision Model to work. (Read – this post from Julia)

Following JS Snippet is basically fetching triggered session’s events with type as ADD/ABANDONED and finally, it returns JSON. Which we will connect with Triggered Experience in the next step.

(function () {
     function getTriggerSession(){
        var sessionRef;
        if (typeof entity !== 'undefined' && entity && entity.ref !== 'undefined') {
            sessionRef = entity.ref;
        }
        
        var triggerSession;
        for (var i = 0; i < guest.sessions.length; i++) {
            var session = guest.sessions[i];
            if (session.ref === sessionRef) {
                triggerSession = session;
                break;
            }
        }
        return triggerSession;
    }
    var triggerSession =  getTriggerSession();
    
    if(triggerSession)
    {
        var productTypes = [];
        htmlBody="<ul>";
        for (var i = 0; i < triggerSession.events.length; i++) {
                var event = triggerSession.events[i];
                if (event.type === "ADD" && triggerSession.cartType == "ABANDONED") {
                     productTypes.push({ 
                        "item_id": event.arbitraryData.product.item_id,
                        "price": event.arbitraryData.product.price,
                        "currency": event.arbitraryData.product.currency,
                        "abandonedAt": triggerSession.endedAt
                    });
                    
                    htmlBody +="<li> ItemID : " + event.arbitraryData.product.item_id + ", Price :" + event.arbitraryData.product.price +", Currency:"+ event.arbitraryData.product.currency 
                    + ", AbandonedAt : " + triggerSession.endedAt;
                    htmlBody +="</li>";
                }
        }
        
      htmlBody +="</ul>";
      
      return {
            "email": guest.email,
            "productTypes": productTypes,
            "htmlBody":htmlBody
        }
    }
})();

Step 3 : Create a Triggered Experience

Before we implement Triggered Experience. Let’s do a quick recap of what we’ve done so far:

  1. Created connection with our Email API Service
  2. Created Decision Model and using Programmable we have final JSON response which gives you ABANDONED Cart data

Triggered experience is going to connect the dots.

Experiences -> Full Stack -> Triggered Experience

Triggered experience as the name indicates will be triggered based on the Event.

You can select preconfigured Trigger – In this example, we will use “Abandoned Cart”
Connect to your Decision Model (Created in Step 2 to get JSON response of required data)
Connect to Email Destination Service (Created in Step 1)
Read Decision Model Response and Create API Request JSON using Freemarker
This is how your triggered experience should look like!

Final Result

Added 3 Apple Watches from my sample App and clicked on Force close which triggers abandoned cart
Abandoned Cart triggered this email

Troubleshooting

You can also view this Triggered Experience status from the portal as shown below:

Go to Guest Profile and Interactions timeline

If your Triggered experience is failing, then you can go to your Triggered experience’s operational tab and see analytics of your execution, and for more details click on “Execution Report”

Execution report, View log can show you full details

That’s it for now, hope you found this post useful and you learned something about Sitecore CDP/Personalize!

November 9, 2021 / kiranpatils

5 Scenarios to demonstrate the power of Sitecore CDP/Personalize

I had the privilege to be part of Sitecore CDP Developer Deep Dive training last week. Thanks to HZTL for an opportunity, Sitecore Partner Enablement Team, and our trainer Sarah O’Reilly!

The training was nicely planned and full of hands-on. It was fun to learn something new and be happy to see it working!

In case you haven’t heard of Sitecore CDP then it stands for Sitecore Customer Data Platform. Which was earlier known as Boxever. The following Image by Dave O’Flanagan summarizes all Sitecore offerings!

You might have noticed Sitecore CDP and Sitecore Personalize as a separate box in the above image. The rationale behind that is. Sitecore wants to be the truly composable solution. Where if you want to do Data Ingestion you can opt for Sitecore CDP and if you also want to use that data for personalization and Testing, you can opt for Sitecore Personalize.

You might be wondering what are the different features between Sitecore CDP and Sitecore Personalize. The Sitecore team had nice slides explaining it. But I wanted to have a single image for myself hence updated the image to add some visual indicators which should help you identify different features of Sitecore CDP and Sitecore Personalize

Original Image Credits: Sitecore

Now, you might be excited to know. How can I get started? My fellow Sitecore Community Member – Neil Killen has done a great job outlining this and some basic details on his blog: https://neilkillen.com/2021/11/07/sitecore-cdp-tips-and-tricks/ – I strongly recommend you to read his post!

After reading through Neil’s post and getting some basic details. You might be more curious and would like to see more scenarios that we can achieve using Sitecore CDP/Personalize products. If yes, then this post is for you.

Quick Disclaimer :-): This is a work of fiction. any similarities to persons living or dead, or actual events is purely coincidental.

Scenario 1: User visiting the website for the first time (Visitor. Old: Unknown contact)

A Visitor is a Guest who hasn’t provided enough identifying information and appears anonymous.

Scenario 2: Visitor visting few pages

Scenario 3: User Sign up and login (Visitor -> Customer. Old : Known Contact)

A customer is a guest that has provided enough identity information, or if they have not, they are a contact on an order.

Scenario 4: User adding items to cart and abandons cart

For sending emails, I could easily configure an SMTP connection using Portal.

Scenario 5: User purchased products

Sounds amazing?! If yes, then you will be more amazed to know that, to make the above scenarios happen. No/Low Code (Freemarker, Javascript) has been used, the platform had 21M users and everything was blazing fast!

As part of this post, I’ve just demonstrated 5 initial features. There is a lot more you can do using this platform. For example:

  • Sending Interactive data
  • Decision modelling
  • Dynamic offers
  • A/B Testing and Personalized Experiences
  • Batch API for Customer, Orders etc.
  • Segments

If you want to read more. You can start from here: https://doc.sitecore.com/cdp/ or/and https://sitecore.cdpknowledgehub.com/docs (I’m sure both these sources will be ported to doc.sitecore.com one day!)

If you are curious to see more on this topic and also would like me to explain what it takes from a Code/Configuration point of view to make each scenario possible. Please drop me a comment and will be more than happy to share what I learned!

%d bloggers like this: