Creating an Alexa skill is like cooking a delicious meal. There are many recipes to choose from and several ingredients that go into each one. The Alexa Skill-Building Cookbook on GitHub gives you the recipes and ingredients to build engaging Alexa skills, using short code samples and guidance for adding features to your voice experience. With each installment of the Alexa skill recipe series, we’ll introduce you to a new recipe that can help you improve your voice design and skill engagement. You’re the chef. Let’s get cooking!
When a customer enables your Alexa skill, your skill can use the Device Address API to request permission from the customer to use address data associated with their Alexa device. You can then use this address data to enhance the voice experience.
For example, using this address information, your skill could provide a list of nearby store locations or restaurant recommendations, deliver food and groceries to a customer’s home, or provide directions to a nearby gym.
It’s important to note that this is not the GPS location of the device, but rather the address configured by the customer in their Alexa app settings. Also, the device address is not automatically available to a skill by default. Your skill needs to request permissions from the customer by presenting a card on the Alexa app, along with a helpful voice response. For example:
User: Alexa, ask food buddy for restaurant recommendations.
Alexa: Sure. I need your permission to access your zip code to get some yummy recommendations based on your address. I’ve sent a card to your Alexa app that you can use to grant the permissions to this skill to access your zip code.
User: <Opens up the Alexa app, and grants the permission using the card sent by the skill.>
Once the customer has granted the permissions through the Alexa app, they can go back to interacting with Alexa and getting the location-specific information back from your skill.
User: Alexa, ask food buddy for restaurant recommendations
Alexa: Here are some recommendations based on your location, …
As you can see from this simple conversation above, when a user enables a skill with the Alexa app that wants to use location data, the user will be prompted to provide consent for location data to be made available to the skill. It is important to note that when a user enables a skill via voice, the user will not be prompted for this information and the default choice will be "none." In this case, you should use cards to prompt the user to provide consent using the Alexa app.
There are two levels of location data your skill can request permissions from customers for:
Let’s see how we can achieve the sample conversation above using the Node.js SDK. We will begin by breaking down the several parts into steps, and then bring them all together in an encompassing “device address” recipe at the end of this post.
Step 1: Configure your skill in the developer console to indicate that it requires address information.
The first thing we need to do is, enable Device Address for our skill in developer console.
For this example, let’s assume that we need the "Full Address.” So, we choose that as shown in the screenshot below:
Step 2: Request permission through voice and cards.
We are now ready to write some code to request permissions from the user. When the customer launches the skill, Alexa should respond back with a helpful message like "Please grant skill permissions to access your device address.” It should also send a card to the customer’s Alexa app that they can use to grant our skill the permissions.”
Here’s how we can do this using the Alexa Node.JS SDK:
//generate the voice response using this.response.speak
this.response.speak('Please grant skill permissions to access your device address.');
const permissions = ['read::alexa:device:all:address'];
this.response.askForPermissionsConsentCard(permissions);
this.emit(':responseReady');
To generate a helpful voice response, we use Alexa Node.js SDK’s askForPermissionsConsentCard() method to generate the permissions card for us, and pass it the permissions we need as a parameter.
Understanding Permissions Scope
Permissions is a list of scope strings that match the scope that we declared for the skill on the Configuration page in the Amazon developer portal in step 1. In this case, it’s read::alexa:device:all:address. If the request was for the country and postal code, then the permissions value in this response will be read::alexa:device:all:address:country_and_postal_code.
As a general rule, you should include only those Alexa permissions that are both needed by your skill and that are declared in your skill metadata on the Amazon developer portal.
Device Address Permissions on the Developer Console | permissions = |
Full Address | ['read::alexa:device:all:address’] |
Country & Postal Code Only |
['read::alexa:device:all:address:country_and_postal_code’] |
Now we are all set with part 1 and requesting permissions from the customer. We are now ready to obtain the permissions granted by the user, and use the address data to deliver the appropriate response based on their location. Let’s do that now in part 2.
Now that we have requested the permissions from the customer (and hopefully, the customer has granted those permissions through the Alexa app), we now need to call the Device Address API to retrieve those permissions, and use that to get the address data of the customer.
Step 1: Get the deviceId and apiAccessToken from the JSON request.
To call the Device Address API, we need the device ID (deviceId) and the API access token (apiAccessToken). This is included in the JSON requests sent to your skill.
Each JSON request sent to your skill includes the device ID (deviceId). And regardless of whether the user granted your skill the permissions needed to fulfill the request, it also includes an API access token (apiAccessToken), which encapsulates the permissions granted to your skill.
Here’s an example of a request that your skill may receive:
Using the Alexa Node SDK, we can grab these values with the following code:
const token = this.event.context.System.apiAccessToken
const deviceId = this.event.context.System.device.deviceId;
Step 2: Obtain the endpoint for the Device Address API.
Next, we need the endpoint for the Device Address API. The endpoint for the Device Address API varies depending on the geographic location of your skill. You can get the correct base URL to use from the apiEndpoint value in the System object: context.System.apiEndpoint in the JSON request (see request above).
Using the Alexa Node SDK, we can grab the API endpoint with the following code:
const apiEndpoint = this.event.context.System.apiEndpoint;
Step 3: Call the Device Address API.
Once we have obtained the deviceId, the apiAccessToken, and the apiEndpoint from the JSON request, we are ready to call Device Address API, and get the address data for our customer. Here’s the code to do just that:
const das = new Alexa.services.DeviceAddressService();
das.getFullAddress(deviceId, apiEndpoint, token)
.then((data) => {
this.response.speak('<address information>');
console.log('Address get: ' + JSON.stringify(data)); //print log to Amazon CloudWatch
this.response.speak("You are in " + data.city);
this.emit(':responseReady');
})
.catch((error) => {
this.response.speak('I\'m sorry. Something went wrong.');
this.emit(':responseReady');
console.log(error.message);
});
We create an instance of "DeviceServiceAddressService" built into the Alexa Node SDK, and then use that to call the getFullAddress() method (or getCountryAndPostalCode() method if you were requesting country and postal code only). This returns the following JSON string that we use to create our response (data.city):
{
"addressLine1": "7 W 34TH ST 6TH FLOOR",
"addressLine2": null,
"addressLine3": null,
"districtOrCounty": null,
"stateOrRegion": "NY",
"city": "NEW YORK",
"countryCode": "US",
"postalCode": "10001-8100"
}
Here is the all-encompassing recipe that you can use from one of your intent handlers to request device address permissions (part 1) and obtain the address data of the customer (part 2).
'DeviceAddressIntent': function () {
console.log(JSON.stringify(this.event));
if (this.event.context.System.user.permissions) {
const token = this.event.context.System.user.permissions.consentToken;
const apiEndpoint = this.event.context.System.apiEndpoint;
const deviceId = this.event.context.System.device.deviceId;
const das = new Alexa.services.DeviceAddressService();
das.getFullAddress(deviceId, apiEndpoint, token)
.then((data) => {
this.response.speak('<address information>');
console.log('Address get: ' + JSON.stringify(data));
this.response.speak("You are in " + data.city);
this.emit(':responseReady');
})
.catch((error) => {
this.response.speak('I\'m sorry. Something went wrong.');
this.emit(':responseReady');
console.log(error.message);
});
} else {
this.response.speak('Please grant skill permissions to access your device address.');
const permissions = ['read::alexa:device:all:address'];
this.response.askForPermissionsConsentCard(permissions);
console.log("Response: " + JSON.stringify(this.response));
this.emit(':responseReady');
}
}
The only one new thing we have added in this recipe is the if/else statement, just to check if the user has granted us permissions. If they have, the “permissions” property will be included in the JSON request. In the GIF below, you can see that the permissions property is included in the JSON request sent to your skill after the permissions have been requested from the customer.
For more recipes, check out the skill recipe series on the Alexa blog or visit the Alexa Skill-Building Cookbook on GitHub.
Every month, developers can earn money for eligible skills that drive some of the highest customer engagement. Developers can increase their level of skill engagement and potentially earn more by improving their skill, building more skills, and making their skills available in in the US, UK and Germany. Learn more about our rewards program and start building today. Download our guide or watch our on-demand webinar for tips to build engaging skills.