Skip to main content

Sitecore

Connecting Sitecore CDP to Next.js website

Connection

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:

Boxever Ui

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

Api Key Api Key Detail

Create Point of Sale

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

PocPoc Detail

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.

Debug

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.

Company Info

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

Company Info Id

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:

View Event

This is the response:

View Event Response

We can search data in Sitecore CDP by browser_Id

Cdp By Browser Id

All user interactions associated with that session are available

Cdp By Browser Id Events

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

Cdp By Browser Id Detail

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

Identify Event

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

Identify Event Cdp

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

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Sergey Plotnikov

Sergey has more than 20 years of development experience and has been working with Sitecore since 2015. In his spare time, he enjoys time with his family as well as tennis, chess, and following hockey.

More from this Author

Categories
Follow Us
TwitterLinkedinFacebookYoutubeInstagram