Include a Card in Your Skill's Response
Interactions between a user and an Alexa device can include graphical cards displayed in the Alexa app that describe or enhance the voice interaction. A custom skill can include these cards in its responses.
To view the cards, open the Alexa app and navigate to the Activity page. Cards can also display on an Alexa-enabled device with a screen, such as an Echo Show, if your skill doesn't include content specifically intended for the screen by using Alexa Presentation Language.
Overview of cards
Cards can enhance an interaction. For instance, voice responses need to be concise and "written for the ear". A card can provide additional, useful details that would make the voice response too verbose or too difficult to understand as speech. For example, this simple card provides additional details about the user's gift card balance:
The Alexa Skills Kit provides different types of cards:
- A
Simple
card displays plain text. You provide text for the card title and content. - A
Standard
card also displays plain text, but can include an image. You provide the text for the title and content, and the URL for the image to display. - A
LinkAccount
card is a special card type only used with account linking. This card lets users start the account linking process. - An
AskForPermissionsConsent
card is sent to the Alexa app when a skill requires the customer to grant specific permissions.
To send a card to the Alexa app, you include the card in the response your service sends back to Alexa. You typically only return cards when responding with the information the user requested. Other responses, such as questions to ask the user for more information do not normally include cards.
To view the cards, open the Alexa app and navigate to the Activity page.
For recommendations to design effective cards, see Best Practices for Skill Card Design.
Create a basic card to display text
The simplest cards consist of plain text. You provide the title and content and the Alexa app displays the card:
Note that the total number of characters (both title and content combined) for the card cannot exceed 8000.
To create a simple card, include the card
property in your JSON response:
- Set the
type
toSimple
. - Set the
title
andcontent
properties to the text to display. Use either "\r\n
" or "\n
" within thecontent
to insert line breaks.
This code example uses the Alexa Skills Kit SDK for Node.js (v2).
Use the speak
and withSimpleCard
methods on the ResponseBuilder
object to define the speech and card text. The getResponse()
method returns the response with the specified properties.
return handlerInput.responseBuilder
.speak("This is the text Alexa speaks. Go to the Alexa app to see the card!")
.withSimpleCard(
"This is the Title of the Card",
"This is the card content. This card just has plain text content.\r\nThe content is formated with line breaks to improve readability.")
.getResponse();
This code example uses the Alexa Skills Kit SDK for Python.
Use the speak
and set_card
methods on the ResponseFactory
object to define the speech and the card text in the response.
from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.utils import is_intent_name
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_model import Response
from ask_sdk_model.ui import SimpleCard
class HelloWorldIntentHandler(AbstractRequestHandler):
"""Handler for Hello World Intent."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return is_intent_name("HelloWorldIntent")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
speech_text = "This is the text Alexa speaks. Go to the Alexa app to see the card!"
card_title = "This is the Title of the Card"
card_text = "This is the card content. This card just has plain text content.\r\nThe content is formated with line breaks to improve readability."
return handler_input.response_builder.speak(speech_text).set_card(
SimpleCard(card_title, card_text)).response
This code example uses the Alexa Skills Kit SDK for Java.
Use the withSpeech()
and withSimpleCard
methods on the ResponseBuilder
object to define the speech and card text. The build()
method returns the response with the specified properties.
@Override
public Optional<Response> handle(HandlerInput handlerInput, IntentRequest intentRequest) {
String speechText ="This is the text Alexa speaks. Go to the Alexa app to see the card!";
String cardTitle = "This is the Title of the Card";
String cardText = "This is the card content. This card just has plain text content.\r\nThe content is formated with line breaks to improve readability.";
return handlerInput.getResponseBuilder()
.withSpeech(speechText)
.withSimpleCard(cardTitle, cardText)
.build();
}
This JSON response shows how you return a simple plain text outputSpeech
string. The response also includes a card that displays a title and simple content.
{
"version": "1.0",
"response": {
"outputSpeech": {
"type": "PlainText",
"text": "This is the text Alexa speaks. Go to the Alexa app to see the card!"
},
"card": {
"type": "Simple",
"title": "This is the Title of the Card",
"content": "This is the card content. This card just has plain text content.\r\nThe content is formated with line breaks to improve readability."
}
}
}
Create a card to display text and an image
A card can include a single image. In this case, you provide the title, text, and two URLs (a small version and large version) for the image to display.
Note that the total number of characters (title
, content
, and both URLs
combined) for the card cannot exceed 8000. Each URL cannot exceed 2000 characters.
To create a card with an image, include the card
property in your JSON response:
- Set the
type
toStandard
. - Set the
title
andtext
properties to the text to display.- Note that this type of card uses a
text
property, not acontent
property likeSimple
. - Use either "
\r\n
" or "\n
" within thetext
to insert line breaks.
- Note that this type of card uses a
- Include an
image
object withsmallImageUrl
andlargeImageUrl
properties. - Set
smallImageUrl
andlargeImageUrl
to the URLs of a small and large version of the image to display. See below for details about the image format, size, and hosting requirements.
{
"version": "1.0",
"response": {
"outputSpeech": {"type":"PlainText","text":"Your Ride Hailer car is on the way!"},
"card": {
"type": "Standard",
"title": "Ordering a Car",
"text": "Your ride is on the way to 123 Main Street!\nEstimated cost for this ride: $25",
"image": {
"smallImageUrl": "https://ridehailer.com/resources/card-images/race-car-small.png",
"largeImageUrl": "https://ridehailer.com/resources/card-images/race-car-large.png"
}
}
}
}
Image format and size
You can provide images in the following formats:
- JPEG
- PNG
Images should be less than 500 KB in size.
When including an image, you provide two URLs: a smaller resolution image and a larger resolution image. The different sizes are used when displaying cards on different sized screens:
Property | Description | Recommended Size (in pixels) |
---|---|---|
smallImageUrl |
Displayed on smaller screens | 720w x 480h |
largeImageUrl |
Displayed on larger screens | 1200w x 800h |
For best results on different screens that can display cards, provide both smallImageUrl
and largeImageUrl
. If you only provide one URL, the Alexa app uses that image regardless of the screen size where it is displayed. This may cause your cards to display poorly. For example, if you only provide smallImageUrl
, the Alexa app must scale up that image when displaying on larger screens, which could degrade the quality of the image.
Using images close to the recommended sizes ensures the quality of the image in the app. Smaller images may be scaled up to display in the app, which can degrade image quality. Large images take longer to load, so using images that are larger than necessary can slow the performance of rendering the cards in the app.
For instance, in this example, the Alexa app has scaled up a very small image:
Be sure to test your cards in the Alexa app (ideally on different devices with a variety of screen sizes) to ensure that the cards display well.
Hosting the images
The Alexa app loads the images from the provided URL at runtime. The image files you provide must be hosted on an HTTPS endpoint that meets the following requirements:
- Endpoint provides an SSL certificate signed by an Amazon-approved certificate authority. Many content hosting services provide this. For example, you could host your files at a service such as Amazon Simple Storage Service (Amazon S3) (an Amazon Web Services offering).
- The endpoint must allow cross-origin resource sharing (CORS) for the images. This allows the Amazon Alexa app to download the image for processing and validation before displaying it in the Alexa app.
To enable CORS, the image server must set the Access-Control-Allow-Origin
header in its responses. If you want to restrict the resources to just the Alexa app, allow just the origins http://ask-ifr-download.s3.amazonaws.com and https://ask-ifr-download.s3.amazonaws.com.
How you configure this depends on your image host. For example, if you host your images in an Amazon S3 bucket, you can configure the bucket with the following CORS configuration (shown in JSON):
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET"
],
"AllowedOrigins": [
"http://ask-ifr-download.s3.amazonaws.com",
"https://ask-ifr-download.s3.amazonaws.com"
],
"ExposeHeaders": []
}
]
For more about S3 and CORS, see Enabling Cross-Origin Resource Sharing.
Common issues when including images in standard cards
This section describes some common issues that may occur when you include an image in a Standard
card.
Blank space instead of image: This can occur for several different reasons:
-
Missing images: The image URLs you provide don't point to actual images, reference images that are not publicly available, or are URLs that have expired.
Note: If you use Amazon S3 to host your images, be sure to make them public and non-expiring. Some hosting solutions (including Amazon S3) allow you to set an expiration time on an image URL. In this case, the URL becomes invalid once that time passes. Since the Alexa app loads the image from the provided URL at runtime, the URL must always point to a valid image. Do not set an expiration time on the URLs you use for your images. - Image host not CORS-enabled: The server hosting your images is not CORS-enabled.
- Incorrect image format: The image URLs reference images that are not in one of the supported formats (
PNG
orJPEG
). - Image is too large: the file size for the image you provided is too large.
Card displayed with no image and no placeholder: This can occur if your response doesn't include an actual image object. The card is still displayed, but with no image.
For example, note the following JSON. This is specified as an Standard
card, but with no image
:
{
"version": "1.0",
"response": {
"outputSpeech": {"type":"PlainText","text":"Your Ride Hailer car is on the way!"},
"card": {
"type": "Standard",
"title": "Ordering a Car",
"text": "Your ride is on the way to 123 Main Street!\nEstimated cost for this ride: $25"
}
}
}
This creates a card that looks like this:
Define a card for use with account linking
Some Alexa skills require the ability to connect the identity of the end user with a user in another system. This is referred to as account linking, since the goal is to create a link between the Alexa user and the user account in your system.
If the user invokes an intent that requires this link and the link has not yet been established, the skill should send back a response directing the user to use the Alexa app to link their account. The card displayed in the app is a special card type that lets the user connect their account. Note that the account linking card is available in the main Home feed in the app, in addition to the Activity feed:
The card includes your skill icon and name. The "Link Account" button opens the authorization URI you configure in the developer console when setting up account linking for your skill.
To create an account linking card, include the card
property in your JSON response. Set the type to LinkAccount
and pass no other properties.
{
"version": "1.0",
"response": {
"outputSpeech": {"type":"PlainText","text":"Please go to your Alexa app and link your account."},
"card": {
"type": "LinkAccount"
}
}
}
The following examples show how to return a link account card with either the Alexa Skills Kit SDK for Node.js or the Alexa Skills Kit SDK v2 for Java.
This code example uses the Alexa Skills Kit SDK for Node.js (v2).
const OrderCarIntentHandler = {
// ...
handle(handlerInput){
// This intent requires an access token so that we can get the user's
// Ride Hailer user profile with payment information.
// The access token is in the Context object. Access the
// request in the HandlerInput object passed to the
// handler.
var accessToken = handlerInput.requestEnvelope.context.System.user.accessToken;
if (accessToken == undefined){
// The request did not include a token, so tell the user to link
// accounts and return a LinkAccount card
var speechText = "You must have a Ride Hailer account to order a car. " +
"Please use the Alexa app to link your Amazon account " +
"with your Ride Hailer Account.";
return handlerInput.responseBuilder
.speak(speechText)
.withLinkAccountCard()
.getResponse();
} else {
// Use the token to access the user's profile. This should also verify that the
// token represents a valid Ride Hailer user.
// ...
}
}
};
This code example uses the Alexa Skills Kit SDK for Java.
public class OrderCarIntentHandler implements RequestHandler {
// ...
@Override
public Optional<Response> handle(HandlerInput handlerInput) {
// This intent requires an access token so that we can get the user's
// Ride Hailer user profile with payment information.
// The access token is in the Context object. Access the
// request in the HandlerInput object passed to the
// handler.
String accessToken = handlerInput
.getRequestEnvelope()
.getContext()
.getSystem()
.getUser()
.getAccessToken();
if (accessToken != null) {
// Call a method to validate the token, get the user's Ride Hailer
// profile and order a ride
return orderCarForUser(accessToken, handlerInput);
} else {
// The request did not include a token, so tell the user to link
// accounts and return a LinkAccount card
String speechText = "You must have a Ride Hailer account to order a car. "
+ "Please use the Alexa app to link your Amazon account "
+ "with your Ride Hailer Account.";
// Build a response with output speech and a LinkAccount card.
return handlerInput.getResponseBuilder()
.withSpeech(speechText)
.withLinkAccountCard()
.build();
}
}
}
See Account Linking for Custom Skills for details.
Send a card to ask for customer permission
During a skill session, your skill can include the AskForPermissionsConsent
card to ask the user to grant permissions to the skill, such as access to Alexa lists or customer contact information.
Include the following values in the Card
object.
Property | Value |
---|---|
|
|
|
A list of permission scope strings. Include only those permissions that your skill metadata declared in the Alexa developer console. |
Related topics
- Best Practices for Skill Card Design
- Handling Requests Sent by Alexa
- Add Account Linking to Your Alexa Skill
- Configure Permissions for Customer Information in Your Skill
- JSON Interface Reference for Custom Skills
- Steps to Build a Custom Skill
Last updated: Sep 10, 2024