Skip to main content

Personalizing on Kontent Data

Once you have installed the Uniform Optimize plugin for Kontent, the next step is to get the Kontent content into your application and start personalizing it.

Fetch data from Kontent

The file below expects the Kontent JS SDK to be already installed. It returns the Kontent Delivery client so it can be used to Query data.

/utils/api.ts
import { ContentItem, DeliveryClient, Elements, IContentItem, TypeResolver } from '@kentico/kontent-delivery';

// PersonalizedHeroItem is a component with a reference field that holds
// HeroItem components as personalization variations.
// HeroItem contains the Uniform Intent Tag for intent matching purposes.
//
// Data setup in Kontent CMS
//
// PageItem
// - PersonalizedHeroItem
// -- HeroItem (no intent tag)
// -- HeroItem (with Intent Tag)
// -- HeroItem (with Intent Tag)
// -- ...
//
// The <presonalize /> component delivered by the Uniform SDK choses
// which HeroItem to show based on the Intent scoring given by the Signals.
//
// More info: https://docs.uniform.app/optimize/strategy
// And more: https://docs.uniform.app/optimize/dev

export type ComponentType = PersonalizedHeroItem | HeroItem;

export class PageItem extends ContentItem {
public page_components: Elements.LinkedItemsElement<ComponentType>;
public title: Elements.TextElement;
public slug: Elements.UrlSlugElement;
}

export class PersonalizedHeroItem extends ContentItem {
public unfrmoptp13nlist: Elements.LinkedItemsElement<IContentItem>;
}

export class HeroItem extends ContentItem {
public title: Elements.TextElement;
public description: Elements.RichTextElement;
public image: Elements.AssetsElement;
public intent_tags: Elements.CustomElement;
}

export const deliveryClient = new DeliveryClient({
projectId: process.env.KONTENT_PROJECT_ID, // Your Kontent Project ID
typeResolvers: [
new TypeResolver('page', () => new PageItem()),
new TypeResolver('personalized_hero_banner', () => new PersonalizedHeroItem()),
new TypeResolver('hero_banner', () => new HeroItem()),
],
});

The following piece of code loads a page by slug. Beware this is a highly simplified version of this code.

import { deliveryClient, PageItem } from '../lib/api';

export const getPageBySlug = async (slug: string) => {
const page = await deliveryClient.item<PageItem>(slug).depthParameter(3).toPromise();
const components = page.item.page_components.value;

return {
props: {
title: slug,
components: components,
},
};
};

Use Kontent Data With the Personalize Component

The variations field contains references to personalizable content entries. The <Personalize /> component needs variants to be mapped in a specific way. See the HeroData type below. The result can be passed to the variations field.

/components/personalizedHero.tsx
import { Personalize } from '@uniformdev/optimize-tracker-react';
import { IntentTags } from '@uniformdev/optimize-common';
import { Hero } from './Hero';

enum ComponentType {
Hero = 'hero',
PersonalizedHero = 'personalized-hero',
}

type HeroData = {
type: ComponentType.Hero;
title: string;
description: string;
image: string;

// Note the 'intentTag' key.
// This is needed for the <Personalize /> component to understand how to personalize.
intentTag: IntentTags | undefined | null;
};

type PersonalizedHeroData = {
type: ComponentType.PersonalizedHero;
heros: HeroData[];
};

export const PersonalizedHero = ({ item }: { item: PersonalizedHeroData }) => {
return (
<Personalize
variations={item.heros}
component={Hero}
trackingEventName="heroPersonalized"
loadingMode={PersonalizedHeroLoading} // specifiy a component for a potential loading state
/>
);
};

Note that the intentTag field comes back as a serialized string from the Kontent CMS. Make sure to JSON.parse it.

export const convertIntents = (IntentTagValue: Elements.CustomElement) => {
return JSON.parse(IntentTagValue.value);
};