Troubleshooting tracking and personalisation in Sitecore XM Cloud
Published: 2024-04-25 11:16:30

One of the first things I tested in Sitecore XM Cloud was embedded tracking and personalisation capabilities. It has been really interesting to see what is available out-of-the-box, how much flexibility XM Cloud offers to marketing teams and what is required from developers to set it up. 

However, in this article I want to take a step back and talk about troubleshooting steps for situations when Sitecore XM Cloud tracking or personalisation is not working as expected. I have been working with Sitecore XP for many years so over time it became easy to find what is wrong in my setup. As XM Cloud applications are built on a new technology stack, investigating issues initially was a challenge. So I created this troubleshooting guide and hope that you will find it useful too. 

## Troubleshooting tracking

The first step is to ensure that your website is tracking visitors correctly as without it you will not be able to use personalisation reports. Navigate to the **Analyze** section on the XM Cloud portal. If you see the "No data available" message and empty charts across both **Site insights** and **Page insights**, it is a sign that tracking is not functioning as expected.

![Missing tracking data](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lbv3v7rl7bdiqt63par4.png)

To troubleshoot, load your website in a browser, open the **Development Tools** panel and switch to the **Network** tab. Refresh the page and look for a POST request to the Personalize tracking API, it should look similar to this:

```
https://api-engage-eu.sitecorecloud.io/v1.2/events
```
If you do not see this request, ensure that the component **\src\components\CdpPageView.tsx** and the file **\src\Scripts.tsx** are included in your layout (by default it is **\src\Layout.tsx**), otherwise tracking will not work.

Additionally, check the browser console for any error messages. Here are potential reasons that could cause them:

- Incorrect Site Identifier (or Point of Sale in CDP/Personalize terminology)
- Incorrect Target URL
- Content Security Policy headers block tracking requests

Make sure that your Site Identifiers and Target URL match those from the **Developer Settings** in XM Cloud and that Target URL is whitelisted in your security headers.

Rectifying these errors should restore tracking functionality and you will start seeing statistics and charts similar to these in the XM Cloud portal:

![Analytics reports in Sitecore XM Cloud](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ismajqf00bdypf4jh2ea.png)

## Troubleshooting personalisation

Troubleshooting personalisation can't be done directly via browser simply because it is performed on the server side within your rendering host application. This is where debug-level logging can help us see what happens behind the scenes.

To enable debug-level logs for the rendering host add the following line to the **.env** file:

- **DEBUG=sitecore-jss:***
- or **DEBUG=sitecore-jss:personalize*** to limit detailed logging to the Personalize middleware only

After this you will start seeing API request and response details for both the GraphQL API and Sitecore Personalize API, as well as additional debugging information:

![Debug logs of the rendering host container](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/euvw08spxivo5m4g5cv2.png)

## Handling common scenarios

**1. Middleware is disabled**

One of the common reasons why personalisation does not seem to be working is the "**disable**" function of Personalize middleware. This function defines logic and conditions for skipping personalisation. 

If the function returns "**true**", you will see the following message in the log:

```
sitecore-jss:personalize skipped (personalize middleware is disabled)
```
By default, it returns "**true**" for the development environment so personalisation will not be triggered on your local machine.

**Solution:**

Open the file **\src\lib\middleware\plugins\personalize.ts** and update the function **disabled**. Remember to implement your own logic, for example cookie consent validation.

![The function "disabled" of Personalize middleware](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kzrizr002likw071v4qx.png)

**2. Timeouts**

Timeouts for both GraphQL and Personalize API requests can occur in development environments with frequent codebase updates and application restarts. If there is a timeout error, you will easily see which API responds slower than the allowed threshold.
Log message for GraphQL API timeout:

```
sitecore-jss:personalize request: {url: 'http://cm/sitecore/api/graph/edge’,…} sitecore-jss:personalize response error: 'Request timed out, timeout of 400ms is exceeded'
```
Log message for Personalize API timeout:

```
sitecore-jss:personalize request: {url: 'https://api-engage-eu.sitecorecloud.io/v2/callFlows’,…} sitecore-jss:personalize request error:  [AbortError: Request timed out, timeout of 400ms is exceeded]
```
**Solution:**

Adjusting timeout thresholds in the **.env** file can resolve these issues. However, be cautious not to set them too high as it can slow down your application. To increase API request timeouts, change the following variables:

- **PERSONALIZE_MIDDLEWARE_CDP_TIMEOUT** for Personalize API
- **PERSONALIZE_MIDDLEWARE_EDGE_TIMEOUT** for GraphQL API

Default values are 400ms and depending on the development environment configuration, these requests may be require more time to respond.

**3. Personalize info not found**

This error occurs when an incorrect page route or language is requested. Basically, it means that the GraphQL API was not able to find the requested page and layout details for it. Here is the log message to identify it, usually it is followed by 404 page response:

```
sitecore-jss:personalize skipped (personalize info not found)
```
**Solution:**

Make sure that you request the correct page URL and correct language version.

**4. No personalization configured**

If no personalised variants are configured for the requested page, the "no personalization configured" message appears in the log. It means that the GraphQL API was able to find the page and its layout, but the layout does not contain any personalised page variants.

```
sitecore-jss:personalize skipped (no personalization configured)
```
**Solution:**

Verify that the page you are testing indeed contains personalised variants. If the requested page does not have any personalisation rules, then this message is expected and may not require any fixes.

**5. Browser ID generation failed**

The browser ID is used for identifying requests from the same visitors. If a browser ID has been previously generated, it is stored in a cookie and sent to the server with every page request.
However, if it is the very request without any cookies (or cookies have been cleared), then Personalize middleware will attempt to generate a new browser ID for the current request. If something goes wrong during browser ID generation, the following message will be written to the log: 

```
sitecore-jss:personalize skipped (browser id generation failed)
```
**Solution:**

Ensure that the correct Site Identifier, Target URL and Clint Key are configured in the **.env** file as they are needed for browser ID generation.

**6. No variant identified**

When the Personalize middleware sends a request but fails to identify any matching audience for the current visitor, the "no variant identified" message appears:

```
sitecore-jss:personalize skipped (no variant identified)
```
**Solution:**

Double check that the personalisation rule is correct and does match your current visitor audience. 

If you are not sure what is wrong with the rule, try simplifying it as much as possible to identify which part of it is not working as expected. For example, if a rule combines multiple conditions, consider testing each condition individually to find which one is failing.

**7. Invalid variant**

This scenario occurs when an audience is identified for the current visitor, but the Personalize middleware is unable to find corresponding page variant in the page layout. It can be caused by outdated page definitions or mismatches between environments.

```
sitecore-jss:personalize skipped (invalid variant)
```
**Solution:**

If there are mismatches between content in XM Cloud and audience definitions, save personalisation rules in XM Cloud to synchronise them with Personalize API.

If you are seeing this error in a local development environment and want to test personalisation there, consider copying content from the environment where these personalisation rules were created.

## Other API errors

If you are seeing any other errors related to personalisation, pay attention to logged API requests and responses. For example, an incorrect CM hostname or API key would trigger an error.
In some cases in can be useful to grab request details from logs and try running it in a tool like Postman to see how it is executed and what it returns.

**GraphQL API request:**

```
sitecore-jss:personalize request: {    
url: 'http://cm/sitecore/api/graph/edge',    
headers: { sc_apikey: ‘...' },    
query: '\n query($siteName: String!, $language: String!, $itemPath: String!) {\n layout(site: $siteName, routePath: $itemPath, language: $language) {\n item {\n id\n version\n personalization {\n variantIds\n }\n }\n }\n }\n ',    
variables: { siteName: 'Test', itemPath: '/', language: 'en’ }
}
```
**Personalize API request:**

```
sitecore-jss:personalize request: {   
url: 'https://api-engage-eu.sitecorecloud.io/v2/callFlows',    
headers: { content-type: 'application/json’, user-agent: ‘...’ },   timeout: 10000,   
method: 'POST',   
body: '{"clientKey":“...","pointOfSale":"default","channel":"WEB", "browserId":“...","friendlyId":"embedded_77735a5b0ac9441caa5f00428e47500_en", "params":{"referrer":"about:client","utm":{"campaign":“test_campaign", "content":null,"medium":null,"source":null}}}'
}
```

## Successful response

When debug-level logging is enabled, successful responses from GraphQL and Personalize APIs will be saved too. Examples of successful responses and their data format are shown below. 

**GraphQL API response:**

```
sitecore-jss:personalize response: {    
layout: {       
   item: {          
      id: '77735A5b0AC9441CAA5f00428E47500’,          
      version: 1,          
      personalization: {             
         variantIds: [ '25026aae743c4de2a5f54effc47f5a5c', length: 1 ]    
      }       
   }    
}}
```
**Personalize API response:**

```
sitecore-jss:personalize response: {    
status: 200,    
statusText: 'OK’,    
headers: { ... },    
url: 'https://api-engage-eu.sitecorecloud.io/v2/callFlows’,    
redirected: false,    
data: { variantId: '25026aae743c4de2a5f54effc47f5a5c’ }  
}
```
Finally, if you see the following "**Personalize middleware end**" message, congratulations, your website returned some personalised content! 

You can use the logged variant ID to make sure that correct audience was selected and the expected variant is displayed on the website:

```
sitecore-jss:personalize personalize middleware end: {    
rewritePath: '/_variantId_0dd7b00680be49c6815ca4d0793a36da/_site_Test/About’,    
browserId: '53bda419-2228-4a4b-a406-5e08a453f9e9’,    
headers: {    
   set-cookie: 'BID_{CDP_client_key}=53bda419-2228-4a4b-a406-5e08a453f9e9;
   ...,    
   x-middleware-cache: 'no-cache’,    
   x-middleware-rewrite: 'http://localhost:3000/ variantId0dd7b00680be49c6815ca4d0793a36da/_site_Test/About’,    
   x-sc-rewrite: '/_variantId_0dd7b00680be49c6815ca4d0793a36da/_site_Test/About’ 
}
```
Hopefully, this guide helped you to understand the common issues in XM Cloud tracking and personalisation, and you found ideas on how to approach and resolve them. 

Please do let me know if you want to learn more about how XM Cloud personalisation works inside out and I will cover it in my next post!