The Sitecore Experience Platform is a true Headless Content Management System and it separates the building blocks managed by back-end components from the front-end, with this, you can create the Head of your application in any tech stack without compromising the Sitecore Content Management System offerings, and one of the major requirements or functionality or offering of Sitecore Experience Platform is Tracking of User Journey.
Sitecore is an API-first CMS and Decoupled CMS which also facilitate the Sitecore Experience Platform offering for digital marketers related to analytics and reporting on Headless CMS implementation.
When you are doing Sitecore Headless CMS-based implementation using any Client-Side Scripting framework like NextJS, tracking of events would be different from Sitecore Experience Platform ASP.NET MVC-based implementation.
For the Sitecore JSS NextJS-based application, we have to use the Sitecore JSS Tracking API, a client-side implementation of Headless Services Tracker and available to the Sitecore NextJS-based application via the Sitecore JSS tracking module.
Follow these links to skip to specifc topics
The sitecore-jss-tracking package provides the trackEvent function to capture the following Sitecore Tracking Services:
• Event
• Goal
• Outcome
• Campaign
• PageView
The method details are present at JSS Tracking API (sitecore.com)
Even type |
Event properties |
---|---|
|
{
goalId: "<goal ID>"
}
|
|
{
outcomeId: "<goal ID>",
currencyCode: "<currency code>",
monetaryValue: "<monetary value>"
}
|
|
{
pageId: "<page ID>",
url: "<page URL>"
}
|
|
{
campaignId: "<campaign ID>"
}
|
|
{
eventId: "<event-value>"
}
|
<configuration>
<sitecore>
<settings>
<setting name="Sitecore.JSS.TrackerServiceEnabled" value="true" />
</settings>
</sitecore>
</configuration>
You can use Sitecore Patch Configuration Files to deploy to both CM and CD roles.
The ways to access the different tracking services mentioned at Track events in JSS apps using the Tracking API (sitecore.com).
To simplify, I have created the file which will help to pass the required details for different types of operations.
Sitecore JSS Tracking code ? SitecoreTracking.ts
/*!***************************************************!*\
!*** Siteocre JSS Tracking Functions ***!
\***************************************************/
/**
This file created with the help of Sitecore StyleguideTracking details.
The functions in this file can be used in NextJS based application with Sitecore JSS
to track the Sitecore Goals, Sitecore Outcome, Sitecore Page Event, Sitecore Campaign.
*/
import { trackingApi } from "@sitecore-jss/sitecore-jss-tracking"
import config from "temp/config"
import { dataFetcher } from "src/lib/data-fetcher"
import getConfig from "next/config"
import { useCallback } from "react"
import { useQueryClient } from "react-query"
import { AxiosError } from "axios"
const {
publicRuntimeConfig: { PublicUrl },
} = getConfig()
const trackingApiOptions = {
host: PublicUrl + "/api/services",
serviceUrl: "/jss/track",
querystringParams: {
sc_apikey: config.sitecoreApiKey,
},
fetcher: dataFetcher,
}
interface SitecoreTracking {
//--goalDetails: Goal GUID or Name
triggerGoal: (goalDetails: string) => void
triggerCampaign: (campaignDetails: string) => void
triggerEvent: (eventDetails: string) => void
triggerPageView: (pageView: PageView) => void
triggerOutcome: (outcome: Outcome) => void
}
type PageView = {
pageId: string
url: string
}
type Outcome = {
url: string
pageId: string
outcomeId: string
monetaryValue: number
}
export const sitecoreTracking = (): SitecoreTracking => {
const queryClient = useQueryClient()
const triggerGoal = useCallback(
(goalDetails: string) => {
trackingApi
.trackEvent([{ goalId: goalDetails }], trackingApiOptions)
.catch((error) => {
if (
error &&
error.isAxiosError &&
(error as AxiosError).response?.status === 400
) {
}
console.error("Error :: SitecoreTracking > triggerGoal=>" + error, error.isAxiosError)
})
},
[queryClient]
)
const triggerCampaign = useCallback(
(campaignDetails: string) => {
trackingApi
.trackEvent(
[
{
campaignId: campaignDetails,
},
],
trackingApiOptions
)
.catch((error) => {
if (
error &&
error.isAxiosError &&
(error as AxiosError).response?.status === 400
) {
}
console.error(
"Error :: SitecoreTracking > triggerCampaign =>" + error,
error.isAxiosError
)
})
},
[queryClient]
)
const triggerEvent = useCallback(
(eventDetails: string) => {
trackingApi
.trackEvent(
[
{
eventId: eventDetails
},
],
trackingApiOptions
)
.catch((error) => {
if (
error &&
error.isAxiosError &&
(error as AxiosError).response?.status === 400
) {
}
console.error(
"Error :: SitecoreTracking > triggerEvent =>" + error,
error.isAxiosError
)
})
},
[queryClient]
)
const triggerPageView = useCallback(
(pageView: PageView) => {
trackingApi
.trackEvent(
[
{
pageId: pageView.pageId,
url: pageView.url, },
],
trackingApiOptions
)
.catch((error) => {
if (
error &&
error.isAxiosError &&
(error as AxiosError).response?.status === 400
) {
}
console.error(
"Error :: SitecoreTracking > triggerPageView =>" + error,
error.isAxiosError
)
})
},
[queryClient]
)
const triggerOutcome = useCallback(
(outcome: Outcome) => {
trackingApi
.trackEvent(
[
{
url: outcome.url,
pageId: outcome.pageId,
outcomeId: outcome.outcomeId,
currencyCode: "USD",
monetaryValue: outcome.monetaryValue,
},
],
trackingApiOptions
)
.catch((error) => {
if (
error &&
error.isAxiosError &&
(error as AxiosError).response?.status === 400
) {
}
console.error(
"Error :: SitecoreTracking > triggerPageView =>" + error,
error.isAxiosError
)
})
},
[queryClient]
)
return {
triggerGoal,
triggerCampaign,
triggerEvent,
triggerPageView,
triggerOutcome
}
}
In the above functions, I have utilized the useCallback to improve the performance of API calls. The React hook useCallback hook will cache the API details and will only be called again when one of its dependencies changed. This will improve the performance.
You can pass dependencies as per your need to React hook useCallback
useCallback(fn, deps) – Returns a memoized callback.
Usage of Sitecore JSS Tracking code ? Sitecore-Tracking-Component.tsx
/*!***************************************************!*\
!*** Siteocre JSS Tracking Functions Usage ***!
\***************************************************/
/**
The purpose of this file is to showcase, how Sitecore JSS Tracking services can be used
from Sitecore NextJS applicaiton to track the Sitecore Goals, Sitecore Outcome, Sitecore Page Event, Sitecore Campaign.
*/
import { Box } from "@material-ui/system"
import { sitecoreTracking } from "lib/SitecoreTracking"
import { useState } from "react"
const SitecoreTracking = () => {
const { triggerGoal,triggerCampaign,triggerEvent, triggerPageView, triggerOutcome } = sitecoreTracking()
const [inputGoalValue, setGoalValue] = useState('')
const [inputCampaignValue, setCampaignValue] = useState('')
const [inputEventValue, setEventValue] = useState('')
const [inputPageIdValue, setPageIdValue] = useState('')
const [inputPageUrlValue, setPageUrlValue] = useState('')
const [inputOutComeValue, setOutComeValue] = useState('')
const [inputMonetaryValue, setMonetaryValue] = useState('')
return (
<Box>
<Box>
<fieldset className="form-group col-sm">
<legend>Goal</legend>
<p>
Goals are defined in{" "}
<code>/sitecore/system/Marketing Control Panel/Goals</code>
</p>
<label htmlFor="goal">Goal GUID or Name</label>
<input
type="text"
className="form-control"
id="goal"
placeholder="i.e. Register"
value={inputGoalValue}
onChange={e => { setGoalValue(e.currentTarget.value); }}
/>
<button
type="button"
className="btn btn-primary mt-3"
onClick={() => triggerGoal(inputGoalValue)}
>
Submit
</button>
</fieldset>
<fieldset className="form-group col-sm">
<legend>Campaign</legend>
<p>
Campaigns are defined in{" "}
<code>
/sitecore/system/Marketing Control Panel/Campaigns
</code>
</p>
<label htmlFor="campaign">Campaign GUID or Name</label>
<input
type="text"
className="form-control"
id="campaign"
value={inputCampaignValue}
onChange={e => { setCampaignValue(e.currentTarget.value); }}
/>
<button
type="button"
className="btn btn-primary mt-3"
onClick={() => triggerCampaign(inputCampaignValue)}
>
Submit
</button>
</fieldset>
<fieldset className="form-group col-sm">
<legend>Event</legend>
<p>
Events are defined in{" "}
<code>/sitecore/system/Settings/Analytics/Page Events</code>
</p>
<label htmlFor="event">Event GUID or Name</label>
<input
type="text"
id="event"
className="form-control"
value={inputEventValue}
onChange={e => { setEventValue(e.currentTarget.value); }}
/>
<button
type="button"
className="btn btn-primary mt-3"
onClick={() => triggerEvent(inputEventValue)}
>
Submit
</button>
</fieldset>
<fieldset className="form-group col-sm">
<legend>Page View</legend>
<p>
Track arbitrary page views for custom routing or offline use.
Note that Layout Service tracks page views by default unless{" "}
<code>tracking=false</code> is passed in its query string.
</p>
<label htmlFor="pageId">Page Item GUID</label>
<input
type="text"
className="form-control"
id="pageId"
placeholder="i.e. {11111111-1111-1111-1111-111111111111}"
value={inputPageIdValue}
onChange={e => { setPageIdValue(e.currentTarget.value); }}
/>
<br />
<label htmlFor="pageUrl">Page URL</label>
<input
type="text"
className="form-control"
id="pageUrl"
placeholder="i.e. /foo/bar"
value={inputPageUrlValue}
onChange={e => { setPageUrlValue(e.currentTarget.value); }}
/>
<button
type="button"
className="btn btn-primary mt-3"
onClick={() => triggerPageView({pageId: inputPageIdValue, url: inputPageUrlValue})}
>
Submit
</button>
</fieldset>
<fieldset className="form-group col-sm">
<legend>Outcome</legend>
<p>
Outcomes are defined in{" "}
<code>/sitecore/system/Marketing Control Panel/Outcomes</code>
</p>
<label htmlFor="pageId">Page Item GUID</label>
<input
type="text"
className="form-control"
id="pageId"
placeholder="i.e. {11111111-1111-1111-1111-111111111111}"
value={inputPageIdValue}
onChange={e => { setPageIdValue(e.currentTarget.value); }}
/>
<br />
<label htmlFor="pageUrl">Page URL</label>
<input
type="text"
className="form-control"
id="pageUrl"
placeholder="i.e. /foo/bar"
value={inputPageUrlValue}
onChange={e => { setPageUrlValue(e.currentTarget.value); }}
/>
<br />
<label htmlFor="outcomeName">Outcome GUID or Name</label>
<input
type="text"
className="form-control"
id="outcomeName"
value={inputOutComeValue}
placeholder="i.e. Marketing Lead"
onChange={e => { setOutComeValue(e.currentTarget.value); }}
/>
<br />
<label htmlFor="outcomeValue">Monetary Value (optional)</label>
<input
type="number"
className="form-control"
id="outcomeValue"
value={inputMonetaryValue}
placeholder="i.e. 1337.00"
onChange={e => { setMonetaryValue(e.currentTarget.value); }}
/>
<button
type="button"
className="btn btn-primary mt-3"
onClick={() => triggerOutcome({url: inputPageUrlValue, pageId: inputPageIdValue,outcomeId: inputOutComeValue,monetaryValue:parseInt(inputMonetaryValue) })}
>
Submit
</button>
</fieldset>
</Box>
</Box>
)
}
export default SitecoreTracking
In the code above, block (NextJS Component), I tried to use all the Sitecore JSS Tracking functions defined at SitecoreTracking.ts:
Execute Goal by Goal Name
Execute Goal by Goal Id
Tracking object not deployed
If you are trying to execute Goal or Events or any other tracking events on objects or Sitecore Tracking Deployed which not present in the Sitecore Content Tree (Web DB) then you will get error MarketingDefinitionNotFound
For this you can follow the steps at Deploy marketing definitions and taxonomies (sitecore.com) or verify the Sitecore Items at Web DB
Execute Campaign by Campaign Name
Execute Campaign by Campaign Id
Headless CMS architecture separates back-end content functions (like creation, management, and storage) from front-end functions (like presentation and delivery) in this case you can utilize Sitecore Tracking Services to execute the Sitecore Goals, Sitecore Outcome, Sitecore Page Event, Sitecore Campaign in order to track the performance of Sitecore Website content.
Later the collected data via the Sitecore xConnect API can be used to build reports for business users.
Credit/References
- JSS services and APIs (sitecore.com)
- JSS Tracking API (sitecore.com)
- Tracking Service (sitecore.com)
- Track events in JSS apps using the Tracking API (sitecore.com)
- Identifying contacts (sitecore.com)
Amit is an IT Solution Architect with Assurex. Reach out to Amit on