通过适用于 Google 助理的 Action 吸引用户

1. 概览

Google 助理是 Google 虚拟智能个人助理,借助 Actions on Google 开发者平台,您可以打造软件,从而为超过 10 亿台设备(包括智能音箱、手机、汽车、电视、头戴式耳机等)扩展 Google 助理的功能。用户在对话中与 Google 助理互动以处理各种事务,例如购买日用品或约车。(有关操作的完整列表,请参阅 Actions 目录。)作为开发者,您可以使用 Actions on Google 在用户与您的第三方服务之间轻松打造和管理令人愉悦且高效的对话体验。

这是一个高级 Codelab 单元,适合在构建适用于 Google 助理的 Action 方面具备一定经验的读者。如果您之前没有任何 Actions on Google 开发经验,我们强烈建议您通过学习我们的入门级 Codelab(第 1 级第 2 级第 3 级)熟悉该平台。这些高级模块将引导您了解一系列功能,帮助您扩展 Action 的功能并扩大受众群体。

衡量 Action 是否成功的一个重要方法是用户互动度,即 Action 在将用户首次互动后吸引回来方面的有效性。为了简化操作,您可以在 Action 中实现多项功能,为用户提供返回对话的路径。

此 Codelab 介绍了 Actions on Google 的用户互动度功能以及最佳实践。

a3fc0061bd01a75.png 961ef6e27dc73da2

构建内容

启用已构建的功能后,您可以:

  • 向用户发送每日更新,他们可以点按该动态来与您的 Action 对话
  • 向用户发送链接回您的 Action 的推送通知
  • 创建一个可将用户从移动网络浏览器转到你的 Action 的链接

学习内容

  • 什么是用户互动,以及这种互动度对 Action 的成功至关重要
  • 如何修改 Action 以提高用户互动度
  • 在不同类型的 Action 中使用哪些用户互动功能
  • 如何使用 Actions API 通过 Google 助理发送通知

所需条件

您必须拥有以下工具:

  • 您选择的 IDE/文本编辑器,例如 WebStormAtomSublime
  • 已安装 Node.js、npm 和 git 的终端,用于运行 shell 命令
  • 网络浏览器,例如 Google Chrome
  • 使用 Firebase 命令行界面的本地开发环境
  • 装有 Google 助理的移动设备(Android 或 iOS 设备)。登录 Google 助理时所用的 Google 账号必须与构建此项目时所用的账号相同。

我们也强烈建议您(但并非必须)熟悉 JavaScript (ES6) 来理解 webhook 代码。

2. 设置项目

本部分介绍了如何向之前构建的完整 Action 添加用户互动功能。

了解示例

此 Codelab 的示例是一个针对虚构健身房“Action Gym”的简单 Action。该 Action 提供健身房的相关信息,包括每天轮流的课程列表。像这样的信息性 Action 适合所有用户互动功能,因为轮播的类别列表每天会提供不同的实用信息。

下图显示了 Action Gym 示例的对话流程:

e2d6e4ad98948cf3.png

您将对对话框稍作修改,使其更适合您添加的互动功能。不过,对话的一般设计不会有太大变化。

下载基础文件

运行以下命令,克隆此 Codelab 的 GitHub 代码库:

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

设置项目和代理

如需设置 Actions 项目和 Dialogflow 代理,请完成以下步骤:

  1. 打开 Actions 控制台
  2. 点击 New project
  3. 输入项目名称,例如 engagement-codelab
  4. 点击创建项目
  5. 向下滚动至更多选项部分,然后点击对话卡片,而非选择类别。
  6. 点击 Build your Action,展开选项并选择 Add Action(s)
  7. 点击添加首个操作
  8. Create Action 对话框中,选择 Custom Intent,然后点击 Build 以启动 Dialogflow 控制台。
  9. 在 Dialogflow 控制台的代理创建页面中,点击创建
  10. 点击左侧导航栏中的 6bf56243a8a11a3b(齿轮图标)。
  11. 点击导出和导入,然后点击从 ZIP 文件恢复
  12. 从您之前下载的 /user-engagement-codelab-nodejs/start/ 目录中上传 agent.zip 文件。
  13. 输入 RESTORE,然后点击恢复
  14. 点击完成

部署执行方式

现在,您的 Actions 项目和 Dialogflow 代理都已准备就绪,请使用 Firebase Functions CLI 部署本地 index.js 文件。

从克隆的基础文件的 /user-engagement-codelab-nodejs/start/functions/ 目录中,运行以下命令:

firebase use <PROJECT_ID>
npm install
firebase deploy

几分钟后,您应该会看到“Deploy complete!”,这表示您已成功将 webhook 部署到 Firebase。

检索部署网址

您需要向 Dialogflow 提供该 Cloud Functions 函数的网址。如需检索此网址,请按以下步骤操作:

  1. 打开 Firebase 控制台
  2. 从选项列表中选择您的 Actions 项目。
  3. 转到开发 >函数。如果系统提示您“选择数据共享设置”,则可以点击以后再说来忽略此选项。
  4. 信息中心标签页下,您应该会看到“fulfillment”条目并在触发器下添加一个网址。保存此网址;在下一部分中,您需要将其复制到 Dialogflow 中。

1741a329947975db

在 Dialogflow 中设置网络钩子网址

现在,您需要更新 Dialogflow 代理,以将 webhook 用于 fulfillment。为此,请按以下步骤操作:

  1. 打开 Dialogflow 控制台(如果您愿意,可以关闭 Firebase 控制台)。
  2. 点击左侧导航栏中的 Fulfillment
  3. 启用网络钩子
  4. 如果您从 Firebase 信息中心复制的网址尚未显示,请粘贴该网址。
  5. 点击保存

验证项目设置是否正确

用户应该能够调用您的操作来获取有关 Action Gym 的信息,包括包含营业时间的硬编码文本回复,以及列出一周中每一天的课程安排的文本回复。

如需在 Actions 模拟器中测试您的 Action,请执行以下操作:

  1. 在 Dialogflow 控制台的左侧导航菜单中,点击集成 >Google 助理
  2. 确保已启用 Auto-preview changes(自动预览更改),然后点击 Test(测试)以更新您的 Actions 项目。
  3. Actions 模拟器会加载您的 Actions 项目。如需测试您的 Action,请在 Input 字段中输入 Talk to my test app,然后按 Enter 键。
  4. 您应该会看到一条欢迎你使用 Action Gym 的回复。尝试按照提示继续对话,同时确保执行方式针对每项输入都有响应。

60acf1ff87b1a87f

3. 添加每日更新订阅

吸引用户的常见方法是在最需要的时候向他们提供信息。这是通过为用户提供订阅 intent 的每日更新选项来实现的,这会向用户发送直接链接到该 intent 执行方式的 Google 助理通知。

在此步骤中,您将了解每日更新订阅并将其添加到您的 Action 的 Class List intent 中。按照以下说明操作后,您的 Action 对话将如下图所示:

f48891c8118f7436.png

这会如何吸引用户?

智能手机用户可能熟悉推送通知,这类通知会提供应用特定的信息和更新。通过每日更新订阅,您可以轻松通过 Google 助理以外的移动设备联系用户,前提是您发送更新所针对的 intent 会继续每天为用户带来价值。

每日更新是一款实用的互动工具,但不一定要包含在每项 Action 中。在决定是否向 Action 添加每日更新订阅时,请考虑以下提示:

  • 确保每天更新会使用户每天看到不同的实用信息。如果点按每日更新时每次都显示相同的提示,用户可能会在几天后退订。
  • 如果用户直接跳转到每日更新的意图,请确保对话框对他们而言是有意义的。用户不一定要从对话开始,因此不应指望他们了解太多的上下文。
  • 在提示用户订阅每日动态之前,先向他们展示您的 Action 的好处。您的用户应该在想:“我希望每天都能看到这些内容”。
  • 不要向用户重复提出订阅建议。在向用户展示他们将会订阅的内容后,立即提供每日更新订阅,避免在别处纠缠不休。
  • 在触发更新 intent 后,确保对话简短。大多数每日更新都应仅包含一条响应,然后关闭,无需用户输入。

开启每日动态

每日更新订阅可以添加到欢迎 intent 中,使用户进入对话的开头;也可以添加到更具体的 intent 中,通过深层链接将用户引至对话中的某个位置。在此 Codelab 中,Class List intent 最为合理,因为对话框每天都会发生变化,用户可能会发现提醒自己有哪些可用类很有用。

请按照以下步骤为 Class List intent 启用每日更新:

  1. 在 Actions 控制台中,点击 Develop 标签页,然后在左侧导航栏中选择 Actions
  2. 点击 Actions 列表下的 Class List
  3. 用户互动部分下,切换您希望向用户提供每日动态选项。
  4. 设置一个描述每日更新的描述性内容标题。背景信息将是“您希望我何时发送每日<内容标题>”,因此请确保您的标题既描述清晰,又大声读出来。在此示例中,请将内容标题设置为 list of upcoming Action Gym classes
  5. 点击页面顶部的保存

c00885cc30e14d68.png

设置 Dialogflow

在 Dialogflow 控制台中,按照以下步骤为每日更新订阅流程创建 intent:

提示用户订阅

  1. 设置一个新的 intent 来处理要求订阅每日动态的用户。在 Dialogflow 控制台中,点击左侧导航栏中意图 (Intents) 旁边的 + 按钮以创建新的意图。
  2. 将此新 intent 命名为 Setup Updates
  3. 训练短语部分下,添加以下用户表述
  • Send daily reminders
  • Reminder
  • Remind me
  • Updates
  • Upcoming classes
  1. Fulfillment 部分下,切换为此 intent 启用 webhook 调用 (Enable webhook call for this intent) 选项。
  2. 点击页面顶部的保存

5c70faa02151da0

处理用户的决定

  1. 设置一个新 intent 来处理用户对每日更新订阅提示的响应。点击左侧导航栏中意图 (Intents) 旁边的 + 按钮以创建新的意图。
  2. 将此新 intent 命名为 Confirm Updates
  3. 事件部分下,添加 actions_intent_REGISTER_UPDATE。用户完成每日更新订阅流程后,无论是否最终订阅,都会触发此 Dialogflow 事件。
  4. Fulfillment 部分下,切换为此 intent 启用 webhook 调用 (Enable webhook call for this intent) 选项。
  5. 点击页面顶部的保存

b871c2bdadac8abc.png

实现 fulfillment

如需在 webhook 中实现 fulfillment,请完成以下步骤:

加载依赖项

b2f84ff91b0e1396.pngindex.js 文件中,更新 require() 函数以添加 actions-on-google 软件包中的 RegisterUpdate 软件包,这样您的导入代码将如下所示:

index.js

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

更新建议内容信息卡

b2f84ff91b0e1396.pngindex.js 文件中,向建议内容信息卡标题列表添加一个 DAILY 条目,因此您的 Suggestion 定义如下所示:

index.js

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

为新 intent 添加执行方式

当用户表示想要订阅时,通过使用更新的目标 intent (Class List) 和类型 (DAILY) 调用 RegisterUpdate 帮助程序,启动每日更新订阅流程。订阅流程完成后,Google 助理会使用 status 参数触发 actions_intent_REGISTER_UPDATE 事件,该参数用于描述订阅是否成功。向用户提供根据订阅状态而变化的后续提示。

b2f84ff91b0e1396.pngindex.js 文件中,添加以下代码:

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]));
  }
});

为用户提供备选提示

您的课程列表响应最后会提供每日更新订阅,但这样就会带来问题。由于用户点按每日更新通知时会触发相同的响应,因此系统仍会要求他们订阅每日动态,即使这些动态来自于某次更新。如何让用户不认为他们需要重新订阅?

幸运的是,conv 对象的参数包含有关用户在何处发起对话的信息。您可以检查 conv 参数以查看它们是否包含 UPDATES 部分(指示用户从每日更新通知发起对话),并相应地更改响应。您还可以使用此对话分支在提供类列表后立即关闭对话框,这遵循我们的最佳实践,即保持每日更新简短。

b2f84ff91b0e1396.pngindex.js 文件中,替换以下代码:

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]));
  }
});

替换为:

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]));
    };
  };
});

测试每日更新

在终端中,运行以下命令,将更新后的 webhook 代码部署到 Firebase:

firebase deploy

如需在 Actions 模拟器中测试自定义重新提示,请按以下步骤操作:

  1. 在 Actions 控制台中,前往 Test
  2. Input 字段中输入 Talk to my test app,然后按 Enter 键。
  3. 输入 Learn about classes,然后按 Enter 键。现在,您的 Action 响应应该会询问是否发送每日提醒。
  4. 输入 Send daily reminders,然后按 Enter 键。
  5. 输入您希望看到更新的时间,然后按 Enter 键。出于测试目的,请尝试比当前时间晚 3-5 分钟再回复。

83a15ecac8c71787

在移动设备上,您应该会在您指定的更新时间前后收到 Google 助理发出的通知。请注意,此通知可能需要几分钟才能显示。点按该通知,它应该会深层链接到 Google 助理中的 Class List intent,从而为您提供即将开始的课程的列表:

8582482eafc67d5b

4. 添加推送通知

您还可以通过调用 Actions API 向用户发送推送通知,作为在 Action 之外吸引用户的另一种方式。与每日动态不同,Google 助理不会自动排定这些通知的发送时间,因此您可以随意向其发送通知。

在此步骤中,您将了解如何在 Action 中实现推送通知,具体方法是添加新的 Class Canceled intent,并向用户发送通知以通知他们课程取消。您还将设置发送通知所需的以下三个组件:

  • Actions API 账号 - 您可以通过向 API 发送 POST 请求来向用户发送通知,因此您需要设置服务账号和凭据,以便与此 API 连接。
  • 权限帮助程序 - 您需要获得用户的许可,才能访问其发送推送通知所需的用户 ID。在此示例中,您将使用客户端库函数来调用权限帮助程序并请求此 ID。
  • 存储 - 为了在对话外向用户发送推送通知,您需要将用户 ID 存储在可以随时调用的位置。在此示例中,您将设置 Firestore 数据库来存储每个用户的信息。

按照这些说明,你会将以下对话框添加到 Action 的对话中:

7c9d4b633c547823

这会如何吸引用户?

智能手机用户可能熟悉推送通知,这类通知会提供应用特定的信息和更新。推送通知是用户通过 Google 助理以外的移动设备访问用户的一种灵活方式,前提是用户有充分的理由启用推送通知。通过每日更新,用户已经知道他们每天都会收到通知。但是,使用推送通知,用户不知道他们是选择接收不常收到的通知,还是每天会收到多条通知。

推送通知是一款实用的互动工具,但不一定要包含在每个 Action 中。在决定是否向 Action 添加推送通知时,请考虑以下提示:

  • 计划一些推送通知的时间安排示例。如果您打算每天只发送一条推送通知,可以考虑改用每日更新。
  • 确保你每次收到推送通知时都能提供有用的信息。您的通知还可以通过深层链接指向您的某个 Action 的 intent,因此请确保该 intent 实用且与操作相关。
  • 在要求用户订阅推送通知时要明确明确。他们应该了解每条推送通知的预期内容,并知道发送通知的频率。

启用 Actions API

  1. 打开 Google Cloud 控制台,然后从下拉列表中选择您的 Actions 项目名称。

d015c1515b99e3db.png

  1. 在导航菜单 (☰) 中,转到 API 和服务 >内容库。
  2. 搜索 Actions API,然后点击启用

6d464f49c88e70b4

创建服务账号

Actions API 需要身份验证,因此您需要创建服务账号来发送请求。请按照以下步骤为 Actions API 创建和安装服务账号密钥:

  1. 在 Google Cloud 控制台的导航菜单 (☰) 中,转到 API 和服务 >凭据
  2. 点击创建凭据 >服务账号密钥
  3. 服务账号下拉菜单中,选择新建服务账号
  4. 填写以下信息:
  • 服务账号名称service-account
  • 角色:项目 >负责人
  • 服务账号 ID service-account(始终后跟 @<project_id>.iam.gserviceaccount.com)
  • 密钥类型:JSON
  1. 点击创建
  2. 将下载的 JSON 文件移动到您项目的 /user-engagement-codelab/start/functions/ 目录中。
  3. 将 JSON 文件重命名为 service-account.json

d9bd79d35691de3a.png

启用 Firestore

为了在对话外发送通知,您需要一种方法来存储可从通知代码中引用的用户 ID。在此示例中,我们使用 Firestore 数据库来存储订阅用户的用户 ID。

请按照以下步骤为您的 Action 创建 Firestore 数据库:

  1. Firebase 控制台中,选择您的 Actions 项目名称。
  2. 在左侧导航栏中,转到开发 >数据库,然后点击创建数据库
  3. 选择以测试模式开始
  4. 点击启用

6dfc386413954caa

设置 Dialogflow

在 Dialogflow 控制台中,按照以下步骤创建推送通知选择启用流程:

提示用户订阅

  1. 设置一个新的 intent 来处理针对已取消的类请求订阅推送通知的用户。在 Dialogflow 控制台中,点击左侧导航栏中意图 (Intents) 旁边的 + 按钮以创建新的意图。
  2. 将此新 intent 命名为 Setup Push Notifications
  3. 训练短语部分下,添加以下用户表述
  • Subscribe to notifications
  • Send notification
  • Notify me
  • Send class notifications
  • Cancelled notifications
  1. Fulfillment 部分下,切换为此 intent 启用 webhook 调用 (Enable webhook call for this intent) 选项。
  2. 点击页面顶部的保存

3d99bc41d0492552

处理用户的决定

  1. 设置一个新的 intent 来处理用户对推送通知订阅提示的响应。点击左侧导航栏中意图 (Intents) 旁边的 + 按钮以创建新的意图。
  2. 将此新 intent 命名为 Confirm Push Notifications
  3. 事件部分下,添加 actions_intent_PERMISSION。当用户完成推送通知订阅流程时,无论他们最终是否订阅,都会触发此 Dialogflow 事件。
  4. Fulfillment 部分下,切换为此 intent 启用 webhook 调用 (Enable webhook call for this intent) 选项。
  5. 点击页面顶部的保存

d37f550c5e07cb73.png

处理推送通知

您可以将推送通知与特定 intent 相关联,这样,点按推送通知的用户将直接深层链接到 Action 中的该 intent。在此示例中,为推送通知添加了一个新的 intent,以提供有关已取消的类的详细信息。

请按照以下步骤添加将在用户点击推送通知时触发的 intent:

  1. 在 Dialogflow 控制台中,点击左侧导航栏中意图 (Intents) 旁边的 + 按钮以创建新的意图。
  2. 将此新 intent 命名为 Class Canceled
  3. 训练短语部分下,将 Cancelations 添加为用户表达
  4. Fulfillment 部分下,切换为此 intent 启用 webhook 调用 (Enable webhook call for this intent) 选项。
  5. 点击页面顶部的保存

940379556f559631

在对话过程中发送测试通知

在生产环境中,您应该有一个与用于发送推送通知的 Action 执行方式代码分开的脚本。在此示例中,请创建一个 intent,您可以在与 Action 对话时调用该 intent 来发送推送通知。此 intent 仅用于调试目的;在实践中,推送通知不应由执行方式处理,也不得以其他方式作为 Action 对话的一部分触发。

请按照以下步骤创建用于测试推送通知的 intent:

  1. 出于测试和调试目的,请设置一个允许您向订阅用户发送推送通知的新 intent。在 Dialogflow 控制台中,点击左侧导航栏中意图 (Intents) 旁边的 + 按钮以创建新的意图。
  2. 将此新 intent 命名为 Test Notification
  3. 训练短语部分下,将 Test notification 添加为用户表达
  4. Fulfillment 部分下,切换为此 intent 启用 webhook 调用 (Enable webhook call for this intent) 选项。
  5. 点击页面顶部的保存

6967f5a997643eb8

开启推送通知

请按照以下步骤为 Class Canceled intent 启用推送通知:

  1. 在 Dialogflow 控制台的导航栏中,转到集成 (Integrations)。
  2. Google 助理卡片上,点击集成设置
  3. Class Canceled 添加为隐式调用 intent。为了让 Dialogflow 识别到用户可使用“Class Canceled” intent(通过点按推送通知)开始您的对话,必须执行此步骤。
  4. 点击关闭

1ac725231ed279a1

  1. 在 Actions 控制台中,点击 Develop 标签页,然后在左侧导航栏中选择 Actions
  2. 点击操作列表下的课程已取消
  3. 用户互动部分下方,切换您想发送推送通知?选项。
  4. 设置一个描述推送通知的描述性内容标题。上下文将是“Is it ok if I send push notifications for <content title>?”(我可以针对<内容标题>发送推送通知吗?),因此请确保您的标题采用描述性且在大声读出时没有问题。在此示例中,请将内容标题设置为 class cancelations
  5. 点击页面顶部的保存

4304c7cd575f6de3

实现 fulfillment

如需在 webhook 中实现 fulfillment,请完成以下步骤:

加载依赖项

b2f84ff91b0e1396.pngindex.js 文件中,更新 require() 函数以添加 actions-on-google 软件包中的 UpdatePermission 软件包,这样您的导入代码将如下所示:

index.js

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

更新建议内容信息卡

b2f84ff91b0e1396.pngindex.js 文件中,向建议内容信息卡标题列表添加一个 NOTIFICATIONS 条目,因此您的 Suggestion 定义如下所示:

index.js

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

设置新的导入

如需连接到您的 Firestore 数据库,请添加 firebase-admin 软件包,并为数据库中存储的字段添加常量。此外,导入 google-auth-libraryrequest 软件包,以处理向 Actions API 发出的身份验证和请求。

b2f84ff91b0e1396.pngindex.js 文件中,将以下代码添加到导入中:

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');

询问设置课程取消通知

b2f84ff91b0e1396.pngindex.js 文件中,替换以下代码:

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]));
    };
  };
});

替换为:

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]));
    };
  };
});

为新 intent 添加执行方式

当用户表示想要订阅推送通知时,调用 UpdatePermission 帮助程序向用户请求权限。如果请求成功,系统会将 PERMISSION 实参添加到 conv 对象的实参中,您可以检查这些实参以转换对话。

获得用户的权限后,从 conv 对象的参数中获取用户 ID,并将其保存到您的数据库中。您稍后会将此用户 ID 发送到 Actions API,以便 Google 助理确定通知接收人。

最后,为通过点按推送通知触发的 Class Canceled intent 添加执行方式。在此示例中,您的响应是一个占位字符串,但在此 Action 的正式版中,通知脚本会提供更多动态信息来说明哪个类已被取消。

b2f84ff91b0e1396.pngindex.js 文件中,添加以下代码:

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.');
});

添加测试通知

如需向用户发送推送通知,请向 Actions API 发送 POST 请求,并提供用户 ID、通知标题和目标 intent。在此示例中,触发测试通知 intent 将遍历您的 Firestore 数据库,并向订阅了通知的每个用户发送推送通知。

请记住,在此示例中,您将在 webhook 执行方式中添加用于发送推送通知的代码,并通过在对话中调用测试 intent 来触发该代码。在你打算发布的 Action 中,推送通知代码应存在于独立于执行方式的脚本中。

b2f84ff91b0e1396.pngindex.js 文件中,添加以下代码:

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.');
});

测试推送通知

在终端中,运行以下命令,将更新后的 webhook 代码部署到 Firebase:

firebase deploy

如需在 Actions 模拟器中测试通知,请按以下步骤操作:

  1. 在 Actions 控制台中,前往 Test 标签页。
  2. Input 字段中输入 Talk to my test app,然后按 Enter 键。
  3. 输入 Learn about classes,然后按 Enter 键。
  4. 输入 Get notifications,然后按 Enter 键。
  5. 如果你尚未向 Action 授予向你发送推送通知的权限,请输入 yes,然后按 Enter 键。
  6. 输入 yes,然后按 Enter 键。现在,你的 Google 账号应该已订阅针对此 Action 的推送通知。

3a8704bdc0bcbb17

  1. 输入 no,然后按 Enter 键退出。
  2. 输入 Talk to my test app,然后按 Enter 键即可发起新会话。
  3. 输入 Test notification,然后按 Enter 键。

634dfcb0be8dfdecdec.png

您应该会在几分钟内收到“Test Notification from Action Gym”移动设备上的 Google 助理推送通知。点按此通知会将您深层链接到相应 Action 的 Class Canceled intent。

33cbde513c10122e

5. 创建 Google 助理链接

到目前为止,我们已经讨论了你可以实现哪些互动功能来吸引用户反复使用你的 Action,但这些功能取决于用户发现和使用你的 Action。

您可以创建一个 Google 助理链接,将移动设备用户直接链接到您的 Action on Google 助理。由于 Google 助理链接是标准超链接,因此你可以将其添加到网站或任何网络营销材料(例如博客或社交媒体帖子)。

在此步骤中,您将了解什么是 Google 助理链接、如何为 Action 的欢迎 intent 创建 Google 助理链接,以及如何将其添加到简单的网站进行测试。

这会如何吸引用户?

首次吸引用户访问您的 Action 可能比较困难,尤其是当用户需要明确调用您在 Google 助理上的 Action 时。Google 助理链接可为用户提供指向您的 Action 的直接链接,从而缓解这种不便。当用户在内置 Google 助理的设备上访问你的 Google 助理链接时,会直接跳转到你的 Action。当用户在非移动设备或不支持 Google 助理的任何其他设备上打开您的链接时,系统仍会将其转到您的 Actions 目录详情(如已发布),以便通过该链接向这些用户宣传您的 Action。

Google 助理链接是一种实用的互动工具,因此如果您打算通过网站或社交媒体宣传您的 Action,则应创建一个互动工具。不过,在创建和分发 Google 助理链接之前,请注意以下提示:

  • Google 助理链接只有在你的 Action 发布后才起作用。当项目处于草稿状态时,该链接将只能在您自己的设备上使用。其他所有用户都会转到 Actions 目录中的 404 页面。
  • 通过在 Alpha 版或 Beta 版环境中发布您的 Action,您可以让用户在发布 Google 助理链接之前对其进行测试。请注意,只有参与了 Alpha 版或 Beta 版测试的用户才能测试你的 Google 助理链接。
  • 请确保 Google 助理链接的目标 intent 给新用户留下良好的第一印象。你的欢迎 intent 是 Google 助理链接的默认目标位置,因为它应该已经很好地介绍你的 Action

请按照以下步骤为欢迎 intent 创建 Google 助理链接:

  1. 在 Actions 控制台中,点击 Develop 标签页,然后在左侧导航栏中选择 Actions
  2. 点击操作列表下的 actions.intent.MAIN
  3. 链接部分下,切换 Would you like enabled a 网址 for this Action 选项。
  4. 设置一个描述您的 Action 的描述性链接标题。将标题设置为简单的动词-名词对,描述用户可通过您的 Action 实现的目标。在此示例中,请将链接标题设置为 learn about Action Gym
  5. 复制此页面底部的 HTML 代码段并保存以备后用。
  6. 点击页面顶部的保存

55341b8102b71eab

部署测试网站

如需测试 Google 助理链接,您可以使用 Firebase 工具将测试网站与执行方式一起部署。我们已经为此示例构建了一个简单的测试网站,你只需添加 Google 助理链接即可。

转到执行方式的 /user-engagement-codelab-nodejs/start/public/ 目录,然后在文本编辑器中打开 index.html 文件。

b2f84ff91b0e1396.pngindex.html 文件中,将 Google 助理链接的 HTML 代码段粘贴到正文元素中。文件最终应如以下代码段所示:

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>

在终端运行以下命令,将您的测试网站部署到 Firebase:

firebase deploy

部署命令运行完毕后,请记下输出中的 Hosting 网址(托管网址)。

b01e8d322fb5d623.png

在移动设备的网络浏览器上访问此网址,你应该会在测试网站上看到 Google 助理链接。在移动设备上点击此链接后,系统应该会将您转到 Google 助理中相应 Action 的欢迎 intent。

599845d647f5b624

你也可以尝试在桌面浏览器上前往 Hosting 网址,由于你的 Action 尚未发布,因此系统应该会转到 Google 助理目录中的 404 页面。

6. 后续步骤

恭喜!

现在,您已经了解了在开发 Action 时用户互动的重要性、平台上提供了哪些用户互动功能,以及如何向 Action 添加每项功能。

其他学习资源

请浏览以下资源,详细了解您的 Action 的用户互动度:

欢迎关注我们的 Twitter 账号 @ActionsOnGoogle,及时了解我们的最新公告,还可以使用标签 #AoGDevs 发布 Twitter 微博,分享您构建的成果!

反馈调查问卷

在您离开之前,请填写此表单,告诉我们您对我们是否满意!