Issues

An Omnichannel experience with Umbraco Heartcore

Umbraco Heartcore is the headless CMS version of Umbraco. This Software as a Service (SaaS) product offers you a super friendly editor experience, managed APIs and CDN among other features. It was launched on the second of December 2019 and you can read more about the Heartcore launch and why digital agencies such as Luminary love to work with headless.

An Omnichannel experience revolves around your customer and creates a single customer experience across your brand by unifying sales and marketing. The Latin word Omni means all. So Omnichannel is about targeting all channels.

You would have heard or read about how a headless CMS could create an Omnichannel experience. In this article, you will be taken on a journey where you will see Umbraco Heartcore power an omnichannel experience in a fictional Lamington shop.

What’s a Lamington? Those of you outside Australia and New Zealand would probably ask. Wikipedia gives us a succulent description.

A lamington is an Australian cake made from squares of butter cake or sponge cake coated in an outer layer of chocolate sauce and rolled in desiccated coconut. The thin mixture is absorbed into the outside of the sponge cake and left to set, giving the cake a distinctive texture.

While you are salivating on the Lamington, it’s time to dig in and see how our fictional Lamington shop covers all its channels with content-driven from Umbraco Heartcore.

Alert to non-developers, you can skip the content set up and implementation details in this article to get the cream of this post.

Content set up

This section will guide you on setting up the content to try this entire scenario on your own. You can sign up for a trial of Umbraco Heartcore to try this out.

Document Types

There are a few document types needed to support the website. But to be succinct, in this article, you will only concentrate on two document types used for managing products.

Document Type Group Property Editor
Product Collection Content Title Textstring
    Sub Title Textstring
Product Content Title Textstring
    Price Textstring
    Description Richtext editor
    Image Media picker
    Quantity Textstring
    Is on special today True/false

*Note that all fields are mandatory.

Relationships

Product Collection document type is allowed in the root and Product document types are allowed as child nodes of Product Collection. It would be easy starting by creating Document Type Collection with Product Collection as the parent and Product as the item.

Feature Alert

Umbraco Heartcore’s Content Management API allows you to retrieve Content Types (AKA Document Types). Unfortunately, at this point, we are unable to create Content Types using the Content Management API. So that's a little manual exercise for you. But do remember that all of this is done in the familiar Umbraco 8 back-office and it should be a breeze. If it's your first time with Umbraco follow this guide to create these document types.

Once you have done creating the content types, you can request the content type definition for the product with the following request:

curl --location --request GET 'https://api.umbraco.io/content/type/product' \
  --header 'Authorization: Basic YOURACCESSKEYHERE' \
  --header 'umb-project-alias: your-project-alias' \

In response, you will get the JSON payload with the properties of the product content type.

Content Population

Once you have got the content types set up manually, you can use the Content Management API to create content. Here’s an example where we create a product:

curl --location --request POST 'https://api.umbraco.io/content/' \
--header 'Authorization: Basic YOURACCESSKEYHERE' \
--header 'umb-project-alias: your-project-alias' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": {
        "$invariant": "Classic Lamington"
    },
    "contentTypeAlias": "product",
    "parentId": "guid-of-the-product-collection",
    "sortOrder": 0,
    "title": {
        "$invariant": "Classic Lamington"
    },
    "price": {
        "$invariant": "2.50"
    },
    "image": {
        "$invariant": "umb://media/f1485357ba7b4d8abea23c0789ba572c"
    },
    "description": {
        "$invariant": "<p>The classics in a pack of six.</p>"
    },
    "quantity": {
        "$invariant": 38
    },
    "isOnSpecialToday": {
        "$invariant": true
    }
}'

You should get a 201 Created response back if your request is successful.

The next step is to publish that content item.

curl --location --request PUT 'https://api.umbraco.io/content/guid-returned-from-previous-action/publish' \
  --header 'Authorization: Basic YOURACCESSKEYHERE' \
  --header 'umb-project-alias: your-project-alias' \

You should get 200 Success response when your item is successfully published.

If you are using Postman to create content this Postman collection will help you get on the way. Note that the images referred to in the scripts were uploaded manually and then referenced.

In this manner, we have published the following products:

Feature Alert

Umbraco Heartcore’s Content Management API allows you to create, update and publish content items. Similarly, there are other endpoints for manipulating media, languages, members and even Umbraco Forms.

No-UI

Our not-so-fictional shopper, Jordan loves his lamingtons. So much so that when he wakes up each morning, he hollers “Hey Google, Talk to Lord Lamington”.

The Google mini in his room replies “Lord Lamington sends his greetings. How can I help you today?”. Jordan responds by asking for today’s specials.

“We have got Classic Lamington on special today. There are only 38 left. So you better hurry if you want one!” replies the assistant and ends the conversation.

Watch this conversation play out on YouTube

No-UI Implementation

As you may have guessed, the data for the specials was pulled out of Umbraco Heartcore. Let’s have a look at how this was setup step by step using Google Dialogflow and Firebase.

  1. Go to https://dialogflow.cloud.google.com/
  2. Create a new agent
  3. Go to the settings of the new agent and in the “Export and Import” section, Import the zip file found here - Heartcore-lamington-Rnd.zip
  4. Once you have imported it, go to the Fulfilment section and enable Inline Editor (Powered by Cloud Functions for Firebase)*
  5. Copy the code from index.js and package.js files and deploy
  6. Once the deployment is complete, you should be able to test the application in the Google Assistant Test console or any other Google devices you may have.

IMPORTANT: To call external APIs such as Umbraco Heartcore, you need to have a paid firebase package. You would need to go to the Usage and Billing section in your Firebase project and change it to use a Pay as you Go plan.

The most important part of this implementation is the options used to make an API request to Umbraco Heartcore.

var options = {
  method: 'POST',
  uri: 'https://cdn.umbraco.io/content/filter',
  headers: {
    'umb-project-alias': 'your-project-alias',
    'umb-nocache': 'true',
    'Content-Type': 'application/json'
  },
  body: {
    'contentTypeAlias': 'product',
    'properties': [{
    'alias': 'isOnSpecialToday',
    'value': '1',
    'match': 'LIKE'
    }]
  },
  json: true
};

The full code can be found here - https://github.com/emmanueltissera/umbraco-heartcore-omnichannel/tree/master/no-ui

Feature Alert

Umbraco Heartcore’s Content Delivery AP allows you to retrieve published content items via the CDN. In the above example, we are using the Content Filter endpoint to bring in the specials for the day.

Smart Display

Jordan is eating his breakfast. He can’t stop thinking about the Lamingtons. So he shouts out to the Google Nest Hub in the kitchen as he wants to see today’s specials.

This is what he sees:

Smart Display Implementation

Once again the previously used Google Dialogflow sample responds with a card when it is accessed via the Google Nest Hub. It allows us to respond with a Title, text and an image.

agent.add(new Card({
  title: specialTitle,
  imageUrl: specialImage,
  text: specialMessage
}));

Feature Alert

Heartcore ships with Content Delivery Network (CDN) capabilities using Cloudflare. This provides you with a stable platform as well as fast delivery of your content to any frontend and users - wherever in the world they might be! So displaying an image on your smart display is easy-peasy.

Web Channel

Jordan is in school and it’s a few hours before he could go get his Lamingtons. Just before school starts he jumps on his mobile to see what’s on for sale.

He even manages to use his laptop during the first break to check out the site.

Then he sneaks a look on his tablet during his Arts lesson.

Web Channel Implementation

The website uses the Umbraco Heartcore .NET Standard client to display content which can scale for multiple devices.

The code to run it is available on this repo. You can also have a look at the website at heartcore.lordlamington.com.

Bonus Implementation

Heartcore also offers the newly minted language variant feature of Umbraco 8 and it can be seen on this Sinhala variant of the site.

Feature Alert

Heartcore has two open-source client libraries which allow you to get started fast. This particular website uses the .NET Standard client, but there is a Node.js client available too.

The URL routing feature provided out of the box makes Heartcore stand out from the crowd when it comes to Headless CMSs.

IoT Powered Display Screen

Finally, school is out and Jordan gets to the Lamington shop. In the shop, there is a display screen which shows all the available Lamingtons. There's also a Raspberry PI is connected to the screen.

IoT Powered Display Screen implementation

  • This display screen runs off a Raspberry Pi running Raspian Buster. You can follow this article on how to set up a Kiosk using Chromium.
  • Then you will set up a static HTML page served using GitHub pages.
  • The static page will load and the Heartcore content will be pulled via a JQuery AJAX request from the client browser. The AJAX request is crafted so:
$.ajax({
  type: "GET",
  url: "https://cdn.umbraco.io/content/type?contentType=product&page=1&pageSize=3",
  dataType: "json",
  headers: {
    "Accept-Language": "en-AU",
    "umb-project-alias": "your-project-alias"
  },
  success: processData,
  error: function() {
    showAlert("JSON call to CaaS failed - retrieve slides");
  }
});

The complete code for the implementation of the static page can be found here - https://github.com/emmanueltissera/umbraco-heartcore-lamington/tree/master/display

Spreadsheet Magic

As Jordan goes to pay for the Lamington he ordered, he sees the cashier looking at a spreadsheet on his desk. It seems to have information about all the Lamingtons and their stock.

Spreadsheet implementation

Having the content from your CMS display on a spreadsheet is super awesome. You can take inspiration from this Medium article on how to consume a JSON API using Google sheets.

Once you have the initial script set up according to the instructions in the article, use the following formula in cell A1 to display the data:

=ImportJSON("https://cdn.umbraco.io/content/type?contentType=product&umb-project-alias=your-project-alias", "/_embedded/content/_updateDate,/_embedded/content/title,/_embedded/content/description,/_embedded/content/price,/_embedded/content/quantity,/_embedded/content/isOnSpecialToday,/_embedded/content/image/_url", "noInherit,noTruncate,allHeaders")

The Lamington Inventory is available as a shared document for you to copy and enjoy. You will need to add a few other formulas to cleanse the data and show resized images.

Feature Alert

Umbraco Heartcore offers an image manipulation service on the CDN. In the spreadsheet, retrieved images are resized to 100 pixels in width by just adding an extra query string parameter.

Tweet Tweet

Jordan got his Classic Lamington and was able to eat it too. But early next morning before he could holler at his Google mini, he sees a tweet from Lord Lamington.

Jam and Vanilla Lamington on special today. 21 baked fresh just now. Come and grab one! See lordlamington.com for more mouth-watering delicacies.

Social Media Implementation

To implement the social media integration, you can spin up an Azure function which listens to a webhook call from Umbraco Heartcore.

  1. First, register your App on Twitter
  2. Use the code from this location and build an Azure function
  3. Copy the keys and tokens from the Twitter App to the Azure configuration
  4. You can use the sample webhook call to test out the Azure function locally
  5. Once you are happy it's working deploy the function to Azure from Visual Studio
  6. Setup a webhook on Umbraco Heartcore to call the endpoint on your Azure function

Feature Alert

Umbraco Heartcore comes with Webhooks inbuilt. For this implementation, we have used a webhook to call an Azure function whenever an item is published.

All roads lead to Rome

All roads lead to Rome, or in this case, all channels lead to the Lamingtons. The content pushed from a single source allows Lord Lamington to target their customer no matter what channel they consume

We have only looked at the implementation across a few channels, such as:

  • No-UI
  • Smart Display
  • Web for PC, Tablets and Mobile
  • IoT powered screen
  • Spreadsheets
  • Social Media

But there are other channels which you could tap into such as:

  • Native mobile apps
  • Desktop applications
  • Point of Sale (PoS) systems
  • Remarketing automation to serve content via Google Ads or Facebook Ads
  • Enterprise systems for managing products and inventory

You might be wondering if a traditional CMS cannot achieve what you just did. It can. But it would involve weeks of custom development and ongoing maintenance to provide what Umbraco Heartcore provides out of the box. For more details watch this episode of Umbraco Virtual where the benefits of headless CMS over a traditional one are explained.

The premise of Umbraco Heartcore is that you create, manage and work with content in the Umbraco back-office and then you use the API endpoints to distribute the content wherever you want. With this article you see that happening across various channels with practical code samples.

Want to define your own omnichannel experience? Start with a trial of Umbraco Heartcore.

Emmanuel Tissera

Emmanuel is a Umbraco Certified Master and the co-organizer for the Melbourne Umbraco meet-ups. He is currently a Technical Lead at Luminary with almost 18 years of professional experience including six years at Emirates airline. Emmanuel is passionate about content localisation, content management systems, and content as a service. He's been working with Umbraco since 2009. In his spare time, Emmanuel could be either found on a ladder repairing a mess of his own making or reading fiction by the fireplace.

comments powered by Disqus