Welcome to the second blog post of our Getting Started series! Through this series, we aim to help you build great Cortana Skills, that will enable millions of users to get stuff done using Cortana, their trusted personal digital assistant.
If you haven’t already, check out out first blog post on how you can quickly get started with creating and interacting with a Cortana Skill in under an hour!
In this post, we are going to look at how you can personalize user interactions with your Skill by requesting and leveraging the user profile and contextual information from Cortana’s Notebook. All that with user consent, of course!
Cortana uses the Notebook as a repository for user profile information like user’s name, lists, reminders, favorite places, different services the user has connected to, etc. The Notebook also contains some contextual information that Cortana has discovered about the user and changes more frequently, such as their location. Users can navigate to the Notebook (on Windows, select Cortana on Start , then select Menu > Notebook) and provide more information to get better, more personalized help from Cortana.
As part of the Cortana Skills Kit, we have enabled developers to request for some of this information (six data points to be precise, with more coming) to personalize user interactions with their skills. Read below for a step-by-step guide on how to go about this.
Step 1: Request User Profile Data from Cortana
(Go through Step 1 to 3 from our first blog post if you never built a skill before. Follow-on when you are finishing up Step 4 there.)
When you are configuring your bot for the Cortana channel, you can request for the specific user profile data you would like access to. Click on Add a user profile request, Select Data and then select the user profile information you need from the drop-down list.
Let us select two data points – the user’s name (User.Info.Name) and the user’s current location (User.SemanticLocation.Current) from the list. We will assign them friendly names, userName and userLocation respectively, for easy reference in the code.
Click Save.
Step 2: Grant Cortana the permission to share this info with your skill
Now that you have requested for this permission, each user invoking the skill will be asked if they are fine with Cortana sharing this information with your skill. Granting permission is a one-time process and needs to be done the first time a user invokes the skill.
Before you try to invoke the skill on Cortana across Windows, Android or iOS apps, ensure that you are signed into Cortana with the same MSA as you created the skill & that your region settings for the device are set to en-US.
Go ahead and say “Hey Cortana! Open <invocation name>”.
If the user does not grant permission to share all the requested information, the skill is not invoked and no data sent. Therefore, you should only request for data you absolutely require for the functionality of your skill.
Step 3: Leverage profile info to personalize your skill
Once you have granted permission, go back to your bot code (the BUILD tab if you are using the Azure Bot Service and the run.csx or index.js file depending on if you selected C# or node.js).
Edit the switch-case statement to the following (for run.csx):
switch (activity.GetActivityType()) { case ActivityTypes.Message: var client = new ConnectorClient(new Uri(activity.ServiceUrl)); var reply = activity.CreateReply(); var userInfo = activity.Entities.FirstOrDefault(e => e.Type.Equals("UserInfo")); if(userInfo != null) { var userName = userInfo.Properties["userName"]["GivenName"].ToString(); if (!string.IsNullOrEmpty(userName)) { reply.Text = "Hello " + userName + "! "; } var currentLocation = userInfo.Properties["userLocation"]; if (currentLocation != null) { log.Info($"location found!" + currentLocation["Hub"].ToString() + "!!"); var address = currentLocation["Hub"]["Address"].ToString(); if (!string.IsNullOrEmpty(address)) { reply.Text += "Thank you for checking in from " + address + ". "; } } } else reply.Text = "Hello anonymous! "; reply.Speak = reply.Text; await client.Conversations.ReplyToActivityAsync(reply); break; case ActivityTypes.ContactRelationUpdate: case ActivityTypes.Typing: case ActivityTypes.DeleteUserData: case ActivityTypes.Ping: default: log.Error($"Unknown activity type ignored: {activity.GetActivityType()}"); break; }
In the code above, we are first looking for the Entities passed on by Cortana with each message from the user, specifically the UserInfo entity. In this entity, we will find the two pieces of information we requested from Cortana – the userName and userLocation. (Tip: Test your skill by requesting for all available data points and see which ones you can leverage for your skill.)
Once we get the data, we verify that it is not empty. Users might sometimes not share the required data with Cortana as well – so they can turn up empty – and error handling becomes important here.
Then, we personalize the Hello message to include the user’s given name and address string as they are available.
Now, go back and invoke the skill again by saying – “Hey Cortana! Open <invocation name>”. You should see the custom personalized greeting message.
A nice personal touch!
You can read up more information available on our documentation for this topic. You can also check the reference for user profile and contextual information that is shared as entity data.
Please let us know below if you have any questions. We would also love to hear about specific topics for blogs that you would like to see and we would be happy to oblige! We have more blogs coming that discuss how we can deep link to client side apps from Cortana Skills, debug skills locally, test with a group of users and finally how to publish the Skill for the millions of Cortana users in the US.
Have a great day!
– The Cortana Skills Kit Team.