Skip to main content

JSS (Optimize only)

This section describes how to add tracking and edge-side personalization to a site that uses Uniform Optimize but does not use Uniform Deploy (i.e. page delivery is not completely decoupled from the CD instance using a static-site generator).

note

Currently Uniform documentation only covers JSS sites built using React. If you are using a different front-end library, contact your Uniform representative for guidance.

tip

A starter application is available that provides a complete example of a site with tracking and personalization configured If you prefer to start your learning from a complete example, this starter application is what you should use. This application is available on GitHub.

Add npm packages#

Add the following npm packages to your JSS application:

  • @uniformdev/esi-jss-react
  • @uniformdev/optimize-js
  • @uniformdev/tracking-react

Add tracker to layout component#

Routing in a React application can be handled in one of two ways: server-side or client-side. The steps needed to add the tracker to a layout component depends on which kind of routing is used.

note

Information on the differences between server-side and client-side routing is available in the reference section.

Server-side routing#

The following code demonstrates adding the Uniform tracker to a very basic layout component:

import React from 'react';import Helmet from 'react-helmet';import { Placeholder, withSitecoreContext } from '@sitecore-jss/sitecore-jss-react';import { useSitecoreTracker } from '@uniformdev/tracking-react';
const Layout = ({route, sitecoreContext}) => {
  useSitecoreTracker(sitecoreContext, {    type: "jss"  });
  return (    <React.Fragment>      <Helmet>        <title>          {(route.fields && route.fields.pageTitle && route.fields.pageTitle.value) || 'Page'}        </title>      </Helmet>
      <div>        <Placeholder name="jss-main" rendering={route} />      </div>    </React.Fragment>  )};
export default withSitecoreContext()(Layout);

Client-side routing#

When client-side routing is used, the Uniform tracker cannot automatically track page views because the Uniform tracker has no way to know exactly when a route change occurs. A developer must add code to invoke the tracker when the route changes.

The following code demonstrates how to incorporate the Uniform tracker into a site that uses client-side routing:

import React, { useEffect, useState } from 'react';import Helmet from 'react-helmet';import { Placeholder, withSitecoreContext } from '@sitecore-jss/sitecore-jss-react';import { useSitecoreTracker } from '@uniformdev/tracking-react';import { doTracking } from '@uniformdev/optimize-js';
const Layout = ({route, sitecoreContext}) => {
  //  //Each time the layout component is loaded, it is  //possible that the route has changed. This state  //variable keeps track of the current route so that  //route changes can be recognized.  const [currentRoute, setCurrentRoute] = useState();
  //  //In client-side routing mode, the tracker is only  //initialized once. When the tracker is initialized,  //this indicates a route change, but the regular  //route change mechanism is not triggered. This  //state variable allows you to know when this sort  //of route change has occurred.  const [isTrackerInitialized, setIsTrackerInitialized] = useState(false);
  useEffect(() => {    setCurrentRoute(route);  }, [route]);
  useSitecoreTracker(sitecoreContext, {    type: "jss",    clientSideRouting: true,    onInitialized: () => { setIsTrackerInitialized(true); }  });
  useEffect(() => {    //    //A page view should only be captured if the route has changed.    const shouldNotTrack = () => {      if (!currentRoute) return true;      if (isTrackerInitialized !== true) return true;      if (!sitecoreContext) return true;      if (!sitecoreContext.tracking) return true;      if (!sitecoreContext.tracking.item) return true;      if (currentRoute.itemId !== sitecoreContext.tracking.item.id) return true;      return false;    }    if (shouldNotTrack()) return;    //    //Invoke the tracker to capture the page view.    doTracking({      source: "sitecore",      context: sitecoreContext,      debug: true,    });  }, [currentRoute, isTrackerInitialized, sitecoreContext])
  return (    <React.Fragment>      <Helmet>        <title>          {(route.fields && route.fields.pageTitle && route.fields.pageTitle.value) || 'Page'}        </title>      </Helmet>
      <Navigation />
      <div className="container">        <Placeholder name="jss-main" rendering={route} />      </div>    </React.Fragment>  )};
export default withSitecoreContext()(Layout);
note

There are many ways to implement client-side routing and to determine when a route has changed. The code above is just one. This approach is not a recommendation, simply one example.

Add personalization to layout component#

note

The steps in this section are the same regardless of whether server-side routing or client-side routing is used.

  1. In the file that defines your layout component, add the following import statements:

    import { useSitecoreContext } from '@sitecore-jss/sitecore-jss-react';import { SitecorePersonalizationContextProvider } from '@uniformdev/personalize-react';
  2. Before the the component is returned, add the following code:

    const { sitecoreContext } = useSitecoreContext();
  3. Wrap the layout component in the following tag:

    <SitecorePersonalizationContextProvider  contextData={sitecoreContext}  personalizationMode="jss-esi"  sitecoreApiKey=""  sitecoreSiteName="">  ...</SitecorePersonalizationContextProvider>
  4. For the prop sitecoreApiKey, add the JSS API key for your Sitecore instance.

  5. For the prop sitecoreSiteName, set the name of the Sitecore site.

  6. The return statement for the component should look something like the following:

    const { sitecoreContext } = useSitecoreContext();return (  <SitecorePersonalizationContextProvider    contextData={sitecoreContext}    personalizationMode="jss-esi"    sitecoreApiKey="11112222-3333-4444-5555-666677778888"    sitecoreSiteName="my-jss-site"  >    <React.Fragment>      <Helmet>        <title>          {(route.fields && route.fields.pageTitle && route.fields.pageTitle.value) || 'Page'}        </title>      </Helmet>
          <Navigation />
          <div className="container">        <Placeholder name="jss-main" rendering={route} />      </div>    </React.Fragment>  </SitecorePersonalizationContextProvider>)

Add ESI Context placeholder#

Uniform adds a placeholder named esi-context to the page layout. This placeholder is populated with a component that is responsible for generating the context on the edge that powers edge-side personalization.

This placeholder must be added to Nextjs application, and it must be added before any placeholders that hold personalized components. When the components inside this placeholder are rendered, there is no output. This means you do not need to worry that adding this placeholder could break your layout.

<Placeholder name="esi-context" rendering={route} />
note

For more information about the ESI Context, see the reference section.

Update component factory#

JSS uses a component factory to resolve the component name returned from Layout Service to a React component. Uniform's edge-side personalization depends on a number of custom React components. These components must be registered with the component factory.

In a JSS site, the component factory is configured in the file scripts/generate-component-factory.js. The following steps describe how to add the Uniform components to the component factory:

  1. Locate src/RouteHandler.js

    You should see the following import statement

    import componentFactory from './temp/componentFactory';
  2. Add an import for the Component Factory Personalizer wrapper

    import {  componentFactoryWithUniformPersonalizer} from '@uniformdev/esi-jss-react';
  3. Wrap the componentFactory to create a new function with Optimize support

    const componentFactoryWithPersonalizer =  componentFactoryWithUniformPersonalizer(componentFactory);
    info

    See Personalizer for more information on how this works as well as further options to include or exclude specific components.

  4. Save the file.

  5. Deploy the JSS site.