Inspiration

I've been a big fan of the WeThePeople project since the Obama Administration released it in 2011. The platform allows citizens to create and sign petitions on petitions.whitehouse.gov. Once a petitions reaches 100,000 signatures it becomes eligible for an official response from the White House. With the change in administration, I was happy to see that this system continued to be used and garner official responses from the Oval Office. When Amazon announced the Tech for Good competition, I realized it would be a great opportunity to apply with WeThePeople for an API key. Once I got approved and received an API key, I created a skill that would enable petition discovery, voice-based signing, and ongoing tracking of signed petitions. I think this is a fantastic chance to increase direct line access to the White House!

What it does

Users who enable the skill can search for top petitions on issues that matter to them. Once they find an issue that they want to support, they can ask Alexa to sign it for them. In order to sign petitions, users must link their Amazon account, giving the skill access to their name and email. After a user has signed a petition, they can check the skill for updates about their signed petitions, and can be sent official responses once released by the White House.

How I built it

I used serverless as a framework to develop the skill. The process was much easier than when I built my last skill in 2015 by constantly uploading .zip files to AWS Lambda directly. Serverless makes describing a deployment and managing your Lambda functions simple. As an example, here's my serverless.yml file, which completely describes the access and connections that need to be made on AWS:

service: makingADifference

provider:
  name: aws
  runtime: nodejs8.10
  region: us-east-1
  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - dynamodb:Query
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
      Resource: "arn:aws:dynamodb:us-east-XXX:table/MakingADifference"

functions:
  makingADifference:
    handler: handler.makingADifference
    alexaSkill: amzn1.ask.skill.XXX

I used DynamoDB to persist simple key/value user state. A major pro-tip if you're building a skill in Node.js: use the alexa-sdk library. It has features that make things like storing state pretty mindless. My mind was blown when I saw how easy it was to connect DynamoDB for user attribute storage.

The user can also share petitions after they have been signed. I connected to SendGrid and used dynamic templates to send these sharable messages.

After I finished the skill, I spent as much time testing it as I did building it. I found that I needed to create a few "undocumented" intents. An example of this is I heard one of my test users saying "Go back", so I built an intent that lets users traverse lists of petitions in the opposite direction, even though they would never know about this functionality in the skill unless they asked for it.

Challenges I ran into

One of the biggest challenges I ran into was search. The search on the WeThePeople API is basic: the search term must show up in the title for it to return a result. This made it very difficult to find petitions in an expected way. As a consequence, I built my own local search that would override a WeThePeople API if it matched a popular category. Here's the function that gets run periodically to create those search categories:


'use strict';

const apiBase = 'https://api.whitehouse.gov/v1/';
const request = require('request');
const fs = require('fs');

function getTopPetitions (cb) {
  const url = apiBase + 'petitions?limit=100&isSignable=1&sortBy=signature_count&sortOrder=desc';
  request.get(url, (err, resp, body) => {
    if (err) return cb(err);
    try {
      const petitions = JSON.parse(body);
      return cb(null, petitions.results);
    } catch (e) {
      return cb(e);
    }
  });
}

const categoryOverride = {
  'Economy & Jobs': 'the economy',
  'Innovation: Arts & Technology': 'the arts',
  'Budget & Taxes': 'taxes'
};

module.exports = (cb) => {
  getTopPetitions((err, petitions) => {
    if (err) return cb(err);
    let categoryMap = {};
    petitions.map(p => {
      let categories = p.issues.map(i => { return (categoryOverride[i.name] || i.name.split('&')[0].trim()).toLowerCase(); });
      categories.forEach(c => {
        categoryMap[c] = (categoryMap[c] || []).concat([{
          id: p.id,
          title: p.title,
          signatureCount: p.signatureCount,
          url: p.url
        }]);
      });
    });
    return fs.writeFile('./topSearches.json', JSON.stringify(categoryMap), cb);
  });
};

This function created a flat .json file with all the top petitions matched to a category tag added by users when they create the petition. If the search term given by the user matched any of these categories, I load from the local search instead of using the WeThePeople API search.

Accomplishments that I'm proud of

I'm most proud of the general UX of this skill.

There are a lot of edge cases when it comes to the petitions. For example, there are many petitions that got created and didn't get quite enough support, so closed without response. In these cases, you can't actually sign the petition. The issue is still important to the user, so instead they get sent an email summary of the petition that they can share, and maybe the petition will be reopened (or they can create a new one!)

I also spent a lot of time thinking through the UX around how you iterate through lists of petitions without getting confused or losing your place. Even when I thought I structured the copy in a way that made sense to me, the people who helped me test could easily find where I fell short. There aren't any books and not many articles on Voice UX, so it's definitely learn-as-you-go!

What I learned

There is a petition to erect a statue to Paul Flart a security guard who filmed his farts for 6 months before getting fired.

What's next for Making a Difference

If Making a Difference ends up having a pulse, I will be building out a much more robust alerting system, so that people can get periodic email updates about their petitions' progress and know when there are any updates available. I will also work on improving the way that petitions can be shared between multiple Alexa users, so that you can see the issues that matter to your family and friends as well.

Thank you for your consideration!

Built With

Share this project:

Updates