I have a big issue with Amazon’s ‘documentation.’ Trying to learn how to do anything is akin to sniffing your cat’s butt to find out where the dog is. It’s written from a mindset I don’t share, it rarely has practical and functional examples, and the font is maddeningly small.
How I learn best is by creating a “Hello World” type app. Even if it’s just copy and pasting, by doing that, my brain is able to follow the pathways and understand the logic steps.
If you’re like me and have been swearing at Amazon just trying to make a simple ‘Hello World’ app for your Echo, here we go.
The Outcome
To summarize what we want here, is we would like to be able to do is turn to our Echos and say this:
Hey Alexa, ask HalfElf what the last post is.
And we want Alexa to reply:
The last post on HalfElf was [Post Name]
This is really simple on purpose. While eventually we want to be able to ask for a post on a specific date, we’re not there yet. You’ve got to run before you can walk.
The Design
Designing your API requires forethought. In a previous post, I named my flash briefing URL /MYSITE/v1/alexa-skills/briefing
and, in keeping with that, this one will be named /MYSITE/v1/alexa-skills/last-post/
You’ll need to hang on to your URL – https://example.com/wp-json/MYSITE/v1/alexa-skills/last-post/
– as you will need to put this into your Amazon Skill. This will be a custom skill and you’ll need to have the intent look like this:
{ "intents": [ { "slots": [ { "name": "Date", "type": "AMAZON.DATE" } ], "intent": "HalfElf" } ] }
Remember, the goal is eventually to be able to use that date slot. We’re not right now, but be prepared, as Mr. Lehrer would say.
With that in mind, the sample utterances look like this:
HalfElf last post HalfElf post on {Date} HalfElf today's post HalfElf what the last post is
You’ll notice I’m trying to think of every which way someone might ask the question. You need to do this. Alexa is very picky.
The Rest API Code
Once you’ve built out your Amazon Skill (and yes, that really is the easy part), you have to have the response. This is built off the same model I used before, and can be slipped in and shared.
class MYSITE_Alexa_Skills { public function __construct() { add_action( 'rest_api_init', array( $this, 'rest_api_init') ); } public function rest_api_init() { register_rest_route( 'MYSITE/v1', '/alexa-skills/last-post/', array( 'methods' => [ 'GET', 'POST' ], 'callback' => array( $this, 'last_post_rest_api_callback' ), ) ); } public function last_post_rest_api_callback( $data ) { $response = $this->last_post(); return $response; } public function last_post() { $query = new WP_Query( array( 'numberposts' => '1' ) ); if ( $query->have_posts() ) { while ( $query->have_posts() ) { $query->the_post(); $lastpost = 'The last post on HalfElf was .' get_the_title(); } wp_reset_postdata(); } $response = array( 'version' => '1.0', 'response' => array ( 'outputSpeech' => array ( 'type' => 'PlainText', 'text' => $last_post, ), 'shouldEndSession' => true, ) ); return $response; } } new MYSITE_Alexa_Skills();
As I said, it’s pretty simple. The output looks like this:
{"version":"1.0","response":{"outputSpeech":{"type":"PlainText","text":"The last post on HalfElf was [POSTNAME]"},"shouldEndSession":true}}
This is not the most efficient way to grab one post, but for the purposes of this example, it does get your head around the basic idea.
Next Up?
There are two issues with this code. First of all, it doesn’t meet Amazon’s requirements. Secondly, it doesn’t accept parameters. The first issue is much bigger, because as it turns out, Amazon requires you to check if the requests are coming from Amazon, are valid, and aren’t a bot-net attack. This is actually very smart, but very annoying, since they don’t make it easy to figure out how to do all that.
But that’s next.
If you hear screaming from California, it’s just me.