Quasi Personalisation with XM Cloud Content SDK

Craig
Architect - Sitecore
  • Twitter
  • LinkedIn

The content SDK doesn't have any built in personalization functionality far from it it's just a front end that you can do with as you please so how might you include something akin to Sitecore personalization when all you have is a front end? For one of the projects that we were working on we used a series of personalization codes simply to check if conditions were met relating to a geographic region and a user type. In this case both the region type and the user type were stored in a cookie because the front end acting alone does not have the ability to truly store persistent information in the same way that a sitecore XP does. This does have a minor drawback in that the cookies are directly visible and even editable bye a person viewing the site. However, in this case those visiting the site were able to self select their user type and their region. 

Add a content level we would then need to assign fields for both the user type and the region as rendering parameters to each component that we wanted to be hidden or shown based on there chosen user type and region. In our case if no region or user type filtering criteria was supplied we would always show the content. 

While admittedly this did not show a huge amount of personalization it was enough to satisfy the amount of personalization required for our client. 

//This was the code to implement the visibility filter for the sitecore context 
 


import { SitecoreFields } from './format-properties'; 

import { getCookie } from 'lib/manage-cookies'; 

import { SitecoreContextValue } from '@sitecore-content-sdk/nextjs'; 

import { ComponentProps } from 'lib/component-props'; 

export interface Region { 

id: string; 

fields: { 

name: string; 

userTypes: UserType[]; 

}; 

} 

export interface UserTypePickerProps { 

data: { 

link: UserType[]; 

}; 

} 

export interface UserType { 

id: string; 

displayName: string; 

fields: { 

UserTypeName: { 

value: string; 

}; 

name: string; 

}; 

} 

export const isVisibleContext = ( 

sitecoreProps: SitecoreFields & ComponentProps, 

sitecoreContext: SitecoreContextValue 

): boolean => { 

const UserTypeParams = sitecoreProps?.params?.['User Types']; 

const RegionParams = sitecoreProps?.params?.['Regions']; 

//if we are in edit mode, return true and don't both with other checks 
 


if (UserTypeParams || RegionParams) { 

if (sitecoreContext?.pageEditing === true) { 

return true; 

} 

} 

return isVisible(sitecoreProps); 

}; 

export const isVisible = (sitecoreProps: SitecoreFields & ComponentProps): boolean => { 

const UserTypeParams = sitecoreProps?.params?.['User Types']; 

const RegionParams = sitecoreProps?.params?.['Region']; 

return isItemVisible(UserTypeParams, RegionParams); 

}; 

export const isItemVisible = (userTypes: string, region: string): boolean => {

// Check if we're on the client side before accessing cookies 



if (typeof window === 'undefined') { 

// During SSR, return true to avoid hydration mismatches 
 


return true; 

} 

if (userTypes) { 

const userTypeCookie = getCookie('MY_USER_TYPE').replace(/^{|}$/g, '') as string; 

if (!userTypeCookie) { 

return false; 

} 

const userType = userTypes.toLowerCase(); 

if (!userType.includes(userTypeCookie.toLowerCase())) { 

return false; 

} 

} 

if (region) { 

const regionCookie = getCookie('MY_REGION_LOCATION').replace(/^{|}$/g, '') as string; 

if (!regionCookie) { 

return false; 

} 

const regionValue = region.toLowerCase(); 

if (!regionValue.includes(regionCookie.toLowerCase())) { 

return false; 

} 

} 

return true; 

}; 

//And this was how it was called in each component 


import { isVisibleContext } from '@src/lib/check-visibility'; 

if (!isVisibleContext(sitecoreProps, sitecoreContext)) { 

return <>; 

}