Turn your Umbraco website into an Alexa Skill!

Heads Up!

This article is several years old now, and much has happened since then, so please keep that in mind while reading it.

Users are consuming content in a variety of different formats on countless number of devices. Recently developers have been facing challenges in how we can get our content to them in these different formats to just the traditional website and importantly, how do we easily and consistently update content for these feeds. Hopefully this post will show how to do this for the Amazon Alexa platform but show how this could be easily applied to your chosen technology.

 

An Introduction to Alexa:

(If you already know the basics about Alexa skills, feel free to skip down a few paragraphs.)

I am sure you have heard of Amazon’s venture to AI world via the echo devices, even if not currently available in your country. The out the box functionality of these devices is pretty cool, but for me the really awesome part is that, as programmers, we can get it to some clever apps without having to do all the complicated language recognition stuff. Amazon does that for us and leaves us free to build the actual functionality of the app! The AI behind the system is called Alexa and these apps are called Skills.

There are several types of Alexa skills:

  • Smart home skills- Integrated with smart home devices to be controlled by Alexa. “Alexa, switch on the lights”, for example.
  • Video skills- Integrate with connected TVs to control what to watch. “Alexa, watch Wonder Woman”, for example.
  • Flash Briefing- Provider users with content from subscribed sources. “Alexa, what’s the news?”.
  • Custom skills- you can provide code in a choice of programming languages to do anything else you want to not covered by these other options. I have given a quick guide to building a custom skill integrating with Umbraco here.
  • Echo Show Skills- a new to the market version of the Amazon Echo that has a display. I haven’t looked into this much but I understand we can provide content for on the screen as well as the audio.

More details and getting started tutorials here.

For this tutorial, I want to focus on creating a news skill. A flash briefing is a way to get updates from feeds you have subscribed to via your Amazon echo. It’s usually headlines and then you can get more detail by using the Alexa app and clicking on a “read more” link on the card to read the full article. Most of the large news companies have one so you can ask “Alexa, what’s the news?” and you will get a collated list of your subscribed feeds read out to you.

So, where does the data come from for this? You can do it in RSS by pointing it at your existing RSS feed... but where’s the fun in that, eh? JSON is the prefered format from Amazon anyway so that’s the option I will discuss in this post. Here is some more info on the feed and the format it needs to be in.

Building your Alexa data feed:

Since flash briefing skills are a way to keep people up to date with content published in the last 7 days (using the update date in above api reference, after this Amazon don’t use it as it’s no longer news) so I thought it would be a cool proof of concept to be able to tell people about recently published blog posts. My blog is built in Umbraco so I decided to extend my repo to also provide content as a headless CMS for the Alexa skill JSON feed as well as the standard use of the content on the website blog.

When working on Alexa skills for clients, we try to keep the API content being controlled within the same CMS instance as the website. The client already use Umbraco for their website, so let’s not duplicate content updates needed but just supplement that data with anything needed for the new feed. So I decided to try this for my site too.

My site structure is a “BlogPostRepository” under the homepage which then contains many child nodes of type “Blogpost”. See screenshot:

 

Umbraco Doctype configuration:

 

I updated my Blog Post doctype to have extra fields to support this new feature. I decided to add a property to let me decide if this blog post should be included in my Alexa feed: “Include In Flash Briefing?”

I also added content fields specifically for use in this feed such as “Flash Briefing Title” and “Flash Briefing Main Text”. These could have been fed from existing fields in the CMS but I may want the Alexa headline to use different wording to the blog post introduction used on the site for example, so I made them separate.

The API:

I started off by creating a WebAPI endpoint within my exisiting Umbraco project, more info on this here.

 

As you can see from the code snippet, I created a webAPI controller inheriting from “UmbracoApiController” and implementing a call to get the flash briefing content.

Within this function I get the blog posts from the content tree and create a strongly typed model to represent my Alexa JSON structure. In production, I would use something like Ditto to do the mapping here, but I wanted to show clearly what is happening and not distract from the point of this post. Finally, I then serialise this object and then return it to the API.

public class FlashBriefingController : UmbracoApiController
    {
        public HttpResponseMessage GetFlashBriefing()
        {
            var root = UmbracoContext.ContentCache.GetAtRoot().FirstOrDefault();
            var blogPostRepo = root.Children.Where(x => x.DocumentTypeAlias == "BlogPostRepository").FirstOrDefault();
            var blogPosts = blogPostRepo.Children.Where(x => x.DocumentTypeAlias == "BlogPost").OrderByDescending(x => x.CreateDate);
            var newGuid = Guid.NewGuid();
            var modelList = new List<AlexaNewsBriefingResponseModel>();

            //loop through blogposts and return those that are selected to be in flash briefing.
            foreach (var blogPost in blogPosts)
            {
                if (blogPost.GetPropertyValue<bool>("includeInFlashBriefing") == true)
                {
                    
                    var alexaModel = new AlexaNewsBriefingResponseModel()
                    {
                        uid = "urn:uuid:" + newGuid,
                        updateDate = blogPost.UpdateDate.ToString("yyyy-MM-dd'T'HH:mm:ss'.0Z'"),
                        titleText = blogPost.GetPropertyValue<string>("flashBriefingTitle"),
                        mainText = blogPost.GetPropertyValue<string>("flashBriefingMainText"),
                        redirectionUrl = blogPost.UrlWithDomain(),
                        streamUrl = null // defaults to null
                    };

                    if (!String.IsNullOrEmpty(blogPost.GetPropertyValue<string>("flashBriefingAudioFile")))
                    {
                        //Set the streamUrl if an audio file has been given. 
                        //If this is provided, Amazon use this over the text.
                        var nodeId = blogPost.GetPropertyValue<int>("flashBriefingAudioFile");
                        alexaModel.streamUrl = HttpContext.Current.Request.Url + UmbracoContext.MediaCache.GetById(nodeId).Url();
                    }

                    modelList.Add(alexaModel);
                }
            }

            //Serialise to JSON
            string output = JsonConvert.SerializeObject(modelList);
            HttpContext.Current.Response.ContentType = "application/json";
            HttpContext.Current.Response.Write(output);

            return new HttpResponseMessage();
            
        }
    }

So let’s put this all together…

Here is a new blog post, configured in Umbraco to show in the Alexa feed.

 

And here is the JSON returned from the the API:

[  
   {  
      "uid":"urn:uuid:334f3990-03bc-473d-8c01-d00f010dd340",
      "updateDate":"2017-10-24T22:49:00.0Z",
      "titleText":"Code Craft Conf 2017",
      "mainText":"On 15th September I went along to Citizen M Glasgow to spend the day with about 60 other developers chatting about code! I was a guide for a conversation about mental health within the tech industry.For a wee overview of what happened on the day, click on the link within the Alexa app.",
      "redirectionUrl":"http://carolelogan.net/blog/codecraftconf-2017/",
      "streamUrl":null
   }
]

You are probably wondering “Carole, you said we were making an Alexa skill, this is just an API” … so, we have an API controlled in Umbraco but Alexa can’t get this to users without actually setting up a skill!

 

Alexa Flash Briefing configuration:

So, now we have our data feed but we need to actually tell Alexa how to find this! You can sign up to an Amazon developer account: https://developer.amazon.com/alexa and select the Alexa tab:

 

Now you can complete the forms to configure your skill to point at your JSON API. The Alexa portal will fetch the data when you do this to ensure it is reachable and is of a suitable data structure. You can now test this on your own device registered to your developer account and check that when you ask for your news, your posts are read out!

Here is the card shown in the Alexa app when I ask for my flash briefing.

As you can see, this is the content in CMS sent in JSON and the image is set in the skill configuration. Note: Interestingly, when making a custom skill you can define in your data response the image in the card but don’t seem to have this in flash briefing skill.

 

Should you want to submit you skill to be available to people to subscribe to (please let me know if you do!) then you will need to fill in a few more details like the name, description and keywords to let people find your skill.

 

** A few days later…**

Amazon accepted my skill! Here is my flash briefing skill where you can get any new blog posts in your Alexa news updates. You can see how the skill appears in the app store:

 

So, is an Alexa skill super useful for my wee blog? Probably not. But this was a good proof of concept of how we can do this for a news website or client blog without *too* much extra development.

TLDR; Already have an Umbraco blog? Turn this into an Alexa flash briefing skill within a few hours.

 

Any questions? Working on Alexa skills? Just want to say hello? Get me on @crgrieve

Carole Rennie Logan

Carole is on Twitter as