Quick introduction

Sitecore CDP stands for Sitecore Customer Data Platform. This is a quote from Sitecore documentation:

A Customer Data Platform is packaged software that creates a persistent, unified customer database that is accessible to other systems.

In nutshell it tracks customers’ data across all channels, and later this data can be used to run personalization for segments of customers. Sitecore provides detailed documentation, and you can get more information from their website: What is a CDP

Get access to Sitecore CDP

Thanks, Perficient that as Sitecore platinum partner, we have access to the sandbox where we can practice and work. The Sitecore CDP interface is straightforward:

Goal

I was interested in what need to be done to connect the existing Next.js website to Sitecore CDP. Also, I wanted to see the whole picture of how Sitecore CDP collecting customer data. There is Developer Documentation explaining how to integrate it using vanilla JavaScript. Let’s look how we can apply it to Next.js project.

Setup Sitecore CDP

Obtain Client Key

Login to Sitecore CDP, navigate to System Settings -> API Access

Create Point of Sale

Navigate to System Settings -> Point of Sale to setup a new point of sale for our website

Enable debug mode

Debug mode enables visibility of all data and configuration stored in Sitecore CDP. It will give us access to additional information for requests. To enable debug mode, click on the Bottom left corner -> You Profile -> Feature Flags -> Enable Debug flag.

Review organization identity rules

To be able to send Identity event to Sitecore CDP, we need to know the identity rules for our organization tenant. To verify that information we should navigate to System Settings -> Company Information.

On the company information screen, we should click Debug, and after that Show as JSON, and then locate the identityIndexConfigurations JSON object.

These are the identity rules for our organization’s tenant. In this case the organization is using one identity rule: SITECORE_ID. That means that when we will be sending IDENTITY event to Sitecore CDP it should contain a value for SITECORE_ID attribute to identify a guest.

Implementation

At this point we are ready to connect our application to Sitecore CDP. All sensitive information we will put in the configuration file.

// cdpConfig.js

const cdpConfig = {
client_key: process.env.BOXEVER_CLIENT_KEY,
cookie_domain: process.env.BOXEVER_COOKIE_DOMAIN,
pointOfSale: process.env.NEXT_PUBLIC_BOXEVER_POC,
clientVersion: process.env.BOXEVER_CLIENT_VERSION,
webFlowTarget: process.env.BOXEVER_WEB_FLOW_TARGET,
};

export default cdpConfig;

According to documentation, we need to activate JavaScript library by adding script snippet to each page. We can wrap that script into the react component.

// SitecoreCdp.jsx

import React from ‘react’;
import cdpConfig from ‘@/clients/cdpConfig’;

const SitecoreCdp = () => {
return (
<React.Fragment>
<script
dangerouslySetInnerHTML={{
__html: `var _boxeverq = _boxeverq || [];
var _boxever_settings = {
client_key: ‘${cdpConfig.client_key}’,
target: ‘https://api-us.boxever.com/v1.2’,
cookie_domain: ‘${cdpConfig.cookie_domain}’,
javascriptLibraryVersion: ‘${cdpConfig.clientVersion}’,
pointOfSale: ‘${cdpConfig.pointOfSale}’,
web_flow_target: ‘${cdpConfig.webFlowTarget}’,
web_flow_config: { async: true, defer: true }
};

(function() {
var s = document.createElement(‘script’); s.type = ‘text/javascript’; s.async = true;
s.src = ‘https://d1mj578wat5n4o.cloudfront.net/boxever-${cdpConfig.clientVersion}.min.js’;
var x = document.getElementsByTagName(‘script’)[0]; x.parentNode.insertBefore(s, x);
})();`,
}}
></script>
</React.Fragment>
);
};

export default SitecoreCdp;

We can use that component from our _app.js, so we have that script injected to every page.

// _app.js

import Head from ‘next/head’;
import GoogleAnalytics from ‘@/utils/GoogleAnalytics’;
import SitecoreCdp from ‘@/utils/SitecoreCdp’;
import { AppProvider } from ‘@/contexts/app/AppContext’;

const App = ({
Component,
pageProps
}) => {
return (
<Head>
<meta
name=’viewport’
content=’width=device-width, initial-scale=1′
/>
<meta
httpEquiv=’Content-Type’
content=’text/html; charset=utf-8′
/>
<GoogleAnalytics />
<SitecoreCdp />
</Head>
<AppProvider>
<Component {…pageProps} />
</AppProvider>
);
};

export default App;

Now we need to implement some logic to send events to Sitecore CDP. Few helper functions will help us to provide some common information.

// helpers.js

export const isClientSide = () => typeof window !== ‘undefined’;

export const getChannel = () => {
if (!isClientSide()) {
return null;
}
const userAgent =
window.navigator.userAgent ||
window.navigator.vendor ||
(window.opera && window.opera.toString() === `[object Opera]`);

if (/window phone/i.test(userAgent)) {
return ‘Windows Phone’;
}
if (/android/i.test(userAgent)) {
return ‘Android’;
}
if (/iPad/i.test(userAgent)) {
return ‘iPad’;
}
if (/iPhone/i.test(userAgent)) {
return ‘iPhone’;
}
return ‘WEB’;
};

export const getCdpObjects = () => {
if (!isClientSide()) {
return null;
}
const boxever = window.Boxever;
const boxeverq = window._boxeverq;

if (!boxever) {
return null;
}
const browser_id = boxever.getID();
const channel = getChannel();
const defaultEvent = {
browser_id: browser_id,
channel: channel,
poc: cdpConfig.pointOfSale,
ext: {
userDevice: channel,
},
};
boxever.addUTMParams(defaultEvent);
return { boxever, boxeverq, defaultEvent };
};

isClientSide returning true or false depending on which side of application we are (client or server)
getChannel returning us a channel depending on user browser
getCdpObjects returning boxever objects to send events, and the default event object with common information

And the final preparation step is to create actions to send events.

// cdpActions.js

import { getCdpObjects } from ‘@/utils/helpers’;
const createCdpEvent = (eventData) => {
const { boxever, boxeverq, defaultEvent } = getCdpObjects() || {};

if (!boxever) {
return;
}
const cdpEvent = {
…defaultEvent,
…eventData,
};
boxeverq.push(function () {
boxever.eventCreate(cdpEvent, function () {}, ‘json’);
});
};

const createCdpIdentityEvent = (user, eventData) => {
const { boxever, boxeverq, defaultEvent } = getCdpObjects() || {};

if (!boxever || !user) {
return;
}
const cdpEvent = {
…defaultEvent,
…eventData,
type: ‘IDENTITY’,
email: user.email,
lastName: user.lastName,
firstName: user.firstName,
gender: user.gender,
age: user.age,
phone: user.phone,
identifiers: [
{
provider: ‘SITECORE_ID’,
id: user.id,
},
],
};

cdpEvent.ext.gender = user.gender;
cdpEvent.ext.age = user.age;

boxeverq.push(function () {
boxever.eventCreate(cdpEvent, function () {}, ‘json’);
});
};

export { createCdpEvent, createCdpIdentityEvent };

This code is showing that we created two actions which will be used to send general and identified events. Now we can start sending events to Sitecore CDP from our application. Below is an example how to send both types of events from the home page.

// pages/index.js

import React, { Fragment } from ‘react’;
import { createCdpEvent, createCdpIdentityEvent } from ‘@/actions/cdpActions’;
import { useAppContext } from ‘@/contexts/app/AppContext’;

const HomePage = (props) => {

const { state } = useAppContext();

useEffect(() => {
createCdpEvent({
type: ‘VIEW’,
page: ‘home’,
});
}, []);

useEffect(() => {
if (state.user.email === ”) {
return;
}
createCdpIdentityEvent(state.user, {
page: ‘home’,
});
}, [state.user.email]);

return (
<Fragment>

</Fragment>
);
}

export default HomePage;

When user is visiting this page ‘View’ event is getting sent (which is 1st useEffect hook is responsible for), and when user is logged in, Identity event is getting sent. This is responsibility of 2nd useEffect hook.

Review results

If we visit or home page, we can see that view event has been sent to Sitecore CDP.

This is the request:

This is the response:

We can search data in Sitecore CDP by browser_Id

All user interactions associated with that session are available

And since debug mode was activated, event detail information in JSON format available as well

If we are logging in to our application, then the Identify event is getting sent to Sitecore CDP. Below is the example of how create event request looks like

And request data can be observed from Sitecore CDP side as well.

Conclusion

As we can see Sitecore CDP integration with an existing application is not requiring a lot of work at all. Discussed approach is not the only way to make that integration. There is Sitecore Personalize npm package which is a wrapper for Sitecore CDP scripts and allows us to add use it in react applications. Another approach would be to set up an API server which will be making calls to Sitecore CDP. From an application we will be making calls to that server. In this case we don’t need to inject script to every single page. With Next.js that can be done in the same application. This is an example how these calls could look like.