How To Do Lightning Fast and Decoupled Personalization With Umbraco Heartcore

Christian Bennich
Christian BennichPosted on Jun 22, 2021
8 min read
Home/Blog/How To Do Lightning Fast and Decoupled Personalization With Umbraco Heartcore

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.

Learn more about maintaining security and privacy as a priority when delivering websites with Uniform and Jamstack.

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 and from there, you can create yourself an Umbraco Heartcore project.

  2. Access to Uniform
    1. You can set up a free account 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.


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 unfrmOptIntentTagClick to copy will hold the Intent name configured in Uniform, and the field unfrmOptIntentTagStrengthClick to copy 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:


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: 


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.

In this PoC, we manually generate and deploy the intent manifest into our project. 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:

 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.


The localTrackerClick to copy 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:


Next, we have to setup the clientconnection to Umbraco Heartcore

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 HeroClick to copy that we will later Personalize.


The actual data for the Hero’sClick to copy will be fetched in the Index.tsxClick to copy that we create soon.

First, let's create our HeroClick to copy component.


In hero.tsxClick to copy, we define an interface for the FieldsClick to copy that the HeroClick to copy component should contain and set up the actual hero component.

The Uniform specific fields in the HeroFieldsClick to copy 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:


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.

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 />Click to copy component is how we do the actual personalization with the list of Hero components parsed in once we get to the index.tsxClick to copy file.

Uniforms <Personalize />Click to copy 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.

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: 


The props.heroFieldsListClick to copy are populated as part of GetStaticPropsClick to copy:


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


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

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


To get from Umbraco’s JSON output to the correct IntentTagsClick to copy Interface format for each HeroFieldsClick to copy instance we create our map function. For this purpose, I created the mapIntentJsonToIntentTagClick to copy 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.tsxClick to copy and marketer.tsxClick to copy. Both contain a Hero component with data fetched from Umbraco and rendered.

Because we already set useBehaviorTrackingClick to copy 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.

See our fully composable DXP in action by requesting a demo today.

Happy hacking!!

Uniform has been named in the

2022 Gartner® Cool Vendors™ in Digital Commerce Report