How To Do Lightning Fast and Decoupled Personalization With Umbraco Heartcore

2.png

Connect with Uniform

GithubTwitter
8 minutes read

In the headless and decoupled world, performance and user experience are at the center when creating new and compelling websites. The importance of driving relevant conversations with site visitors are documented time and time again. The relevant discussions are driven by personalized content delivered to individual visitors based on behavior and actions performed on the digital channels.

However, these tailored journeys and content experiences have always been complex to implement and even harder to maintain. This can become even more complex in a headless world and doing it without compromising performance by introducing unnecessary dependencies on origins can be very tricky.  

But what if you could actually do this, do it easy and make it work quickly on Umbraco Heartcore as well?

Uniform provides the fastest possible personalized websites possible by enabling edge or client-based personalization and decoupled tracking without any origin dependency during runtime. All data and functionality can be delivered on edge and as first-party assets embedded into your application for the best possible performance and security.

For more information on security when delivering websites with Uniform and Jamstack: https://uniform.dev/blogs/what-you-need-to-know-about-jamstack-personalization-and-privacy

The principles shown in this article can be applied to any CMS from which you can extract content on a REST API, GraphQL API or similar, for delivery through a front-end centric application built with e.g., Next, Nuxt or similar. 

Let's get started!

This short video will show what we are aiming to implement and how the personalization will work in practice afterwards.

Insert video

What do you need to follow along:

  1. Access to Umbraco Heartcore
    1. You can set up a trial account on try.umbraco.com and from there, you can create yourself an Umbraco Heartcore project.

  2. Access to Uniform
    1. You can set up a free account on uniform.app and deploy a starter to have some default intents and signals generated that we can use in this PoC. For documentation on Intents and Signals, please visit: Uniform documentation Don't worry about which CMS is chosen during the setup, as we will "bypass" that in this demo.

  3. The simplest next.js starter
    1. Clone from here: Github

    2. If you fancy Nuxt - read this type: entry-hyperlink id: 2rrvWxDhRnyeIPy5AtRpjn as well.

Setting up Umbraco Heartcore

To get started we need to define some simple content types in Umbraco Heartcore – a json output can be found here: Github

Please see screenshots for details.

Document types in Umbraco:

UmbracoHearthCore Doctype 1

Overview of contenttypes in the simple solution done. The "Compositions" and "Elements" are folders for organization purposes.

UmbracoHeartCore Doctype2

"Hero Composition" is used a Composition in the "Textpage" contenttype. All Property Editors are defined directly in the Contenttype.

UmbracoHeartCore Doctype3

"Personalized Hero" is used as a Composition in the "Frontpage" and utilizing the element Content type "Hero" as nested Content. See next image.

UmbraoHeartCoreHeroNestedContent

UmbracoHeartCore Doctype 4

"Hero" is the Document type that will be used to hold the hero variants that are used for personalization based on the intents from Uniform. The Document type is used, as described above in the "Personalized Hero" Document type.

UmbracoHeartCore Doctype 5

"Uniform Data" hold the relevant data needed to inform Uniforms tracker about how to do personalization. The Document type are used in the "Hero" and "Textpage" Document types.

UmbracoHeartCore Doctype 6

"Frontpage" is the Document type that are used as the Root type and and use the "Personalized Hero" as the Composition type.

UmbracoHeartCore Doctype 7

"Textpage" use "Hero Composition" as the Composition type to get the relevant fields used on the page.

Content created based on above Content types:

UmbracoHeartCore Doctype 8

Create the root node in the tree - "Home" and define "Hero variants". The field "unfrmOptIntentTag" hold the name of the Intent from Uniform to define when the particular "Hero variant" are to be shown. In above image - Item 1 will be shown if I have the "marketer" intent, which I pick up from visiting the "Marketer" page..more on that later.

UmbracoHeartCore Doctype 9

The "Developer" variant.

UmbracoHeartCore Doctype 10

The "Call for paper" campaign variant.

UmbracoHeartCore Doctype 11

The "Default" variant. Both Uniform field need to be empty here. The type of integration we do here is somewhat manual and shallow as at the time of writing, there is no way to create custom Property Editors etc. in Umbraco Heartcore and therefore we are unable to pull data etc. directly from Uniform.

UmbracoHeartCore Doctype 12

Defining the "Developer" page. The Uniform field are both filled with data here. The "unfrmOptIntentTag" field holds the Intent ID from Uniform and the "unfrmOptIntentTagStrength" hold the amount of "points" consuming this page will accumulate againtst

UmbracoHeartCore Doctype 13

There is not much content here, except for a few headlines and some information necessary to instruct Uniform on tracking behavior and doing personalization.

Essentially, we have defined two simple pages and a hero. The data needed for Uniform is embedded into an Element Content Type in Umbraco Heartcore called “Uniform Data” and for this simple scenario it holds only two fields that, in this PoC, are manually filled with data.

UmbracoHeartCore Doctype 5

The field unfrmOptIntentTag will hold the Intent name configured in Uniform, and the field unfrmOptIntentTagStrength will hold the value that we initially choose for the content if any value is needed. In this PoC – no value is given in any Personalizable hero.

Setting up code and getting Uniform into our code

The application we “build” is based on a very simple next.js starter. Run the below code in your favourite editor or terminal to get started:

Personalize_Umbraco_create_next_app

To get Uniform and the packages necessary for communicating with Umbraco Heartcore into our project, install the following packages with your favourite packagemanager. Please note that version numbers might have changed since publishing this blogpost: 

Personalize_Umbraco_import

Uniform runs all personalization either on the Edge or directly in the client browser. All is handled through the tracker, just imported, and the Intent Manifest.

 The intent manifest - defines an array of known intents and their signals. It is usually provided at build time by a request to Uniform Optimize and baked into your JS bundle. https://docs.uniform.app/optimize/dev/architecture/#data-sources.

 In this PoC, we manually generate and deploy the intent manifest into our project. https://docs.uniform.app/optimize/dev/getting-started/#fetch-intent-manifest. You could however, easily include manifest generation as part of your build.

 If you do no customizations to the manifest generation, the manifest will end up in the /Lib folder and look like this: https://github.com/uniformdev/uniform-umbraco-heartcore-poc/blob/main/lib/intentManifest.json.

 We can now begin to build our small application and fetch some data from Umbraco Heartcore.

 I have created a simple _app.tsx that allows me to bootstrap my entire application into Uniforms tracker.

Personalize_Umbraco_app_tsx

The localTracker is defined in: ../lib/localtracker.tsx

Which very simply just creates an instance of the Uniform Tracker with the previously generated Intent Manifest as the input:

Personalize_Umbraco_localtracker

Next, we have to setup the clientconnection to Umbraco Heartcore - https://github.com/uniformdev/uniform-umbraco-heartcore-poc/blob/main/lib/HearthCoreClient.tsx

Supply your Umbraco Heartcore projectAlias (the Project Alias is an HTTP friendly version of the Project Name under your Umbraco Cloud account.) and apiKey in the .env file. 

We can now create the Hero that we will later Personalize.

Personalize_Umbraco_default_hero

The actual data for the Hero’s will be fetched in the Index.tsx that we create soon.

First, let's create our Hero component.

Personalize_umbraco_hero_tsx

In hero.tsx, we define an interface for the Fields that the Hero component should contain and set up the actual hero component.

The Uniform specific fields in the HeroFields interface are “type” and “intentTag” – which originate from the Interface PersonalizableListItem and are necessary for the Tracker to correctly track the intent tags and personalize on them as well.

The definition of the Hero component is not super complex but contains one important Uniform piece:

Personalize_Umbraco_Usebehaviortracking

We add this line of code to instruct Uniform that this particular component should influence how visitors get classified based on intents in the system. https://docs.uniform.app/optimize/dev/react/behavior/

Now that the hero component is in place let’s create a Personalized version to use on the front page.

Create the PersonalizedHero.tsx in the /components folder.

The <Personalize /> component is how we do the actual personalization with the list of Hero components parsed in once we get to the index.tsx file.

Uniforms <Personalize /> component can accept a list of possible variants and emit a rendered React component based on the type(s) of variants determined to be most relevant to the visitor. https://docs.uniform.app/optimize/dev/react/personalizing

Now we have all the basics in place, and can now move on to create the index.tsx page that will show the actual personalization.

We set up the index component first: 

Personalize_Umbraco_Index_Component

The props.heroFieldsList are populated as part of GetStaticProps:

Personalize_Umbraco_StaticProps

We use “MyClient” to fetch content from Umbraco, similar to this output.

Personalize_Umbraco_JsonOutput

And by mapping out the contents of “heroVariants” to, we create a list that we can use in <PersonalizedHero />.

 Because we have not integrated Uniforms application into the backend of Umbraco Heartcore, we need to “manually” map the array:

Personalize_Umbraco_Array

To get from Umbraco’s JSON output to the correct IntentTags Interface format for each HeroFields instance we create our map function. For this purpose, I created the mapIntentJsonToIntentTag function in /Lib/utils.tsx

It will return IntentTags objects in the correct format to use for Personalization and behavior tracking. 

The last piece of the puzzle is to create pages containing content tagged with specific intents, to drive personalization.

I have created two pages, developer.tsx and marketer.tsx. Both contain a Hero component with data fetched from Umbraco and rendered.

Because we already set useBehaviorTracking in the hero component – we trigger Uniform’s tracker and get tagged with the relevant intent by visiting these two pages. 

That’s it – you now have blazing fast personalization executed completely decoupled from your backend and with the ability to work in a Jamstack manner with statically generated pages, etc., for optimum speed on all pages.

For more information and to see a Demo, visit http://uniform.dev

Happy hacking!!

Christian Bennich

Christian Bennich

I joined Uniform in December 2020. In the past, I have spent 6,5 years with Sitecore, a year with Avanade and running my own consulting business for 10 years. Based in "sunny" Denmark.....

LinkedIn