Check out what’s new from Firebase@ Google I/O 2021, and join our alpha program for early access to the new Remote Config personalization feature. Learn more

Spelling Practice Game using Google Assistant and Cloud Firestore

The Google Assistant developer platform lets you create software to extend the functionality of Google Assistant, a virtual personal assistant, across more than 1 billion devices, including smart speakers, phones, cars, TVs, headphones, and more. Users engage the Assistant in conversation to get things done, such as buying groceries or booking a ride. As a developer, you can use the Assistant developer platform to easily create and manage delightful and effective conversational experiences between users and your own third-party fulfillment service.

This codelab covers intermediate-level concepts for developing with Google Assistant, Cloud Functions, and Cloud Firestore. In this codelab, you'll build a game called "Spelling Practice" that uses Google Assistant to ask users to spell words.

What you'll build

In this codelab, you'll build a sophisticated game with the following functionality:

  • Receives spelling responses from the user and, depending on the value, modifies the conversational prompts
  • Responds with hints related to spelling the word, like its definition or repeating the word
  • Creates a game loop so a user can interact with the Assistant again after spelling the word

Before you start building, you can interact with the live Action on your Google Assistant-enabled device by saying "Hey Google, talk to Spelling Practice". The default path through this Action for a returning user looks like the following interaction:

When you've finished this codelab, your completed Action will have the following conversational flow:

2e9f94dc0ceafc96.png

What you'll learn

  • How to interact with Cloud Firestore
  • How to use slots to gather data from the user
  • How to process a user's input and return a response
  • How to use conditions to add logic to a scene
  • How to add a game loop

What you'll need

The prerequisites for this codelab include the following:

  • A web browser, such as Google Chrome
  • An IDE to write Cloud Functions.
  • A payment method. This codelab utilizes Cloud Functions for Firebase which requires your project to be on the Firebase Blaze pricing plan ( Learn more).
  • A terminal to run shell commands
  • Node.js 10 or later

Clone the GitHub repository from the command line:

$ git clone https://github.com/FirebaseExtended/codelab-actions-firestore

Create a Firebase project

  1. Sign in to Firebase.
  2. In the Firebase console, click Add Project (or Create a project), then name your Firebase project Spelling-Practice.

66ae8d1894f4477.png

  1. Click through the project creation options. Accept the Firebase terms if prompted. Skip setting up Google Analytics, because you won't be using Analytics for this app.

To learn more about Firebase projects, see Understand Firebase projects.

Upgrade to the Blaze pricing plan

In order to use Cloud Functions for Firebase, you'll need to upgrade your Firebase project to the Blaze pricing plan, which means you'll attach a Google Cloud Billing account to your project. This requires you to provide a credit card or other payment method.

All Firebase projects, including those on the Blaze plan, still have access to the free-usage quotas for Cloud Functions. The steps outlined in this codelab will fall within the free-usage limits. However, you will see small charges ( about $0.03) from Cloud Storage, which is used to host your Cloud Functions build images.

The Firebase CLI (command line interface) enables you to deploy your Cloud Functions.

There are several options for installing the Firebase CLI depending on your operating system and use case. The following steps describe the most common option if you're also using Cloud Functions.

  1. Make sure you've installed npm which typically comes with Node.js.
  2. Install or upgrade the CLI by running the following npm command:
$ npm -g install firebase-tools
  1. Verify that the CLI has been installed correctly by running:
$ firebase --version

Make sure the version of the Firebase CLI is 9.0.0 or later so that it has all the latest features required for Cloud Functions. If not, run npm install -g firebase-tools to upgrade as shown above.

  1. Authorize the Firebase CLI by running:
$ firebase login
  1. From the spelling-functions-start directory, set up the Firebase CLI to use your Firebase project. Run the following command, select your Project ID, then follow the instructions. When prompted, you can choose any Alias, such as codelab for instance.
$ firebase use --add

Now you'll add functionality using the Firebase SDK for Cloud Functions to build the backend for the game, Spelling Practice.

Cloud Functions allows you to have code that runs in the cloud without having to set up a server. This codelab will show you how to build functions that react to Firebase Authentication, Cloud Storage, and Firebase Realtime Database events. Let's start with Authentication.

When using the Firebase SDK for Cloud Functions, your functions code will live under the functions directory (by default). To make it easier for you, we've already created the functions/index.js file where your code will go. Feel free to inspect the functions directory before moving forward.

$ cd functions
$ ls

Your functions code is also a Node.js app, and therefore needs a package.json that gives some information about your app and lists dependencies.

If you aren't familiar with Node.js, it will help to learn more about it before continuing the codelab.

The package.json file already lists two required dependencies: the Firebase SDK for Cloud Functions and the Firebase Admin SDK. To install them locally, run npm install from the functions directory:

$ npm install

Let's now have a look at the index.js file:

index.js

/**
 * Copyright 2021 Google Inc. All Rights Reserved.
 * ...
 */
// TODO(DEVELOPER): Import the Cloud Functions for Firebase and Firebase Admin modules here. Also import the Actions SDK here.
// TODO(DEVELOPER): Write the getWordDetailsFromDictionaryAPI function here.
// TODO(DEVELOPER): Write the createSpellingPracticeWord function here.
// TODO(DEVELOPER): Write the app Handle getSpellingWordList function here.
// TODO(DEVELOPER): Write the app Handle getSpellingWord function here.
// TODO(DEVELOPER): Write the app Handle repeatSpellingWord function here.
// TODO(DEVELOPER): Write the app Handle definitionOfSpellingWord function here.
// TODO(DEVELOPER): Write the app Handle verifySpellingWord function here.

You'll first import the required modules, then write four functions in place of the TODOs. Continue to the next step of the codelab to import the modules.

This codelab requires three modules.

  • The firebase-functions module allows us to write the triggers for our Cloud Functions
  • The firebase-admin module allows us to use the Firebase platform on a server with admin access, for instance to write to the Cloud Firestore.
  • The Actions SDK Node.js Fulfillment Library fulfills Actions SDK handlers for the Google Assistant.
  1. Install the Actions SDK by running the following npm command:
$ npm install @assistant/conversation
  1. In the index.js file, replace the first TODO with the following.

These changes import each of the required modules.

Also, the Firebase Admin SDK can be configured automatically when deployed on a Cloud Functions environment or other Google Cloud container. This is what's happening when we call admin.initializeApp(); in the changes below.

index.js

/**
 * Copyright 2021 Google Inc. All Rights Reserved.
 * ...
 */

// Import the Actions SDK
const {conversation} = require('@assistant/conversation');
const https = require('https');
const app = conversation();
const cors = require('cors')({origin: true});

// Import the Firebase SDK for Cloud Functions.
const functions = require('firebase-functions');
// Import and initialize the Firebase Admin SDK.
const admin = require('firebase-admin');
admin.initializeApp();
// To access Cloud Firestore
const db = admin.firestore();
// TODO(DEVELOPER): Write the getWordDetailsFromDictionaryAPI function here.
// TODO(DEVELOPER): Write the createSpellingPracticeWord function here.
// TODO(DEVELOPER): Write the shuffleWordList function here.
// TODO(DEVELOPER): Write the app Handle getSpellingWordList function here.
// TODO(DEVELOPER): Write the app Handle getSpellingWord function here.
// TODO(DEVELOPER): Write the app Handle repeatSpellingWord function here.
// TODO(DEVELOPER): Write the app Handle definitionOfSpellingWord function here.
// TODO(DEVELOPER): Write the app Handle verifySpellingWord function here.

Now let's add business logic using functions to support Assistant Actions.

Get the word definitions and write them to Cloud Firestore

You'll use the dictionaryapi.dev public API to get the word definitions.

In the index.js file, replace the TODO for getWordDetailsFromDictionaryAPI with the following:

index.js

// Retrieves word definition and audio pronunciation from api.dictionaryapi.dev service
// Function uses service provided by https://dictionaryapi.dev/
async function getWordDetailsFromDictionaryAPI(word) {
  let responseData="";
  let req = https.request({
    host: 'api.dictionaryapi.dev',
    port: 443,
    path:'/api/v2/entries/en/' + word,
    method:'GET'
  }, (res) => {
    res.setEncoding('utf8');
    res.on('data', d => {
        responseData+=d;
    })
    res.on('end',function(){
        let object = JSON.parse(responseData)
        const wordListRef = db.collection('wordlist');
        wordListRef.doc(object[0].word).set(
          object[0]
        );
       return responseData;
     });
  });
  req.end();
}

Add a Cloud Firestore trigger

Next, you'll create a Cloud Function that triggers whenever a new document is created in Cloud Firestore. It will call the dictionaryapi.dev API to get word definitions via the getWordDetailsFromDictionaryAPI function we wrote just above.

In the index.js file, replace the TODO for createSpellingPracticeWord with the following:

index.js

// Firestore trigger that fetches word definitions through getWordDetailsFromDictionaryAPI for every new Firestore document

exports.createSpellingPracticeWord = functions.firestore
  .document('wordlist/{word}')
  .onCreate((snap, context) => {
    const newValue = snap.data();
    const word = newValue.word;
    getWordDetailsFromDictionaryAPI(word);
});

Get a list of words for the game

You can write a Cloud Function that retrieves a list of spelling practice words from Cloud Firestore for the Assistant. For this, we use the app handler.

In the index.js file, replace the TODO for getSpellingWordList with the following.

Adding this function to the special app.handle is a way of making the function accessible from the Assistant.

index.js

// Store the list of spelling words in Assistant session
app.handle('getSpellingWordList', conv => {
  const wordListRef = db.collection('wordlist').limit(50);
  const snapshot = wordListRef;

  if (snapshot.empty) {
    console.log('No matching documents.');
    return;
  }
  VocabularyList = []

  return snapshot.get().then(snapshot => {
    snapshot.forEach(doc => {
      if (doc.data().word) {
          let definition = 'unknown';
          let audio = 'unknown';
          try {
            if(doc.data().hasOwnProperty('meanings')) {
              if(doc.data().meanings[0].hasOwnProperty('definitions')) {
                  definition = doc.data().meanings[0].definitions[0].definition;
              }
            }
            if(doc.data().hasOwnProperty('phonetics')) {
              if(doc.data().phonetics.length > 0)
                audio = doc.data().phonetics[0].audio;
            }
          } catch (error) {
            console.log(error);
          }

          let obj = {
            word: doc.data().word,
            answer: doc.data().word.split("").join(" "),
            definition: definition,
            audio: audio
          }
          VocabularyList.push(obj);
      }
      // Shuffle the array
      let currentIndex = VocabularyList.length, temporaryValue, randomIndex;
      while (0 !== currentIndex) {
        randomIndex = Math.floor(Math.random() * currentIndex);
        currentIndex -= 1;
        temporaryValue = VocabularyList[currentIndex];
        VocabularyList[currentIndex] = VocabularyList[randomIndex];
        VocabularyList[randomIndex] = temporaryValue;
      }
      conv.session.params.vocabWord = VocabularyList;
      conv.session.params.vocabWordIndex = 0;
    });
  });
})

Get a word from Assistant session

You can write a Cloud Function that returns the next spelling word from the word list.

In the index.js file, replace the TODO for getSpellingWord with the following:

index.js

// Returns a spelling practice word to Google Assistant and uses Speech Synthesis Markup Language (SSML) to format the response
app.handle('getSpellingWord',  conv => {
  if (!conv.session.params.vocabWord.empty) {
    conv.session.params.vocabWordIndex+=1;
    const ssml = '<speak>' +
    '<audio src="'+ conv.session.params.vocabWord[conv.session.params.vocabWordIndex].audio +'">Use phonetics to spell the word.</audio> ' +
    '</speak>';
    conv.add(ssml);
  }
  else
    conv.add('Great job! You completed the Spelling practice');
});

Enable the game to repeat the word

You can write a Cloud Function that repeats the current word for the game.

In the index.js file, replace the TODO for repeatSpellingWord with the following:

index.js

// Returns current spelling word
app.handle('repeatSpellingWord',  conv => {
  if (!conv.session.params.vocabWord.empty) {
    const ssml = '<speak>' +
    '<audio src="'+ conv.session.params.vocabWord[conv.session.params.vocabWordIndex].audio +'">Use phonetics to spell the word. </audio> ' +
    '</speak>';
    conv.add(ssml);
  }
  else
    conv.add('Great job! You completed the Spelling practice');
});

Get the definition of the word

You can write a Cloud Function that provides the definition of the current word for the game.

In the index.js file, replace the TODO for definitionOfSpellingWord with the following:

index.js

// Returns spelling word definition from Assistant session parameter
app.handle('definitionOfSpellingWord',  conv => {
  conv.add( 'It means ' + conv.session.params.vocabWord[conv.session.params.vocabWordIndex].definition);
});

Check the user's spelling response

You can write a Cloud Function that verifies the user's response of how to spell the current word for the game.

In the index.js file, replace the TODO for verifySpellingWord with the following:

index.js

// Verifies user spelling response
app.handle('verifySpellingWord', conv => {
  try {
    userResponse = conv.intent.params.userresponse.resolved.join("");
    if (userResponse.toLowerCase() === conv.session.params.vocabWord[conv.session.params.vocabWordIndex].word.toLowerCase()) {
      conv.add('You are correct. Say next to continue.');
    }
    else {
      conv.add('Sorry, wrong answer. The correct answer is ' + conv.session.params.vocabWord[conv.session.params.vocabWordIndex].answer + ' . Say next to continue.');
    }
  } catch (error) {
    conv.add('Sorry. I did not understand your response' );
  }
});
exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);

Deploy all your functions

Your Cloud Functions will only be active after you've deployed them to Firebase.

From the root of the spelling-functions-start directory, run the following command:

$ firebase deploy --only functions

This is the console output you should see:

i  deploying functions
i  functions: ensuring necessary APIs are enabled...
⚠  functions: missing necessary APIs. Enabling now...
i  env: ensuring necessary APIs are enabled...
⚠  env: missing necessary APIs. Enabling now...
i  functions: waiting for APIs to activate...
i  env: waiting for APIs to activate...
✔  env: all necessary APIs are enabled
✔  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (X.XX KB) for uploading
✔  functions: functions folder uploaded successfully
i  starting release process (may take several minutes)...
i  functions: creating function createSpellingPracticeWord(us-central1)...
✔  functions[createSpellingPracticeWord(us-central1)]: Successful create operation.
i  functions: creating function ActionsOnGoogleFulfillment(us-central1)...
✔  functions[ActionsOnGoogleFulfillment(us-central1)]: Successful create operation.

✔  Deploy complete!
Project Console: https://console.firebase.google.com/project/spelling-practice-1234/overview

Make a note of ActionsOnGoogleFulfillment function Http endpoint url for later use. To get the endpoint, open Firebase Console and then click spelling-practice project. Open Functions dashboard to view the functions endpoint.

332cb0437411a242.png

You have completed adding all the required functions. Now let's move to setting up Cloud Firestore.

You'll need to enable Cloud Firestore.

In the Firebase console's Build section, click Firestore. Then, click Create database.

5c0b4abf4410ffcf.png

Access to data in Cloud Firestore is controlled by Security Rules. First you need to set some basic rules on the data to get started. Click Firestore and then In the Rules tab of the Firebase console, add the following rules, then click Publish.

The following rules restrict data access to users who are signed in, which prevents unauthenticated users from reading or writing.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      //
      // WARNING: These rules are insecure! We will replace them with
      // more secure rules later in the codelab
      //
      allow read, write: if request.auth != null;
    }
  }
}

In this step, you'll write spelling words data to Cloud Firestore so that you can generate a list of words for the Assistant (and the game).

Cloud Firestore data is structured into collections, documents, fields, and subcollections. Each word for the game will be stored as its own document in a top-level collection called wordlist. For every new document in the Firestore collection, createSpellingPracticeWord function will be triggered to get the word details from the Dictionary API service.

Create a Cloud Firestore collection

  1. In the Firebase console, navigate to the Cloud Firestore section.
  2. Click + Start collection.
  3. In the Collection ID textbox, enter wordlist, then click Next.

1b4ccadb90f52f02.png

Next, we'll create a document for a word: agreement

  1. In the Document ID textbox, enter agreement.
  2. In the Field textbox, enter word and in the Value textbox enter agreement.
  3. Click Save.

379037e011e8511e.png

When you add this document to Cloud Firestore, it triggers your createSpellingPracticeWord function to fetch the definition details for the word. Add more words (for example: awe, car, true, tell, better, commute, ...) by creating a new document for each word.

The following sections describe how to set up your Google Assistant development environment and create your Actions project.

Check your Google permission settings

To test the Action you build in this codelab, you need to enable the necessary permissions so the simulator can access your Action. To enable permissions, follow these steps:

  1. Go to the Activity controls page.
  2. Sign in with your Google Account, if you have not already done so.
  3. Enable the following permissions:
  • Web & App Activity
  • Under Web & App Activity, select the checkbox next to Include Chrome history and activity from sites, apps, and devices that use Google services.

c988e1e639e6d6e1.png

Create an Actions project

Your Actions project is a container for your Action. To create your Actions project for this codelab, follow these steps:

  1. Open the Actions console.
  2. Click New project.
  3. Accept terms of service

b174d45710b8086b.png

  1. Type in or select spelling-practice-codelab which you created using Firebase Console. (The name is for your internal reference. Later, you can set an external name for your project.)

a2951de5d2001fac.png

  1. Click Import project.
  2. In the What kind of Action do you want to build? screen, select the Custom card.
  3. Click Next.
  4. Select the Blank project card.
  5. Click Start building.
  6. Enter Spelling Practice for display name and click save.

Users start the conversation with your Action through invocation. For example, users can invoke your Action by saying a phrase like "Hey Google, talk to Spelling Practice", where Spelling Practice is the display name.

Your Action must have a display name if you want to deploy it to production; however, to test your Action, you don't need to define the display name. Instead, you can use the phrase "Talk to my test app" in the simulator to invoke your Action.

Configure fulfillment

You need to connect to the Assistant the event handlers for the Cloud Functions that you wrote and deployed earlier in this codelab.

To configure your fulfillment, follow these steps:

  1. Click Webhook in the side navigation.
  2. Select Https endpoint as fulfillment option:

d523bf003e96e66f.png

  1. Enter the URL of your function's endpoint in the HTTPs endpoint textbox, then click Save.

be53e2cd0d914d54.png

In the next section, you'll customize the prompt for your main invocation in the Actions console.

Set up main invocation

You must edit the main invocation to define what happens after a user invokes your Action.

By default, Actions Builder provides a generic prompt when your invocation is triggered ("Start building your Action by defining main invocation.").

To modify the prompt that your Action sends back to the user when they invoke your Action, follow these steps:

  1. Click Main invocation in the navigation.

9ff088c04c995cde.png

  1. Check Call your webhook and add the event handler name getSpellingWordList in the textbox.
  2. In the code editor, replace the text in the speech field with the following welcome message: Welcome to Spelling Practice

Note: You can use either YAML or JSON formatting to edit your prompts.

  1. Click Save.

Test the main invocation in the simulator

The Actions console provides a web tool for testing your Action called the simulator. The interface simulates hardware devices and their settings, so you can converse with your Action as if it were running on a Smart Display, phone, speaker, or KaiOS.

To test your Action's main invocation in the simulator, follow these steps:

  1. In the top navigation bar, click Test to go to the simulator.
  2. To invoke your Action in the simulator, type Talk to Spelling Practice in the input field on the top left, then press Enter on your keyboard.

651fc8da1ac9aa0a.png

When you trigger your Action's main invocation, the Assistant responds with your customized welcome message. At this point, the conversation ends after the Assistant responds with a greeting.

View event logs

When you are in the Test tab, the panel on the right shows the event logs, which display the conversation history as event logs. Each event log displays the events that happen during that turn of the conversation. To view the event log click the grey icon before the event.

Your Action currently has one event log, which shows both the user's input ("Talk to Spelling Practice") and your Action's response. The following screenshot shows your Action's event log:

a6fb192f94426824.png

Now that you've defined what happens after a user invokes your Action, you can build out the rest of your Action's conversation. Spelling Practice has four scenes, and you must activate each scene before it can run. The most common way to activate a scene is to configure your Action so that, when a user matches a user intent within a scene, that intent triggers the transition to another scene and activates it.

Transition from main invocation to start scene

In this section, you create a new scene called Start, which sends a prompt to the user asking if they would like to start playing Spelling Practice. You also add a transition from the main invocation to the new Start scene.

To create this scene and add a transition to it, follow these steps:

  1. Click Develop in the top navigation. Then, click Main invocation in the left navigation.
  2. In the Transition section on the right, click the drop-down menu, then type Start in the text field.

dd4f1807a57f794d.png

  1. Click Add. This creates a scene called Start, and tells the Action to transition to the Start scene after the Action delivers the welcome prompt to the user.
  2. Click Scenes in the left navigation to show the list of scenes.
  3. Under Scenes, click Start to see the Start scene.
  4. Click + in the On enter section of the Start scene.
  5. Select Send prompts.
  6. Replace the sentence in the speech field (Enter the response that users will see or hear...) with a question to ask the user: Use phonetic alphabet to spell the word. For example alpha for a, bravo for b, charlie for c etc. Do you want to continue?

Suggestion chips offer clickable suggestions for the user that your Action processes as user input. In this section, you add suggestion chips that appear below the prompt you just configured (Do you want to play

Spelling Practice

?) to support users on devices with screens.

To add suggestion chips to the Start scene's prompt, follow these steps:

  1. In the Start scene, click suggestions below the code editor. This action adds a single suggestion chip.
  2. In the title field, replace Suggested Response with 'Yes'.
  3. Using the same formatting, manually add a suggestion chip titled 'No' and 'Help with Phonetics'. Your code should look like the following snippet:
  4. Click Save.

5ff2ecdc56801b91.png

Test your Action in the simulator

At this point, your Action should transition from the main invocation to the Start scene and ask the user if they'd like to continue. Suggestion chips should also appear in the simulated display.

To test your Action in the simulator, follow these steps:

  1. In the navigation bar, click Test to take you to the simulator.
  2. To test your Action in the simulator, type Talk to Spelling Practice in the Input field.
  3. Press Enter. Your Action should respond with the Main invocation prompt and the added Start scene prompt, "Welcome to Spelling Practice. Use the phonetic alphabet to spell the word. For example alpha for a, bravo for b, charlie for c etc. Do you want to continue?".

The following screenshot shows this interaction:

338c9570b02a618e.png

  1. Click the Yes or No or Help with Phonetics suggestion chip to respond to the prompt. (You can also say "Yes" or "No" or "Help with Phonetics" or enter Yes or No or Help with Phonetics in the Input field.)

When you respond to the prompt, your Action responds with a message indicating that it can't understand your input: "Sorry, I didn't catch that. Can you try again?" Since you haven't yet configured your Action to understand and respond to "Yes" or "No" input, your Action matches your input to a NO_MATCH intent.

By default, the NO_MATCH system intent provides generic responses, but you can customize these responses to indicate to the user that you didn't understand their input. The Assistant ends the user's conversation with your Action after it can't match user input three times.

Add no and phonetics intents

Now that users can respond to the question your Action poses, you can configure your Action to understand the users' responses ("Yes" or "No" or "Help with Phonetics"). In the following sections, you create user intents that are matched when the user says "Yes" or "No" or "Help with Phonetics" and add these intents to the Start scene. We'll use system intent yes and will create other intents.

Create no intent

Now, you need to create the no intent to understand and respond to the user when they don't want to play the game. To create this intent, follow these steps:

  1. Click Develop in the navigation.
  2. Click Custom Intents in the navigation to open the list of intents.
  3. Click + (plus sign) at the end of the list of intents. Name the new intent no and press Enter.
  4. Click no to open the no intent page.
  5. In the Add training phrases section, click in to the Enter Phrase text box and enter the following phrases:
  • No
  • N
  • I don't want
  • nope

98b0c9a7b67ea9b9.png

  1. Click Save.

Add no intent to Start scene

Now, the Action can understand when a user is expressing "no" or something similar to "no", like "nope". You need to add the no user intent to the Start scene because the user is responding to the Start prompt ("Welcome to Spelling Practice. Use the phonetic alphabet to spell the word. For example alpha for a, bravo for b, charlie for c etc. Do you want to continue?").

To add this intent for the Start scene, follow these steps:

  1. Click the Start scene in the navigation.
  2. Click the + (plus sign) in the Start scene next to User intent handling.
  3. In the Intent section, select no in the drop-down.

51f752e78c8b4942.png

  1. Click Send prompts and update the speech field with the following text: Good Bye.

The code in your editor should look like the following snippet:

candidates:
  - first_simple:
      variants:
        - speech: >-
             Goodbye.
  1. In the Transition section, select End conversation from the dropdown.
  2. Click Save.

Test no intent in simulator

At this point, your Action understands when the user does not want to play the game and returns the appropriate response.

To test this intent in the simulator, follow these steps:

  1. In the navigation bar, click Test.
  2. Type Talk to Spelling Practice in the Input field and press Enter.
  3. Type No in the Input field and press Enter. Alternatively, click the No suggestion chip.

7727a456b522f31b.png

Add system YES intent to Start scene

Now, we'll add SYSTEM intent "YES" to the Start scene, since the user is responding yes to the Start prompt ("Welcome to Spelling Practice. Use the phonetic alphabet to spell the word. For example alpha for a, bravo for b, charlie for c etc. Do you want to continue?").

To add this user intent to the Start scene, follow these steps:

  1. Click the Start scene in the navigation.
  2. Click the + (plus sign) in the Start scene next to User intent handling.
  3. Under All System Intents, Select YES in the intent drop-down.

f6cbe789cde49e8f.png

  1. Click Call your webhook and update the event handler textbox with the function you created earlier: getSpellingWordList
  2. In the Transition section, click the drop-down and select End conversation.
  3. Click Save.

Test YES intent in simulator

At this point, your Action understands when the user wants to play the game and returns the appropriate response.

To test this intent in the simulator, follow these steps:

  1. In the navigation bar, click Test.
  2. To test your Action in the simulator, type Talk to Spelling Practice in the Input field and press Enter.
  3. Type Yes in the Input field and press Enter. Alternatively, click the Yes suggestion chip.

Your Action fetches a list of all spelling practice words and stores them in session. Your Action then ends the session because you selected the End conversation transition for the YES intent.

Create Phonetics intent

To create the Phonetics intent, follow these steps:

  1. Click Develop in the navigation.
  2. Click Custom Intents in the navigation to open the list of intents.
  3. Click + (plus sign) at the end of the list of intents. Name the new intent phonetics and press Enter.
  4. Click the phonetics intent to open the phonetics intent page.
  5. In the Add training phrases section, click the Enter Phrase text box and enter the following phrases:
  • how do I spell words
  • phonetics
  • help me with phonetics
  • phonetic alphabet

1455bdfca8dae46.png

  1. Click Save.

Add phonetics intent to Start scene

Now, the Action can understand when a user is expressing a "phonetics" intent. You can add the phonetics user intent to the Start scene, since the user is responding to the Start prompt ("Welcome to Spelling Practice. Use the phonetic alphabet to spell the word. For example alpha for a, bravo for b, charlie for c etc. Do you want to continue?").

To add this user intent to the Start scene, follow these steps:

  1. Click the Start scene in the navigation.
  2. Click the + (plus sign) in the Start scene next to User intent handling.
  3. Select phonetics in the intent drop-down.

67ee2e08000b2aee.png

  1. In the Transition section, click the drop-down and select End conversation.
  2. Click Save.

Transition from Start scene to Spelling scene

In this section, you create a new scene called Spelling, which sends a prompt to the user to spell the word using the phonetic alphabet.

To create this scene and add a transition to it, follow these steps:

  1. Click Develop in the top navigation. Then, click Start scene in the left navigation.
  2. In the User intent handling section click when actions.intent.YES is matched and on the right in the transition section, click the drop-down menu and type Spelling in the text field.
  3. Click Add. This creates a scene called Spelling, and tells the Action to transition to the Spelling scene after the matching with YES intent.
  4. Expand Scenes in the left navigation to show the list of scenes.
  5. Under Scenes, click Spelling to see the Spelling scene.
  6. Click + in the On enter section of the Spelling scene.
  7. Click Call your webhook and enter getSpellingWord in the event handler textbox.
  8. Select Send prompts.
  9. Replace the sentence in the speech field (Enter the response that users will see or hear...) with {}. The actual prompt will be populated by webhook.

Suggestion chips offer clickable suggestions for the user that your Action processes as user input.

To add suggestion chips to the Spelling scene's prompt, follow these steps:

  1. In the Spelling scene, click suggestions below the code editor. This action adds three suggestion chips.
  2. In the title field, replace Suggested Response with 'Repeat'.
  3. Using the same formatting, manually add a suggestion chip titled 'Skip'.
  4. Using the same formatting, manually add a suggestion chip titled 'Quit'. Your code should look like the following snippet:
  5. Click Save.
suggestions:
      - title: 'Repeat'
      - title: 'Skip'
      - title: 'Quit'

e1d437f714ea1539.png

Create Repeat intent

To create the repeat intent, follow these steps:

  1. Click Develop in the navigation.
  2. Click Custom Intents in the navigation to open the list of intents.
  3. Click + (plus sign) at the end of the list of intents. Name the new intent repeat and press Enter.
  4. Click the repeat intent to open the definition intent page.
  5. In the Add training phrases section, click the Enter Phrase text box and enter the following phrases:
  • one more time please
  • say the word again
  • repeat the word
  • tell me again
  • repeat

e61f0b9f80510bc9.png

  1. Click Save.

Add repeat intent to Spelling scene

Now, the Action can understand when a user is expressing a "repeat" intent. You can add the repeat user intent to the Spelling scene, since the user is responding to the Spelling prompt ("Spell the word using phonetic alphabet").

To add this user intent to the Spelling scene, follow these steps:

  1. Click the Spelling scene in the navigation.
  2. Click the + (plus sign) in the Spelling scene next to User intent handling.
  3. Select repeat in the intent drop-down.

5cfd623b25bedbed.png

  1. Checkthe Call your webhook and enter repeatSpellingWord in the event handler textbox to get the word definition.
  2. Check Send prompts.
  3. Replace the sentence in the speech field (Enter the response that users will see or hear...) with ‘'. The actual prompt will be populated by webhook.

Add suggestion chips to "When Repeat is matched"

  1. In "When Repeat is matched" under User Intent handling, click suggestions below the code editor. This action adds three suggestion chips.
  2. In the title field, replace Suggested Response with 'Skip'.
  3. Using the same formatting, manually add a suggestion chip titled 'Quit'.Your code should look like the following snippet:
suggestions:
      - title: 'Skip'
      - title: 'Quit'

ab40e4b0c432b97c.png

  1. Click Save.

Create definition intent

To create the definition intent, follow these steps:

  1. Click Develop in the navigation.
  2. Click Custom Intents in the navigation to open the list of intents.
  3. Click + (plus sign) at the end of the list of intents. Name the new intent definition and press Enter.
  4. Click the definition intent to open the definition intent page.
  5. In the Add training phrases section, click the Enter Phrase text box and enter the following phrases:
  • I would like to know the definition
  • tell me the definition
  • what does it mean
  • meaning
  • definition
  • what is the definition?

c1b88a9c0b1ac082.png

  1. Click Save.

Add definition intent to Spelling scene

Now, the Action can understand when a user is expressing a "definition" intent. You can add the definition user intent to the Spelling scene, since the user is responding to the Spelling prompt ("Spell the word using phonetic alphabet").

To add this user intent to the Spelling scene, follow these steps:

  1. Click the Spelling scene in the navigation.
  2. Click the + (plus sign) in the Spelling scene next to User intent handling.
  3. Select definition in the intent drop-down.

646bdcac3ad3eb0c.png

  1. Check the Call your webhook and enter definitionOfSpellingWord in the event handler textbox to get the word definition.
  2. Check Send prompts.
  3. Replace the sentence in the speech field (Enter the response that users will see or hear...) with ‘‘`. The actual prompt will be populated by webhook.

Add suggestion chips to the webhook response

  1. In the Start scene, click suggestions below the code editor. This action adds three suggestion chips.
  2. In the title field, replace Suggested Response with 'Skip'.
  3. Using the same formatting, manually add a suggestion chip titled 'Quit'.Your code should look like the following snippet:
suggestions:
      - title: 'Skip'
      - title: 'Quit'

25227545839d933f.png

  1. Click Save.

Create skip intent

To create the skip intent, follow these steps:

  1. Click Develop in the navigation.
  2. Click Intents in the navigation to open the list of intents.
  3. Click + (plus sign) at the end of the list of intents. Name the new intent skip and press Enter.
  4. Click the skip intent to open the skip intent page.
  5. In the Add training phrases section, click the Enter Phrase text box and enter the following phrases:
  • next word
  • go next
  • next
  • skip
  • skip word

d1c4908a3d7882f8.png

  1. Click Save.

Add Skip intent to Spelling scene

Now, the Action can understand when a user is expressing a "skip" intent. You can add the skip user intent to the Spelling scene, since the user is responding to the Spelling prompt ("Spell the word using phonetic alphabet").

To add this user intent to the Spelling scene, follow these steps:

  1. Click the Spelling scene in the navigation.
  2. Click the + (plus sign) in the Spelling scene next to User intent handling.
  3. Select skip in the intent drop-down.

5465f97542217964.png

  1. In the Transition section on the right, click the drop-down menu and select Spelling .

c8072485ca82bd3f.png

  1. Click Save.

Create quit intent

To create the Quit intent, follow these steps:

  1. Click Develop in the navigation.
  2. Click Intents in the navigation to open the list of intents.
  3. Click + (plus sign) at the end of the list of intents. Name the new intent Quit and press Enter.
  4. Click the Quit intent to open the definition intent page.
  5. In the Add training phrases section, click the Enter Phrase text box and enter the following phrases:
  • I quit
  • Goodbye
  • Cancel
  • Exit
  • Quit

9916f77b8766541e.png

  1. Click Save.

Add Quit intent to Spelling scene

Now, the Action can understand when a user is expressing a "quit" intent. You can add the quit user intent to the Spelling scene, since the user is responding to the Spelling prompt ("Spell the word using phonetic alphabet").

To add this user intent to the Spelling scene, follow these steps:

  1. Click the Spelling scene in the navigation.
  2. Click the + (plus sign) in the Spelling scene next to User intent handling.
  3. Select quit in the intent drop-down.

5f62fb18a3653d66.png

  1. In the Transition section on the right, click the drop-down menu and select End conversation . 1ffbe35a7bbbb4b0.png
  2. Click Save.

Create phonetic_alphabet type

In this section, you create a new type called phonetic_alphabet, which specifies the phonetic alphabet options the users can choose to spell the word. You can also define a few synonyms for these options in case a user says something similar. In a later section, you add the phonetic_alphabet type to a slot to specify that you want to obtain the user's response.

To create the phonetic_alphabet type, follow these steps:

  1. Click Develop in the navigation.
  2. Click the + (plus sign) under Types.
  3. Type phonetic_alphabet and press Enter.
  4. Click phonetic_alphabet to open the options.
  5. In the What kind of values will this Type support? section, select the Words and synonyms option
  6. Enter the following entries and corresponding values in the Add entries section:

a

alpha, apple, amsterdam

b

bravo, butter, baltimore

c

charlie, cat, casablanca

d

delta, dog, denmark

e

echo, edward, edison

f

foxtrot, fox, florida

g

golf, george, gallipoli

h

hotel, harry, havana

i

india, ink, italia

j

juliette, johnny, jerusalem

k

kilo, king, kilogramme

l

lima, love, london

m

mike, money, madagascar

n

november, new york, nancy

o

oscar, orange, oslo

p

papa, paris, peter

q

quebec, queen

r

romeo, roma, robert

s

sierra, sugar, santiago

t

tango, tommy, tripoli

u

uniform, umbrella, uncle

v

victor, vinegar, Valencia

w

whiskey, william, washington

x

x-ray

y

yankee, yellow, yorker

z

zulu, zebra, zurich

Your key-value table should look like the following:

5b5a5cd9fa557e1b.png

  1. Click Save.

Configure slot filling

Next, you need to configure slot filling in the Spelling scene. To configure the slot-filling logic, follow these steps:

  1. Click the Spelling scene in the navigation.
  2. Click the + (plus sign) in the Spelling scene for Slot filling.
  3. In the Enter slot name field, add userresponse as the slot name.
  4. In the Select type drop-down, select phonetic_alphabet as the slot type.
  5. Check This slot accepts a list of values
  6. Check This slot is required.
  7. Select Customize slot value writeback option and enter userresponse in the session parameter textbox.

ba57a419877a07f3.png

  1. Click Save.

Add Condition to Spelling screen

To add Condition to the Spelling scene, follow these steps:

  1. Click the Spelling scene in the navigation.
  2. Click the + (plus sign) in the Spelling scene next to Condition.
  3. Enter scene.slots.status == "FINAL" as condition
  4. Check the Call your webhook and enter verifySpellingWord in the event handler textbox to verify the user response.
  5. Check Send prompts.
  6. Replace the sentence in the speechfield (Enter the response that users will see or hear...) with {}. The actual prompt will be populated by webhook.

Add suggestion chips to the webhook response

  1. In the Start scene, click suggestions below the code editor. This action adds three suggestion chips.
  2. In the title field, replace Suggested Response with 'Next'.
  3. Using the same formatting, manually add a suggestion chip titled 'Quit'.Your code should look like the following snippet:
suggestions:
      - title: 'Next'
      - title: 'Quit'

ac3d7a9366ebc1b1.png

  1. Click Save.

To test your Action in the simulator, follow these steps:

  1. In the navigation bar, click Test to take you to the simulator.
  2. To test your Action in the simulator, type Talk to Spelling Practice in the Input field.
  3. Press Enter. Your Action should respond with the Main invocation prompt and the added Start scene prompt, "Welcome to Spelling Practice. Use the phonetic alphabet to spell the word. For example alpha for a, bravo for b, charlie for c etc. Do you want to continue?".
  4. Say Yes to continue
  5. Simulator will play a word sound to spell
  6. You can spell the word using phonetic alphabets. For example, for better say or type "bravo echo tango tango echo romeo"
  7. Simulator will respond with either the correct or incorrect response.
  8. Say next to continue to the next word or say quit to exit the game loop.

Congratulations, you've successfully built your game, Spelling Practice!

You now know the key steps required to build a game using Cloud Firestore, Cloud Functions, and Google Assistant Action Builder.

What you covered

  • How to interact with Cloud Firestore
  • How to use slots to gather data from the user
  • How to process a user's input and return a response
  • How to use conditions to add logic to a scene
  • How to add a game loop

Additional learning resources

You can explore these resources for learning about building Actions for Google Assistant:

Clean up your project [recommended]

To avoid incurring possible charges, it is recommended to remove projects that you don't intend to use. To delete the projects you created in this codelab, follow these steps:

  1. To delete your Firebase project and resources, complete the steps listed in the Shutting down (deleting) projects section.

Caution: Ensure that you select the correct project for deletion on the Google Cloud Console's Settings page.

  1. Optional: To immediately remove your project from the Actions console, complete the steps listed in the Deleting a project section. If you don't complete this step, your project will automatically be removed after approximately 30 days.

Follow @ActionsOnGoogle & @Firebase on Twitter to stay tuned to our latest announcements and tweet to #GoogleIO to share what you have built!