Alexa Display Template Skill Deep Dive Part 7: Persisting Data With Session Attributes In Alexa Skills

My Alexa Display Template Skill Design & Coding Deep Dive series continues with a look at persisting data in-session by using session attributes in Alexa skills.

 

Show Me The Data

 

State Management vs. Session Attributes vs. Database

There seems to be some confusion among developers about when to use a database vs. when to use state management vs. when to use session attributes.

State management isn’t really a tool for use in data persistence. Rather, it’s a tool to use when you need the same spoken intent to fire different functions or to deliver different responses depending on where the user is in the session. For example, in a quiz game skill you might want to prompt the user to say “yes” to continue after the skill outputs a welcome message, but later on you want “yes” to be among the possible quiz answers (e.g., some of your questions are yes/no). State management allows for multi-purpose spoken intents. This Alexa Developer Blog post goes into more detail about what State Management is and how to implement it in Alexa skills.

A database is generally the right choice for persisting data across sessions: when you need to persist user data, such as a game score or quiz progress, so the user can pick up where he left off the next time he invokes your skill. This free tutorial from Big Nerd Ranch covers how to use AWS DynamoDB to persist Alexa skill data across sessions.

Session attributes are basically a way of attaching pieces of data to your requests and having the Alexa service send those same pieces of data back to your skill in its responses. The Alexa service accepts and relays the data you want to persist in a container called sessionAttributes, which takes the form of a json array of name: value pairs.

 

Declare A Session Attribute Container

The first step in using session attributes is to create the container in your code as a declared variable. In my Visual Tarot javascript code I do this in a NewSession function, as follows:

var sessionAttributes = {};
sessionAttributes = this.attributes;

Note the curly braces in the var declaration statement. This signifies the variable will take the form of a json array, not a standard javscript array.

Now that the container exists, it will automatically be sent to the server in any request coming out of the function where the container is declared — in this case, the NewSession function.

 

Add Attributes To The Container

Now that the container exists, adding data to it is as easy as setting a new variable equal to the data you need to persist using this type of statement:

sessionAttributes[‘attributeName’] = attributeValue;

In the above statement, attributeName is whatever name you want to use for tracking this specific bit of data.   attributeValue is a generic stand-in for the data itself, which could be an actual value or the result of a calculation. Here’s another example, taken directly from the NewSession function in Visual Tarot, which is used to store the result of a virtual coin toss and store it as a session attribute named “tcFlipOne”:

sessionAttributes[‘tcFlipOne’] = Math.floor(Math.random() * 2);
console.log(‘tcFlipOne is set to ‘ +sessionAttributes[‘tcFlipOne’]+ ‘. ‘);

 

Refer To Attributes Like Variables Within The Function Where They Are Declared

Within the function where it was declared, a session attribute works the same as any other variable. You can access it by reference for use in other calculations within that function. In this case, I have an array containing images from a deck of cards, where rows containing an upright image of each card alternate with rows of upside-down, or “reversed” images of the same cards. Think: Ace of Spades, Ace of Spades reversed, King of Spades, King of Spades reversed, etc. etc.

Here, I’m using the value that was saved to sessionAttributes[‘tcFlipOne’] to determine whether the upright (odd-numbered row) or reversed (even-numbered row) version of the card should be pulled from the card array.

if (sessionAttributes[‘tcFlipOne’] == 0) {
random3_1 = newArray3[0]; // KEEP INDEX AS UPRIGHT VERSION
} else {
random3_1 = parseFloat(newArray3[0]) + 1; // INCREMENT BY ONE TO SET INDEX TO REVERSED VERSION
}

 

Accessing Attributes Across Functions

Again, once the sessionAttributes object has been declared it will automatically attach to any Alexa request generated by the same function, and will be sent back in the subsequent Alexa response. However, unless you’ve declared your sessionAttributes variable as a global object, you must declare a fresh container for it in any function where you need to access the data stored there. In this example, because I declared my sessionAttributes object within the NewSession function I must create the sessionAttributes object in every other function where I need to reference its members.

By using the same name the sessionAttributes naming convention throughout my skill code, I ensure that any reference to that object in my code is a reference to the sessionAttributes json array that’s coming back to my skill in the response. Just put these statements near the beginning of any function where you need access to sessionAttributes data members:

var sessionAttributes = {};
sessionAttributes = this.attributes;

Now, accessing members of the sessionAttributes array within the same function is as simple as using a statement like this one:

var someVariable = sessionAttributes[‘attributeName’];

Personally, I find it helpful to name my local variables the same as I’ve named the corresponding sessionAttribute. Here’s an actual line from the Visual Tarot code that follows the above format:

var ccEight = sessionAttributes[‘ccEight’];

 

Updating Attribute Values

Changing the value of a sessionAttribute data member you’ve already declared is as simple as setting that attribute equal to a new value, like this:

this.attributes[‘attributeName’] = someNewValue;

Note that if someNewValue is a text string I’d need to surround it with quotation marks, as per usual. This is an easy technique to use for incrementing a counter each time a given a given function fires, and there are plenty of other great uses for it as well.

 

Clearing Attributes At Session Close

Data from sessionAttributes has a tendency to hang around on the server side for minutes to hours after your skill’s session has closed for a given user. This means that the next user to fire up your skill could get a pre-existing sessionAttributes data member from a prior session rather than a freshly-calculated, new data member. For this reason, you need to include a SessionEndedRequest or onSessionEnded function in your skill, and ensure any sessionAttributes values your skill has created or assigned are cleared out in that function.

Recall that unless you’ve declared the sessionAttributes variable object globally, you will need to declare it as a local variable within the ‘session ended’ function in order to pull in any existing attributes, just the same as you would in any other function:

var sessionAttributes = {};
sessionAttributes = this.attributes;

There are a number of ways to clear out the attributes from there. I simply set them all equal to a blank value using this type of statement:

this.attributes[‘attributeName’] = “”;

 

The deep dive continues next week.

 

Other Posts In This Series

Introduction

Sourcing Alexa Skill Content

A Look At The Visual Tarot Alexa Skill Code

Things That Kill Alexa Skills
A checklist of reasons why you might want to rethink your skill, or its design, before you get too deep into the build.

Mapping Alexa Skill GUI Flow

Alexa Skill Image Cheatsheet

Alexa Platform Changes

Using Alexa Display Template Directives