Engage users with your Action for Google Assistant

1. Overview

Actions on Google is a developer platform that lets you create software to extend the functionality of Google Assistant, Google's virtual personal assistant, across more than 1 billion devices, including smart speakers, phones, cars, TVs, headphones, and more. Users engage Assistant in conversation to get things done, like buying groceries or booking a ride. (For a complete list of what's possible, see the Actions directory.) As a developer, you can use Actions on Google to easily create and manage delightful and effective conversational experiences between users and your third-party service.

This is an advanced codelab module, intended for readers who already have some experience building Actions for the Google Assistant. If you don't have any prior development experience with Actions on Google, we strongly recommend that you familiarize yourself with the platform by following our introductory codelabs ( Level 1, Level 2, and Level 3). These advanced modules will guide you through a series of features that can help you expand your Action's functionality and grow your audience.

One important way to measure an Action's success is user engagement or how effective the Action is at bringing users back after their first interaction. To help make that easier, you can implement several features in your Action that give users paths back into your conversation.

The codelab covers user-engagement features and best practices for Actions on Google.

a3fc0061bd01a75.png 961ef6e27dc73da2.png

What you'll build

You'll enhance a feature that's already been built by enabling it to:

  • Send users a daily update that they can tap to talk to your Action
  • Send users push notifications that link back to your Action
  • Create a link that takes users to your Action from a mobile web browser

What you'll learn

  • What is user engagement and why it's important for an Action's success
  • How to modify an Action to increase user engagement
  • Which user engagement features to use in different kinds of Actions
  • How to use the Actions API to send notifications through Assistant

What you'll need

You must have the following tools:

  • An IDE/text editor of your choice, such as WebStorm, Atom, or Sublime
  • A terminal to run shell commands with Node.js, npm, and git installed
  • A web browser, such as Google Chrome
  • A local development environment with the Firebase command-line interface
  • A mobile device (Android or iOS) with Assistant (You must be signed-in to Assistant with the same Google Account that you'll use to build this project.)

Familiarity with JavaScript (ES6) is also strongly recommended, although not required, to understand the webhook code.

2. Set up your project

This section shows you how to add user engagement features to a complete, previously built Action.

Understand the sample

The sample for this codelab is a simple Action for a fictional gym named "Action Gym." The Action provides information about the gym, including a list of classes that rotate each day. An informative Action such as this is a good candidate for all user-engagement features because the rotating class list gives different useful information each day.

The following diagram shows the Action Gym sample's conversational flow:

e2d6e4ad98948cf3.png

You'll make minor modifications to the dialog to better suit the engagement features you add. However, the general design of the conversation won't change much.

Download your base files

Run the following command to clone the GitHub repository for the codelab:

git clone https://github.com/actions-on-google/user-engagement-codelab-nodejs

Set up your project and agent

To set up your Actions project and Dialogflow agent, complete the following steps:

  1. Open the Actions console.
  2. Click New project.
  3. Type in a Project name, like engagement-codelab.
  4. Click Create Project.
  5. Rather than pick a category, scroll down to the More options section and click the Conversational card.
  6. Click Build your Action to expand the options and select Add Action(s).
  7. Click Add Your First Action.
  8. On the Create Action dialog, select Custom Intent, and then click Build to launch the Dialogflow console.
  9. In the Dialogflow console's agent creation page, click Create.
  10. Click the 6bf56243a8a11a3b.png (gear icon) on the left navigation.
  11. Click Export and Import, then Restore From Zip.
  12. Upload the agent.zip file from the /user-engagement-codelab-nodejs/start/ directory you downloaded earlier.
  13. Type RESTORE and click Restore.
  14. Click Done.

Deploy your fulfillment

Now that your Actions project and Dialogflow agent are ready, deploy your local index.js file using the Firebase Functions CLI.

From the /user-engagement-codelab-nodejs/start/functions/ directory of your base files clone, run the following commands:

firebase use <PROJECT_ID>
npm install
firebase deploy

After a few minutes, you should see "Deploy complete!", which indicates that you've successfully deployed your webhook to Firebase.

Retrieve the deployment URL

You need to provide Dialogflow with the URL to the cloud function. To retrieve this URL, follow these steps:

  1. Open the Firebase Console.
  2. Select your Actions project from the list of options.
  3. Navigate to Develop > Functions on the left navigation bar. If you're prompted to "Choose data sharing settings", you can ignore this option by clicking Do this later.
  4. Under the Dashboard tab, you should see an entry for "fulfillment" with a URL under Trigger. Save this URL; you'll need to copy it into Dialogflow in the next section.

1741a329947975db.png

Set the webhook URL in Dialogflow

Now you need to update your Dialogflow agent to use your webhook for fulfillment. To do this, follow these steps:

  1. Open the Dialogflow console (you can close the Firebase console if you'd like).
  2. Click Fulfillment on the left navigation.
  3. Enable Webhook.
  4. Paste the URL you copied from the Firebase dashboard if it doesn't already appear.
  5. Click Save.

Verify your project is correctly set up

Users should be able to invoke your Action for information about Action Gym, including a hard-coded text response with business hours and a text response that lists the class schedule for each day of the week.

To test out your Action in the Actions simulator:

  1. In the Dialogflow console left navigation, click on Integrations > Google Assistant.
  2. Make sure Auto-preview changes is enabled and click Test to update your Actions project.
  3. The Actions simulator loads your Actions project. To test your Action, type Talk to my test app into the Input field and press enter.
  4. You should see a response welcoming you to Action Gym. Try following the prompts to continue the conversation while making sure that your fulfillment has a response for each input.

60acf1ff87b1a87f.png

3. Add daily update subscriptions

A common way to engage users is to offer information to them when it's most useful. This is accomplished by offering users the option to subscribe to daily updates for an intent, which sends them an Assistant notification that links directly to that intent's fulfillment.

In this step, you'll learn about daily update subscriptions and add them to your Action's Class List intent. After following these instructions, your Action's conversation will look like the following diagram:

f48891c8118f7436.png

How will this engage users?

Smartphone users are probably familiar with push notifications, which provide app-specific information and updates. Daily update subscriptions are a simple way to access users on mobile devices outside of Assistant, provided that the intent you're sending updates for continues to provide value to the user on a daily basis.

Daily updates can be a useful engagement tool but should not necessarily be incorporated in every Action. Consider these tips when deciding whether to add daily update subscriptions to an Action:

  • Make sure the daily updates will result in the user seeing different, useful information every day. If tapping a daily update results in the same prompt every time, the user will probably unsubscribe after a couple days.
  • Make sure your dialog makes sense to your user if they jump straight to your daily update's intent. Your user won't necessarily start from the beginning of the conversation, so they shouldn't be expected to have much context.
  • Show your user the benefit of your Action before prompting them to subscribe to daily updates. Your user should be thinking "I want this content every day" when they are given the option to subscribe.
  • Don't overwhelm the user with repeated suggestions to subscribe. Offer a daily update subscription right after showing the user what they'd subscribe to, and avoid pestering them about it elsewhere.
  • Keep the conversation short after the update intent is triggered. Most daily updates should only consist of a single response then close without requiring user input.

Turn on daily updates

Daily update subscriptions can be added to the welcome intent which puts the user at the start of your conversation, or a more specific intent in order to deep link them to somewhere within the conversation. For this codelab, the Class List intent makes the most sense because the dialogue will change every day, and users may find it useful to be reminded what classes are available.

Follow these steps to enable daily updates for the Class List intent:

  1. In the Actions console, click the Develop tab, and choose Actions in the left navigation bar.
  2. Click on Class List under the Actions list.
  3. Under the User engagement section, toggle the Would you like to offer daily updates to users option.
  4. Set a descriptive Content title that describes the daily update. The context will be "What time would you like me to send your daily <content title>", so make sure your title is both descriptive and sounds correct when spoken aloud. For this example, set the Content title to list of upcoming Action Gym classes.
  5. Click Save at the top of the page.

c00885cc30e14d68.png

Set up Dialogflow

Follow these steps in the Dialogflow console to create intents for the daily update subscription flow:

Prompt the user to subscribe

  1. Set up a new intent to handle the user asking to subscribe to daily updates. In the Dialogflow console, click the + button next to Intents in the left navigation to create a new intent.
  2. Name this new intent Setup Updates.
  3. Under the Training phrases section, add the following user expressions:
  • Send daily reminders
  • Reminder
  • Remind me
  • Updates
  • Upcoming classes
  1. Under the Fulfillment section, toggle the Enable webhook call for this intent option.
  2. Click Save at the top of the page.

5c70faa02151da0.png

Handle the user's decision

  1. Set up a new intent to handle the user's response to the daily updates subscription prompt. Click the + button next to Intents in the left navigation to create a new intent.
  2. Name this new intent Confirm Updates.
  3. Under the Events section, add actions_intent_REGISTER_UPDATE. This Dialogflow event will be triggered by the user finishing the daily update subscription flow, whether they ended up subscribing or not.
  4. Under the Fulfillment section, toggle the Enable webhook call for this intent option.
  5. Click Save at the top of the page.

b871c2bdadac8abc.png

Implement the fulfillment

To implement the fulfillment in your webhook, complete the following steps:

Load dependencies

b2f84ff91b0e1396.png In the index.js file, update the require() function to add the RegisterUpdate package from the actions-on-google package, so your imports look like this:

index.js

const {
  dialogflow,
  Suggestions,
  RegisterUpdate,
} = require('actions-on-google');

Update suggestion chips

b2f84ff91b0e1396.png In the index.js file, add a DAILY entry to the list of suggestion chip titles, so your Suggestion definition looks like this:

index.js

// Suggestion chip titles
const Suggestion = {
  HOURS: 'Ask about hours',
  CLASSES: 'Learn about classes',
  DAILY: 'Send daily reminders',
};

Add fulfillment for new intents

When the user says they want to subscribe, start the daily updates subscription flow by calling the RegisterUpdate helper with the update's target intent (Class List) and type (DAILY). After the subscription flow is finished, Assistant triggers the actions_intent_REGISTER_UPDATE event with a status argument which describes whether the subscription was successful or not. Offer follow-up prompts to the user that change depending on the subscription status.

b2f84ff91b0e1396.png In the index.js file, add the following code:

index.js

// Start opt-in flow for daily updates
app.intent('Setup Updates', (conv) => {
  conv.ask(new RegisterUpdate({
    intent: 'Class List',
    frequency: 'DAILY',
  }));
});

// Confirm outcome of opt-in for daily updates
app.intent('Confirm Updates', (conv, params, registered) => {
  if (registered && registered.status === 'OK') {
     conv.ask(`Gotcha, I'll send you an update everyday with the ` +
     'list of classes. Can I help you with anything else?');
  } else {
    conv.ask(` I won't send you daily reminders. Can I help you with anything else?`);
  }
  if (conv.screen) {
    conv.ask(new Suggestions([Suggestion.HOURS, Suggestion.CLASSES]));
  }
});

Offer alternative prompts for the user

Your Class List response will offer the daily update subscription at the end, but this presents a problem. Since this same response will be triggered when the user taps the daily update notification, they'll still be asked to subscribe to daily updates even though they just came from one. How can you keep the user from thinking they need to re-subscribe?

Thankfully, your conv object's arguments include information about where the user started the conversation. You can check the conv arguments to see if they contain an UPDATES section, which indicates the user started the conversation from a daily update notification, and change the response accordingly. You can also use this conversation branch to close the dialog immediately after providing the list of classes, which follows our best practice of keeping the daily update short.

b2f84ff91b0e1396.png In the index.js file, replace the following code:

index.js

// Class list intent handler
app.intent('Class List', (conv, {day}) => {
  if (!day) {
    day = DAYS[new Date().getDay()];
  }
  const classes =
  [...new Set(schedule.days[day].map((d) => `${d.name} at ${d.startTime}`))]
  .join(', ');
  const classesMessage =
  `On ${day} we offer the following classes: ${classes}. ` +
  `Can I help you with anything else?`;
  conv.ask(classesMessage);
  if (conv.screen) {
    conv.ask(new Suggestions([Suggestion.HOURS]));
  }
});

with this:

index.js

// Class list intent handler
app.intent('Class List', (conv, {day}) => {
  if (!day) {
    day = DAYS[new Date().getDay()];
  }
  const classes =
  [...new Set(schedule.days[day].map((d) => `${d.name} at ${d.startTime}`))]
  .join(', ');
  let classesMessage = `On ${day} we offer the following classes: ${classes}. `;
  // If the user started the conversation from the context of a daily update,
  // the conv's arguments will contain an 'UPDATES' section.
  let engagement = conv.arguments.get('UPDATES');
  // Check the conv arguments to tailor the conversation based on the context.
  if (engagement) {
    classesMessage += `Hope to see you soon at Action Gym!`;
    conv.close(classesMessage);
  } else {
    classesMessage += `Would you like me to send you daily reminders of upcoming classes, or can I help you with anything else?`;
    conv.ask(classesMessage);
    if (conv.screen) {
      conv.ask(new Suggestions([Suggestion.DAILY, Suggestion.HOURS]));
    };
  };
});

Test your daily updates

In the terminal, run the following command to deploy your updated webhook code to Firebase:

firebase deploy

To test out your custom reprompt in the Actions simulator, follow these steps:

  1. In the Actions console, navigate to Test.
  2. Type Talk to my test app into the Input field and press enter.
  3. Type Learn about classes and press enter. Your Action's response should now offer to send daily reminders.
  4. Type Send daily reminders and press enter.
  5. Type in a time that you'd like to see the update and press enter. For testing purposes, try responding with 3-5 minutes later than the current time.

83a15ecac8c71787.png

On your mobile device, you should receive a notification from Assistant around the time that you specified for updates. Note that this notification may take a couple minutes to appear. Tap on the notification and it should deep-link directly to the Class List intent in Assistant, giving you a list of upcoming classes:

8582482eafc67d5b.png

4. Add push notifications

As another option to engage users outside of your Action, you can call the Actions API to send push notifications to users. Unlike daily updates, these notifications aren't automatically scheduled by Assistant so you can send them at-will.

In this step, you'll learn how to implement push notifications in your Action by adding a new Class Canceled intent and sending notifications to users that notify them about a class cancellation. You'll also set up the following three components needed to send notifications:

  • Actions API account - You send notifications to the user by sending a POST request to an API, so you'll need to set up a service account and credentials to interface with this API.
  • Permission helper - You need the user's permission to access the user ID needed to send them push notifications. In this example, you'll use a client library function to call the permission helper and request this ID.
  • Storage - In order to send push notifications to a user outside of a conversation, you need to store user IDs somewhere that can be recalled at-will. In this example, you'll set up a Firestore database to store information for each user.

After following these instructions, you'll add the following dialog to your Action's conversation:

7c9d4b633c547823.png

How will this engage users?

Smartphone users are probably familiar with push notifications, which provide app-specific information and updates. Push notifications are a flexible way to access users on mobile devices outside of Assistant, provided that users are given a good reason to enable them. With daily updates, users are already aware that they'll be notified on a daily basis. With push notifications, however, users don't know whether they're opting in to receive infrequent notifications or will be pestered with multiple notifications per day.

Push notifications can be a useful engagement tool but should not necessarily be incorporated in every Action. Consider these tips when deciding whether to add push notifications to an Action:

  • Plan some example schedules for your push notifications. If you plan on only sending one push notification per day, consider using daily updates instead.
  • Make sure your push notifications will provide useful information every time they're received. Your notifications can also deep link to one of your Action's intents, so make sure the intent is useful and relevant.
  • Be explicit when asking a user to subscribe to push notifications. They should understand what to expect with each push notification, and have some idea of how often the notifications are sent.

Enable the Actions API

  1. Open the Google Cloud console and select your Actions project name in the dropdown.

d015c1515b99e3db.png

  1. In the navigation menu (☰), go to APIs & Services > Library.
  2. Search for the Actions API, and click Enable.

6d464f49c88e70b4.png

Create a service account

The Actions API requires authentication so you need to create a service account to send requests. Follow these steps to create and install a service account key for the Actions API:

  1. In the Google Cloud Console's navigation menu (☰), go to APIs & Services > Credentials.
  2. Click on Create credentials > Service account key.
  3. In the Service account drop-down menu, select New Service Account.
  4. Fill in the following information:
  • Service account name: service-account
  • Role: Project > Owner
  • Service account ID: service-account (always followed by @<project_id>.iam.gserviceaccount.com)
  • Key type: JSON
  1. Click Create.
  2. Move the downloaded JSON file to the /user-engagement-codelab/start/functions/ directory of your project.
  3. Rename the JSON file to service-account.json.

d9bd79d35691de3a.png

Enable Firestore

In order to send notifications outside of the conversation, you need a way to store user IDs that can be referenced from your notification code. For this example, we're using a Firestore database to store the user IDs of subscribed users.

Follow these steps to create a Firestore database for your Action:

  1. In the Firebase console, select your Actions project name.
  2. In the left navigation, go to Develop > Database and click Create database.
  3. Select Start in test mode.
  4. Click Enable.

6dfc386413954caa.png

Set up Dialogflow

Follow these steps in the Dialogflow console to create the push notifications opt-in flow:

Prompt the user to subscribe

  1. Set up a new intent to handle the user asking to subscribe to push notifications for cancelled classes. In the Dialogflow console, click the + button next to Intents in the left navigation to create a new intent.
  2. Name this new intent Setup Push Notifications.
  3. Under the Training phrases section, add the following user expressions:
  • Subscribe to notifications
  • Send notification
  • Notify me
  • Send class notifications
  • Cancelled notifications
  1. Under the Fulfillment section, toggle the Enable webhook call for this intent option.
  2. Click Save at the top of the page.

3d99bc41d0492552.png

Handle the user's decision

  1. Set up a new intent to handle the user's response to the push notifications subscription prompt. Click the + button next to Intents in the left navigation to create a new intent.
  2. Name this new intent Confirm Push Notifications.
  3. Under the Events section, add actions_intent_PERMISSION. This Dialogflow event will be triggered by the user finishing the push notifications subscription flow, whether they ended up subscribing or not.
  4. Under the Fulfillment section, toggle the Enable webhook call for this intent option.
  5. Click Save at the top of the page.

d37f550c5e07cb73.png

Handle the push notification

You can link your push notifications to a specific intent, so users who tap on the push notification are deep linked directly to that intent in your Action. In this example, add a new intent for push notifications that provides details about cancelled classes.

Follow these steps to add an intent to be triggered by the user tapping a push notification:

  1. In the Dialogflow console, click the + button next to Intents in the left navigation to create a new intent.
  2. Name this new intent Class Canceled.
  3. Under the Training phrases section, add Cancelations as a user expression.
  4. Under the Fulfillment section, toggle the Enable webhook call for this intent option.
  5. Click Save at the top of the page.

940379556f559631.png

Send test notifications mid-conversation

In production, you should have a script separate from your Action fulfillment code that sends push notifications. For this example, create an intent that you can invoke to send a push notification while talking to your Action. This intent is only for debug purposes; in practice, push notifications shouldn't be handled by your fulfillment or otherwise triggered as part of your Action's conversation.

Follow these steps to create an intent for testing push notifications:

  1. For testing and debugging purposes, set up a new intent that allows you to send push notifications to subscribed users. In the Dialogflow console, click the + button next to Intents in the left navigation to create a new intent.
  2. Name this new intent Test Notification.
  3. Under the Training phrases section, add Test notification as a user expression.
  4. Under the Fulfillment section, toggle the Enable webhook call for this intent option.
  5. Click Save at the top of the page.

6967f5a997643eb8.png

Turn on push notifications

Follow these steps to enable push notifications for the Class Canceled intent:

  1. In the Dialogflow console, go to Integrations in the navigation bar.
  2. On the Google Assistant card, click Integration Settings.
  3. Add Class Canceled as an Implicit invocation intent. This step is necessary for Dialogflow to recognize that users can start your conversation with the Class Canceled intent (by tapping a push notification).
  4. Click Close.

1ac725231ed279a1.png

  1. In the Actions console, click the Develop tab, and choose Actions in the left navigation bar.
  2. Click on Class Canceled under the Actions list.
  3. Under the User engagement section, toggle the Would you like to send push notifications? option.
  4. Set a descriptive Content title that describes the push notification. The context will be "Is it ok if I send push notifications for <content title>?", so make sure your title is both descriptive and sounds correct when spoken aloud. For this example, set the Content title to class cancelations.
  5. Click Save at the top of the page.

4304c7cd575f6de3.png

Implement the fulfillment

To implement the fulfillment in your webhook, complete the following steps:

Load dependencies

b2f84ff91b0e1396.png In the index.js file, update the require() function to add the UpdatePermission package from the actions-on-google package, so your imports look like this:

index.js

const {
  dialogflow,
  Suggestions,
  RegisterUpdate,
  UpdatePermission,
} = require('actions-on-google');

Update suggestion chips

b2f84ff91b0e1396.png In the index.js file, add a NOTIFICATIONS entry to the list of suggestion chip titles, so your Suggestion definition looks like this:

index.js

// Suggestion chip titles
const Suggestion = {
  HOURS: 'Ask about hours',
  CLASSES: 'Learn about classes',
  DAILY: 'Send daily reminders',
  NOTIFICATIONS: 'Get notifications',
};

Set up new imports

In order to connect to your Firestore database, add the firebase-admin package and add constants for the fields stored in the database. Also, import the google-auth-library and request packages to handle authentication and requests to the Actions API.

b2f84ff91b0e1396.png In the index.js file, add the following code to your imports:

index.js

// Firebase admin import
const admin = require('firebase-admin');

// Initialize Firestore
admin.initializeApp();
const db = admin.firestore();

// Firestore constants
const FirestoreNames = {
 INTENT: 'intent',
 USER_ID: 'userId',
 USERS: 'users',
};

// Actions API authentication imports
const {auth} = require('google-auth-library');
const request = require('request');

Offer to set up class cancelation notifications

b2f84ff91b0e1396.png In the index.js file, replace the following code:

index.js

// Class list intent handler
app.intent('Class List', (conv, {day}) => {
  if (!day) {
    day = DAYS[new Date().getDay()];
  }
  const classes =
  [...new Set(schedule.days[day].map((d) => `${d.name} at ${d.startTime}`))]
  .join(', ');
  let classesMessage = `On ${day} we offer the following classes: ${classes}. `;
  // If the user started the conversation from the context of a daily update,
  // the conv's arguments will contain an 'UPDATES' section.
  let engagement = conv.arguments.get('UPDATES');
  // Check the conv arguments to tailor the conversation based on the context.
  if (engagement) {
    classesMessage += `Hope to see you soon at Action Gym!`;
    conv.close(classesMessage);
  } else {
    classesMessage += `Would you like me to send you daily reminders of upcoming classes, or can I help you with anything else?`;
    conv.ask(classesMessage);
    if (conv.screen) {
      conv.ask(new Suggestions([Suggestion.DAILY, Suggestion.HOURS]));
    };
  };
});

with this:

index.js

// Class list intent handler
app.intent('Class List', (conv, {day}) => {
  if (!day) {
    day = DAYS[new Date().getDay()];
  }
  const classes =
  [...new Set(schedule.days[day].map((d) => `${d.name} at ${d.startTime}`))]
  .join(', ');
  let classesMessage = `On ${day} we offer the following classes: ${classes}. `;
  // If the user started the conversation from the context of a daily update,
  // the conv's arguments will contain an 'UPDATES' section.
  let engagement = conv.arguments.get('UPDATES');
  // Check the conv arguments to tailor the conversation based on the context.
  if (engagement) {
    classesMessage += `Hope to see you soon at Action Gym!`;
    conv.close(classesMessage);
  } else {
    classesMessage += `Would you like to receive daily reminders of upcoming classes, subscribe to notifications about cancelations, or can I help you with anything else?`;
    conv.ask(classesMessage);
    if (conv.screen) {
      conv.ask(new Suggestions([Suggestion.DAILY, Suggestion.NOTIFICATIONS,
Suggestion.HOURS]));
    };
  };
});

Add fulfillment for new intents

When the user says they want to subscribe to push notifications, call the UpdatePermission helper to request permission from the user. If that's successful, the PERMISSION argument will be added to the conv object's arguments which you can check to pivot the conversation.

Once you have the user's permission, take the user ID from the conv object's arguments and save that in your database. You'll later send this user ID to the Actions API, which is how Assistant determines who receives the notification.

Lastly, add fulfillment for the Class Canceled intent that's triggered by tapping the push notification. In this example your response is a placeholder string, though in a production-ready version of this Action your notification script would provide more dynamic information about which class has been canceled.

b2f84ff91b0e1396.png In the index.js file, add the following code:

index.js

// Call the User Information helper for permission to send push notifications
app.intent('Setup Push Notifications', (conv) => {
 conv.ask('Update permission for setting up push notifications');
 conv.ask(new UpdatePermission({intent: 'Class Canceled'}));
});

// Handle opt-in or rejection of push notifications
app.intent('Confirm Push Notifications', (conv) => {
 if (conv.arguments.get('PERMISSION')) {
   let userId = conv.arguments.get('UPDATES_USER_ID');
   if (!userId) {
     userId = conv.request.conversation.conversationId;
   }
   // Add the current conversation ID and the notification's
   // target intent to the Firestore database.
   return db.collection(FirestoreNames.USERS)
   .add({
     [FirestoreNames.INTENT]: 'Class Canceled',
     [FirestoreNames.USER_ID]: userId,
   })
   .then(() => {
     conv.ask(`Great, I'll notify you whenever there's a class cancelation. ` +
     'Can I help you with anything else?');
   });
 } else {
   conv.ask(`Okay, I won't send you notifications about class cancelations. ` +
     'Can I help you with anything else?');
 }
 if (conv.screen) {
    conv.ask(new Suggestions([Suggestion.CLASSES, Suggestion.HOURS]));
  }
});

// Intent triggered by tapping the push notification
app.intent('Class Canceled', (conv) => {
 conv.ask('Classname at classtime has been canceled.');
});

Add test notifications

To send a push notification to a user, send a POST request to the Actions API with the user ID, the notification's title, and the target intent. In this example, triggering the Test Notification intent will iterate through your Firestore database and send push notifications to every user who's subscribed to notifications.

Remember that, in this example, you're including the code that sends the push notification in your webhook fulfillment and triggering that code by invoking a test intent in your conversation. In Actions that you intent to publish, your push notification code should exist in a script separate from your fulfillment.

b2f84ff91b0e1396.png In the index.js file, add the following code:

index.js

// Debug intent to trigger a test push notification
app.intent('Test Notification', (conv) => {
 // Use the Actions API to send a Google Assistant push notification.
 let client = auth.fromJSON(require('./service-account.json'));
 client.scopes = ['https://www.googleapis.com/auth/actions.fulfillment.conversation'];
 let notification = {
   userNotification: {
     title: 'Test Notification from Action Gym',
   },
   target: {},
 };
 client.authorize((err, tokens) => {
   if (err) {
     throw new Error(`Auth error: ${err}`);
   }
   // Iterate through Firestore and send push notifications to every user
   // who's currently opted in to canceled class notifications.
   db.collection(FirestoreNames.USERS)
       .where(FirestoreNames.INTENT, '==', 'Class Canceled')
       .get()
       .then((querySnapshot) => {
         querySnapshot.forEach((user) => {
           notification.target = {
             userId: user.get(FirestoreNames.USER_ID),
             intent: user.get(FirestoreNames.INTENT),
           };
           request.post('https://actions.googleapis.com/v2/conversations:send', {
             'auth': {
               'bearer': tokens.access_token,
             },
             'json': true,
             'body': {'customPushMessage': notification, 'isInSandbox': true},
           }, (err, httpResponse, body) => {
             if (err) {
               throw new Error(`API request error: ${err}`);
             }
             console.log(`${httpResponse.statusCode}: ` +
               `${httpResponse.statusMessage}`);
             console.log(JSON.stringify(body));
           });
         });
       })
       .catch((error) => {
         throw new Error(`Firestore query error: ${error}`);
       });
 });
 conv.ask('A notification has been sent to all subscribed users.');
});

Test your push notifications

In the terminal, run the following command to deploy your updated webhook code to Firebase:

firebase deploy

To test out notifications in the Actions simulator, follow these steps:

  1. In the Actions console, go to the Test tab.
  2. Type Talk to my test app into the Input field and press enter.
  3. Type Learn about classes and press enter.
  4. Type Get notifications and press enter.
  5. If you haven't already granted your Action permission to send you push notifications, type yes and press enter.
  6. Type yes and press enter. Your Google account should now be subscribed to push notifications for this Action.

3a8704bdc0bcbb17.png

  1. Type no and press enter to exit.
  2. Type Talk to my test app and press enter to start a new conversation.
  3. Type Test notification and press enter.

634dfcb0be8dfdec.png

Within a few minutes you should receive a "Test Notification from Action Gym" Assistant push notification on your mobile device. Tapping this notification will deep link you to the Class Canceled intent of your Action.

33cbde513c10122e.png

5. Create an Assistant link

So far we've discussed engagement features that you can implement to keep users coming back to your Action, but those are predicated on having users who discover and use your Action.

You can create an Assistant link that will link users on mobile devices directly to your Action on Assistant. Since an Assistant link is a standard hyperlink, you can add it to a website or any web marketing materials like a blog or social media post.

In this step, you'll learn about what an Assistant link is, how to create one for your Action's welcome intent, and how to add it to a simple website for testing.

How will this engage users?

Drawing users to your Action for the first time can be challenging, especially when they need to explicitly invoke your Action on Assistant. An Assistant link alleviates this friction by giving users a direct link to your Action. When a user follows your Assistant link on an Assistant-enabled device, they're taken directly to your Action. When a user opens your link on a non-mobile device or any other device that doesn't support Assistant, they'll still be taken to your Actions directory listing (if it's been published) so the link can still market your Action to those users.

Assistant links can be a useful engagement tool, so you should create one if you're planning on advertising your Action through your website or social media. Just be aware of the following tips before you create and distribute an Assistant link:

  • Assistant links only work once your Action is published. While your project is in a draft state, the link will only work on your own devices. Anyone else will be taken to a 404 page in the Actions directory.
  • You can let users test an Assistant link prior to publishing by releasing your Action in an alpha or beta environment. Note that only users who participate in your alpha or beta will be able to test your Assistant link.
  • Make sure the destination intent for your Assistant link makes a good first impression with new users. Your welcome intent is the default destination for an Assistant link because it should already do a good job of introducing your Action

Follow these steps to create an Assistant link for the welcome intent:

  1. In the Actions console, click the Develop tab, and chooseActions in the left navigation bar.
  2. Click on actions.intent.MAIN under the Actions list.
  3. Under the Links section, toggle the Would you like enable a URL for this Action option.
  4. Set a descriptive Link title that describes your Action. Make your title a simple verb-noun pair that describes what the user can accomplish with your Action. For this example, set the Link title to learn about Action Gym.
  5. Copy the HTML snippet from the bottom of this page and save it for later.
  6. Click Save at the top of the page.

55341b8102b71eab.png

Deploy a test website

To test your Assistant link, you can use Firebase tools to deploy a test website alongside your fulfillment. We've already built a simple test website for this example, you just need to add your Assistant link.

Go to your fulfillment's /user-engagement-codelab-nodejs/start/public/ directory and open the index.html file in a text editor.

b2f84ff91b0e1396.png In the index.html file, paste your Assistant link's HTML snippet into the body element. The file should end up looking like the snippet below:

index.html

<body>
    <p>
     <a href="https://assistant.google.com/services/invoke/uid/000000efb5f2fd97">🅖 Ask my test app to learn about Action Gym
     </a>
    </p>
</body>

In the terminal, run the following command to deploy your test website to Firebase:

firebase deploy

Once the deploy command finishes running, take note of the Hosting URL in the output.

b01e8d322fb5d623.png

Go to this URL on your mobile device's web browser and you should see the Assistant link on your test website. Clicking this link on your mobile device should take you to your Action's welcome intent in Assistant.

599845d647f5b624.png

You can also try going to the Hosting URL on a desktop browser, which should take you to a 404 page in the Assistant directory since your Action isn't published.

6. Next steps

Congratulations!

You've now learned about the importance of user engagement when developing an Action, what user engagement features are available on the platform, and how to add each feature to an Action.

Additional learning resources

Explore these resources to learn more about user engagement for your Action:

Follow us on Twitter @ActionsOnGoogle to stay tuned to our latest announcements, and tweet to #AoGDevs to share what you have built!

Feedback survey

Before you go, please fill out this form to let us know how we're doing!