Updates and Notifications

Overview

Updates and notifications allow your Assistant app to re-engage with users through push notifications and scheduled daily updates. During normal interactions with your app, you can ask users to opt-in to receive updates. Updates and notifications may then be pushed by your service, or pulled at a scheduled time by Google. For now, updates are surfaced as system notifications on the user's Assistant-enabled phones, but we will be expanding to new surfaces soon.

User experience

The user experience for updates and notifications can be broken down into five major steps:

  1. Discovery

    The user must first find out that your app can offer proactive updates and notifications. You can provide discovery for your updates during normal conversations with users. For example, after showing the user a piece of content they requested, you might show a suggestion chip offering to send similar content daily.

    In some cases, Google can provide discovery for your updates and notifications. For example, after the third day in a row they ask for a joke from the same Assistant app, Google might automatically ask them whether they'd like to receive the content daily.

  2. Personalization

    For certain types of updates and notifications, you may need to collect some information from the user before finally requesting they opt-in. For example, a weather alert Update likely requires the user to specify a zip code before opting in, so that the content can be targeted to the appropriate location.

  3. Opt-in

    Once the user has discovered your proactive experience and you've gotten all the personalization information you need, you'll need to get their consent to "push" updates, or ask them to set-up a scheduled update.

    Google provides a built-in experience to opt the user in. This flow will be customized according to the specific type of update the user is requesting. Your app can provide multiple types of updates (for example, both a daily news briefing in addition to a breaking news alert).

  4. Receiving updates

    After the user opts in, they will start receiving updates and notifications from your app. These may be triggered by your service (eg. for a weather alert), or by Google (eg. for a scheduled daily joke).

    Updates will show up as system notifications on the user's Assistant-enabled phones. Once they tap one of these notifications, they are deep-linked into conversation with your app, where you can then provide the appropriate proactive content.

  5. Managing updates

    Users may wish to stop receiving updates from your app. Google will add a "Turn off" button on the notifications sent to their phone. If the user taps this button, Google will confirm that they wish to stop receiving updates from your app. The user can also ask the Assistant to "stop sending updates from $app" at any time.

Configuration

The two main use cases for the Updates API are Daily updates and Push notifications:

Daily updates

Daily updates are sent to users at a scheduled time every day. If your app makes sense as part of a daily routine, or you've seen users repeatedly requesting a similar experience from your app on a regular basis, you likely want to support daily updates for your app. Google can then proactively remind the user to trigger your app by sending them a push notification at a scheduled time.

In this example, we will be configuring an app called JokesApp. When the user invokes this app, it asks the user whether they want a joke then tells one if prompted. This guide will walk through setting up JokesApp so the user can receive a daily joke.

Prerequisites

To get started, you should have an Assistant app with an additional triggering intent containing the content you'd like to make available as a daily update.

Console

In the console, you will need to configure your app to support updates:

  1. In the Actions Console, navigate to Overview > Action discovery and updates.
  2. Click the Action matching the additional triggering intent you'd like to enable Updates.

    For the JokesApp example, we are selecting "tell_joke".

  3. Scroll down to the User updates and notifications section and turn on Would you like to offer daily updates to users.

  4. Enter a Content title.

    For example, the "tell_joke" action could have the title "Joke".

  5. Click Save.

Handling update requests

To handle your users' request for daily updates, you will need to declare the actions.intent.CONFIGURE_UPDATES intent. You can configure this intent in the Action Package for Actions SDK, or by creating a Dialogflow intent with action_intent_CONFIGURE_UPDATES set as the event. When users opt for daily updates, the Assistant will trigger your actions.intent.CONFIGURE_UPDATES intent.

When the user taps the notification, your service will receive a normal request to the intent, which will need to call askToRegisterDailyUpdate:

  1. Navigate to your actions.intent.CONFIGURE_UPDATES intent.
  2. Under Responses, go to the Google Assistant tab, click Add Message Content, and select Custom Payload.
  3. In the "Custom Payload" box, add the following code to call the AskToRegisterDailyUpdate helper. Swap INTENT_NAME to your intent's name.

    {
      "google": {
        "system_intent": {
          "intent": "actions.intent.REGISTER_UPDATE",
          "data": {
            "@type":
                 "type.googleapis.com/google.actions.v2.RegisterUpdateValueSpec",
            "intent": "INTENT_NAME",
            "updateContextValueSpec": { "timeContext": { "frequency": "DAILY" } }
          }
        }
      }
    }
    

    If using a webhook, you can call this API directly via the client library:

    appMap.set('setup_update', function(app) {
      app.askToRegisterDailyUpdate('INTENT_NAME');
    })
    
  4. Add one more intent called "finish_update_setup" and enter actions_intent_REGISTER_UPDATE as its Event.

  5. Set the intent's Action to "finish_update_setup" as well.

  6. In your webhook, open index.js and add the following. Replace Ok, I'll start giving you daily updates with whatever response you want to give the user:

    appMap.set('finish_update_setup', function(app) {
      app.tell("Ok, I'll start giving you daily updates.");
    })
    
  7. Add the following code to check whether the user opted in successfully:

    appMap.set('finish_update_setup', function(app) {
      let result = app.getRegisterUpdateValue();
      if (app.isUpdateRegistered()) {
        app.tell("Ok, I'll start giving you daily updates.");
      } else {
        app.tell("Ok, I won't give you daily updates.");
      }
    }
    
  8. Deploy the webhook to Firebase Functions and enable webhook fulfillment in Dialogflow.

Testing

You can now test your app's daily updates to see if they work. The following example shows the testing flow for JokesApp:

  1. Go to the Actions Console and click Simulator, then Start Testing.
  2. In the chat box, enter "ask my test app for a joke"
  3. The app should respond: "Why did the chicken cross the road? To get to the other side."
  4. After the app exits, the Assistant will prompt the user to ask whether they would like to receive updates.

  5. If you respond with "yes" to the post-dialog prompt, it should ask you when you'd like to receive a daily joke. Select a time to complete the opt-in.

  6. You should receive a notification to your phone at the scheduled time. Once you tap it, you should be deep linked into conversation with the app, which should tell you a joke before exiting.

  7. If you say "manage my subscriptions" to the Assistant on your device, you can delete the daily subscription you've created.

Optional: Opt-in during conversation

You may want to build the daily updates opt-in flow directly into your app rather than letting Google handle discovery.

  1. Open the Google Assistant tab under Responses, click Add Message Content, and select Suggestion chips.
  2. Set the chip text for your daily update prompt. You'll want this to be titled "Send daily" or something similar.

  3. Add another Dialogflow intent called "setup_update" with the user expression set the exact same as your daily update prompt (i.e. "Send daily").

  4. Configure "setup_update" as described above in Handling Update Requests.

Push notifications

For some use cases, your app will know best when the user should receive an update. For example, an Overdue Task alert wouldn't work as a daily scheduled update. In this case, you will want to set up push notification updates. You can then push notifications to the user requesting they trigger your app.

In this example, we will be configuring an app called TaskApp. When the user invokes the app, it tells them whether they have any overdue tasks and gives the option to list all their tasks. This guide will walk through setting up TaskApp to send the user a notification when a task is overdue.

Prerequisites

To get started, you should have an Assistant app with an additional triggering intent containing the content you'd like to make available as a daily update.

Console

In the console, you will need to configure your app to support updates:

  1. In the Actions Console, navigate to Overview > Action discovery and updates.
  2. Click the Action matching the additional triggering intent you'd like to enable Updates.

    For the TasksApp example, we are selecting "check_overdue_tasks".

  3. Scroll down to the User updates and notifications section and turn on Would you like to send push notifications.

  4. Enter a Content title.

    For example, the "check_overdue_tasks" action could have the title "Overdue Tasks".

  5. Click Save.

Opt-in during conversation

Unlike daily updates above, Google will not automatically request the user to opt-in. You must instead build the opt-in flow directly into your app.

Google provides the AskForUpdatePermission helper API that you can call to opt the user into push notifications from your app.

  1. Navigate to Dialogflow and select the intent you're configuring for updates.
  2. Scroll down to Response and open the Google Assistant tab.
  3. Click Add message content and select Suggestion chips.
  4. Set the chip text for your push notification prompt. You'll want this to be titled "Alert me" or something similar.
  5. Add another Dialogflow intent called "setup_update" with the user expression set the exact same as your push notification prompt (i.e. "Alert me").

  6. Under Responses, go to the Google Assistant tab, click Add Message Content, and select Custom Payload.

  7. In the "Custom Payload" box, add the following code to call the AskForPermission helper. Swap INTENT_NAME to your intent's name.

    {
      "google": {
        "system_intent": {
          "intent": "actions.intent.PERMISSION",
          "data": {
            "@type": "type.googleapis.com/google.actions.v2.PermissionValueSpec",
            "permissions": [
              "UPDATE"
            ],
            "updatePermissionValueSpec": { "intent": "INTENT_NAME" }
          }
        }
      }
    }
    

    If using a webhook, you can call this API directly via the client library (you'll need to set the Dialogflow action to "setup_alerts" as well):

    actionMap.set('setup_alerts', function(app) {
      app.askForUpdatePermission('INTENT_NAME');
    })
    
  8. Add one more intent called "finish_permission" and enter actions_intent_PERMISSION as its Event

  9. Set the intent's Action to "finish_permission" as well

  10. Open your index.js file and add the following to handle "finish_permission" with your webhook. Replace Ok, I'll start alerting you with whatever response you want to give the user.

    actionMap.set('finish_permission', function(app) {
      app.tell("Ok, I'll start alerting you");
    })
    
  11. Add the following code to check whether the user opted in successfully:

    actionMap.set('finish_permission', function(app) {
      if (app.isPermissionGranted()) {
        /* placeholder to persist the user's opt-in with your web service
        myWebService.newAlertUser(app.getUser().userId); */
        app.tell("Ok, I'll start alerting you");
      } else {
        app.tell("Ok, I won't alert you");
      }
    
  12. Deploy the webhook to Firebase Functions and enable webhook fulfillment in Dialogflow

Send notifications

Once you have a new user opted in, you can use the Conversation Send API to push notifications to them. Your service should have access to the persisted user ID and the intent they opted in to receive notifications from. For this example, there's just one: the "check_overdue_tasks" intent.

You'll need to setup and download a JSON service account key to use the Conversation Send API. You can then use the Google OAuth2 client library to exchange the JWT token for an access token. This access token can be used to authenticate your requests to the API.

Get a service account key
  1. Go to this URL, swapping "example-project-1" at the end for your project ID in the Actions Console: [https://console.developers.google.com/apis/api/actions.googleapis.com/overview?project=example-project-1]
  2. If you see an Enable button, click it. Otherwise, proceed to step 3.
  3. Go to this URL, swapping "example-project-1" at the end for your project ID in the Actions Console: [https://console.developers.google.com/apis/credentials?project=example-project-1]
  4. Click Create credentials > Service Account Key.
  5. Click the Select box under Service Account and click New Service Account.
  6. Give the Service Account a name like "notifications" and the Role of Project Owner.
  7. Select the JSON key type and click Create.
  8. A JSON service account key will be downloaded to your local machine.
Exchange the key for an access token

In your web service, you'll need to exchange the service account key for an access token. We recommend using a Google API client library for this. In the following example, we've already included the Node.js client library.

Add the following code to use the client library to make a request to the Send API:

const google = require('googleapis');
const key = require(PATH_TO_KEY);

let jwtClient = new google.auth.JWT(
  key.client_email, null, key.private_key,
  ['https://www.googleapis.com/auth/actions.fulfillment.conversation'],
  null
);

jwtClient.authorize(function (err, tokens) {
// placeholder for notification send
});

You will need to add the Google OAuth2 client library and the 'request' library to your Node.js package.json:

npm install googleapis request --save
Make requests to the Conversation Send API

Now you're ready to send notifications. Use the following code:

let notif = {
  userNotification: {
    title: 'Pay Parking tickets',
  },
  target: {
    userId: '<USER_ID>',
    intent: 'check_overdue_tasks'
  }
}

console.log(JSON.stringify(tokens) + "\n" + JSON.stringify(notif));

request.post('https://actions.googleapis.com/v2/conversations:send', {
  'auth': {
    'bearer': tokens.access_token
  },
  'json': true,
  'body': { 'customPushMessage': notif, 'isInSandbox': true }
}, function(err,httpResponse,body) {
  console.log(httpResponse.statusCode + ': ' + httpResponse.statusMessage)
});

Testing

You can now test your app's daily updates to see if they work. The following example shows the testing flow for TaskApp:

  1. Go to the Actions Console and click Simulator, then Start Testing.
  2. In the chat box, enter "talk to my test app".
  3. The app should respond with a prompt asking the user if they want to hear about their tasks.
  4. Enter "yes" and the app should tell you about an overdue task.
  5. It should also show a suggestion chip: "Alert me"
  6. If you tap the chip, it should ask for your permission to send notifications. Say yes and it should respond: "Ok, I'll start sending Overdue Task alerts"
  7. Access your webhook logs. If using Firebase Functions, find them by clicking Backend Services then View in Firebase under Cloud Functions. Click Logs in the Firebase console. You should find a log line titled Request body. Expand it, find the "userId" field, and take note of the value.
  8. Update the USER_ID placeholder in the code above to the userId string you found in the logs.
  9. Execute send.js with the command node send.js.
  10. You should immediately receive a push notification on your Assistant-enabled phone.
  11. Tap it, and you should be deep linked into the "check_overdue_tasks" intent of your app.

Personalization

To create more personal experiences, you may want to personalize Updates for the user. You can do this by specifying an argument value when you opt the user in.

Personalized push notifications

In the following example, we will personalize the Overdue Task alert by letting the user set a task category they want to receive alerts about.

  1. Open the TaskApp agent in Dialogflow and open the Entities screen.
  2. Click Create Entity and name it taskCategory.
  3. Add some entries like the following:

    • Reference value: "home"

      Synonyms: "house", "home", "personal"

    • Reference value: "work"

      Synonyms: "job", "work"

  4. Click Save, then open the check_overdue_tasks intent.

  5. Under Action, create a parameter with the following options:

    1. Enter a parameter name of taskCategory
    2. Set the Entity to @taskCategory
  6. Change the Text response to You have one $taskCategory task: test task.

  7. Save the intent, then open the setup_alerts intent.

  8. Under Action, create a parameter with the following options:

    1. Check the box under Required.
    2. Enter a parameter name of taskCategory.
    3. Set the Entity to @taskCategory.
    4. Click Define prompts and enter a prompt like "Which task category do you want alerts for?"
  9. Enable webhook fulfillment for setup_alerts and save the intent.

  10. Add or replace the setup_alerts handler to the following code in index.js:

    appMap.set('setup_alerts', function(app) {
      let taskCategory = app.getArgument("taskCategory");
      app.askForUpdatePermission('check_overdue_tasks'
        [{"name": "taskCategory", "textValue": taskCategory }]
      );
    })
    
  11. Deploy the webhook to Firebase Functions.

  12. Now, when you run send.js, the taskCategory argument should automatically be populated when you tap the notification.

Personalized daily updates

In the following example, we will update our JokeApp to let the user pick a category for the jokes they receive daily.

  1. In the Actions Console, find the Updates config for "tell_joke", re-check a option under When do you want your updates to appear, and click Save.
  2. Open the JokesApp agent in Dialogflow and open the Entities screen.
  3. Click Create Entity and name it jokeCategory.
  4. Add some entries like the following:

    • Reference value: "pun"

      Synonyms: "word"

    • Reference value: "dad"

      Synonyms: "dad joke", "dad"

  5. Click Save, then open the tell_joke intent.

  6. Check End conversation under Google Assistant.

  7. Under Action, create a parameter with the following options

    1. Enter a parameter name of jokeCategory
    2. Set the Entity to @jokeCategory
  8. Change the Text response to Here's your $jokeCategory joke: test joke.

  9. Save the intent, then open the setup_update intent.

  10. Set your intent to support the CONFIGURE_UPDATES intent as described above.

  11. Under Action, create a parameter with the following options:

    1. Check the box under Required.
    2. Enter a parameter name of jokeCategory.
    3. Set the Entity to @jokeCategory.
    4. Click Define prompts and enter a prompt like Which category of joke would you like to receive?
  12. Save the intent. In index.js, add a handler for setup_update as follows:

    appMap.set('setup_update', function(app) {
      app.askToRegisterDailyUpdate(
        'tell_joke',
        [{name: 'jokeCategory', textValue: jokeCategory}]
      );
    })
    
  13. Deploy the webhook to Firebase Functions.

  14. Now, when you test, you should see the automatically-created "Send Jokes daily" chip. When you tap it, you should be deep-linked into the setup_update intent.

  15. Then, when you receive the scheduled notification and tap it, the jokeCategory argument should be populated for you.