Google Chat ユーザーから情報を収集して処理する

このガイドでは、Google Chat アプリがカードベースのインターフェースにフォーム入力を構築して、ユーザーから情報を収集して処理する方法について説明します。

さまざまなウィジェットを備えたダイアログ。
図 1: 連絡先情報を収集するダイアログを開く Chat 用サンプルアプリ

Chat アプリは、Chat 内外で次のようなアクションを実行するために、ユーザーに情報をリクエストします。

  • 設定を行います。たとえば、ユーザーが通知設定をカスタマイズしたり、Chat アプリを構成して 1 つ以上のスペースに追加したりできるようにします。
  • 他の Google Workspace アプリケーションで情報を作成または更新します。たとえば、ユーザーが Google カレンダーの予定を作成できるようにします。
  • ユーザーが他のアプリやウェブサービス内のリソースにアクセスして更新できるようにします。たとえば、Chat アプリを使用すると、ユーザーは Chat スペースから直接サポート チケットのステータスを更新できます。

前提条件

Node.js

インタラクティブ機能が有効になっている Google Chat アプリ。HTTP サービスを使用してインタラクティブな Chat アプリを作成するには、こちらのクイックスタートを完了してください。

Python

インタラクティブ機能が有効になっている Google Chat アプリ。HTTP サービスを使用してインタラクティブな Chat アプリを作成するには、こちらのクイックスタートを完了してください。

Java

インタラクティブ機能が有効になっている Google Chat アプリ。HTTP サービスを使用してインタラクティブな Chat アプリを作成するには、このクイックスタートを完了してください。

Apps Script

インタラクティブ機能が有効になっている Google Chat アプリ。Apps Script でインタラクティブな Chat アプリを作成するには、こちらのクイックスタートを完了してください。

カードを使用してフォームを作成する

情報を収集するために、Chat アプリはフォームとその入力を設計し、カードに組み込みます。Chat アプリは、ユーザーにカードを表示するために次の Chat インターフェースを使用できます。

  • 1 つ以上のカードを含むメッセージ
  • ホームページ。Chat 用アプリとのダイレクト メッセージで [ホーム] タブに表示されるカードです。
  • ダイアログ: メッセージやホームページから新しいウィンドウで開くカードです。

Chat アプリでは、次のウィジェットを使用してカードを作成できます。

  • ユーザーに情報をリクエストするフォーム入力ウィジェット。必要に応じて、フォーム入力ウィジェットに検証を追加して、ユーザーが情報を正しく入力してフォーマットできるようにします。Chat アプリでは、次のフォーム入力ウィジェットを使用できます。

    • 自由形式または候補テキストのテキスト入力textInput)。
    • 選択入力selectionInput)は、チェックボックス、ラジオボタン、プルダウン メニューなど、選択可能な UI 要素です。選択入力ウィジェットでは、静的または動的なデータソースからアイテムを入力することもできます。たとえば、ユーザーは、自分がメンバーである Chat スペースのリストから選択できます。
    • 日時入力用の日時ピッカーdateTimePicker)。
  • ボタン ウィジェット。ユーザーがカードに入力した値を送信できるようにします。ユーザーがボタンをクリックすると、Chat アプリは受信した情報を処理できます。

次の例では、カードがテキスト入力、日時選択ツール、選択入力ウィジェットを使用して連絡先情報を収集します。

Node.js

node/contact-form-app/index.js
/**
 * The section of the contact card that contains the form input widgets. Used in a dialog and card message.
 * To add and preview widgets, use the Card Builder: https://addons.gsuite.google.com/uikit/builder
 */
const CONTACT_FORM_WIDGETS = [
  {
    "textInput": {
      "name": "contactName",
      "label": "First and last name",
      "type": "SINGLE_LINE"
    }
  },
  {
    "dateTimePicker": {
      "name": "contactBirthdate",
      "label": "Birthdate",
      "type": "DATE_ONLY"
    }
  },
  {
    "selectionInput": {
      "name": "contactType",
      "label": "Contact type",
      "type": "RADIO_BUTTON",
      "items": [
        {
          "text": "Work",
          "value": "Work",
          "selected": false
        },
        {
          "text": "Personal",
          "value": "Personal",
          "selected": false
        }
      ]
    }
  }
];

Python

python/contact-form-app/main.py
# The section of the contact card that contains the form input widgets. Used in a dialog and card message.
# To add and preview widgets, use the Card Builder: https://addons.gsuite.google.com/uikit/builder
CONTACT_FORM_WIDGETS = [
  {
    "textInput": {
      "name": "contactName",
      "label": "First and last name",
      "type": "SINGLE_LINE"
    }
  },
  {
    "dateTimePicker": {
      "name": "contactBirthdate",
      "label": "Birthdate",
      "type": "DATE_ONLY"
    }
  },
  {
    "selectionInput": {
      "name": "contactType",
      "label": "Contact type",
      "type": "RADIO_BUTTON",
      "items": [
        {
          "text": "Work",
          "value": "Work",
          "selected": False
        },
        {
          "text": "Personal",
          "value": "Personal",
          "selected": False
        }
      ]
    }
  }
]

Java

java/contact-form-app/src/main/java/com/google/chat/contact/App.java
// The section of the contact card that contains the form input widgets. Used in a dialog and card message.
// To add and preview widgets, use the Card Builder: https://addons.gsuite.google.com/uikit/builder
final static private List<GoogleAppsCardV1Widget> CONTACT_FORM_WIDGETS = List.of(
  new GoogleAppsCardV1Widget().setTextInput(new GoogleAppsCardV1TextInput()
    .setName("contactName")
    .setLabel("First and last name")
    .setType("SINGLE_LINE")),
  new GoogleAppsCardV1Widget().setDateTimePicker(new GoogleAppsCardV1DateTimePicker()
    .setName("contactBirthdate")
    .setLabel("Birthdate")
    .setType("DATE_ONLY")),
  new GoogleAppsCardV1Widget().setSelectionInput(new GoogleAppsCardV1SelectionInput()
    .setName("contactType")
    .setLabel("Contact type")
    .setType("RADIO_BUTTON")
    .setItems(List.of(
      new GoogleAppsCardV1SelectionItem()
        .setText("Work")
        .setValue("Work")
        .setSelected(false),
      new GoogleAppsCardV1SelectionItem()
        .setText("Personal")
        .setValue("Personal")
        .setSelected(false)))));

Apps Script

apps-script/contact-form-app/contactForm.gs
/**
 * The section of the contact card that contains the form input widgets. Used in a dialog and card message.
 * To add and preview widgets, use the Card Builder: https://addons.gsuite.google.com/uikit/builder
 */
const CONTACT_FORM_WIDGETS = [
  {
    "textInput": {
      "name": "contactName",
      "label": "First and last name",
      "type": "SINGLE_LINE"
    }
  },
  {
    "dateTimePicker": {
      "name": "contactBirthdate",
      "label": "Birthdate",
      "type": "DATE_ONLY"
    }
  },
  {
    "selectionInput": {
      "name": "contactType",
      "label": "Contact type",
      "type": "RADIO_BUTTON",
      "items": [
        {
          "text": "Work",
          "value": "Work",
          "selected": false
        },
        {
          "text": "Personal",
          "value": "Personal",
          "selected": false
        }
      ]
    }
  }
];

情報の収集に使用できるインタラクティブ ウィジェットの例については、インタラクティブなカードまたはダイアログを設計するをご覧ください。

インタラクティブなウィジェットからデータを受信する

ユーザーがボタンをクリックするたびに、Chat アプリはインタラクションに関する情報を含む CARD_CLICKED インタラクション イベントを受信します。CARD_CLICKED インタラクション イベントのペイロードには、ユーザーが入力した値を含む common.formInputs オブジェクトが含まれます。

値はオブジェクト common.formInputs.WIDGET_NAME から取得できます。ここで、WIDGET_NAME は、ウィジェットに指定した name フィールドです。値は、ウィジェットの特定のデータ型(Inputs オブジェクトとして表されます)として返されます。

以下は、ユーザーが各ウィジェットの値を入力した CARD_CLICKED インタラクション イベントの一部を示しています。

HTTP

{
  "type": "CARD_CLICKED",
  "common": { "formInputs": {
    "contactName": { "stringInputs": {
      "value": ["Kai 0"]
    }},
    "contactBirthdate": { "dateInput": {
      "msSinceEpoch": 1000425600000
    }},
    "contactType": { "stringInputs": {
      "value": ["Personal"]
    }}
  }}
}

Apps Script

{
  "type": "CARD_CLICKED",
  "common": { "formInputs": {
    "contactName": { "": { "stringInputs": {
      "value": ["Kai 0"]
    }}},
    "contactBirthdate": { "": { "dateInput": {
      "msSinceEpoch": 1000425600000
    }}},
      "contactType": { "": { "stringInputs": {
      "value": ["Personal"]
    }}}
  }}
}

データを受け取るために、Chat アプリはインタラクション イベントを処理して、ユーザーがウィジェットに入力した値を取得します。次の表に、特定のフォーム入力ウィジェットの値を取得する方法を示します。この表には、ウィジェットごとに、ウィジェットが受け入れるデータ型(インタラクション イベントに格納されている値)と値の例が表示されます。

フォーム入力ウィジェット 入力データの種類 インタラクション イベントからの入力値 値の例
textInput stringInputs event.common.formInputs.contactName.stringInputs.value[0] Kai O
selectionInput stringInputs 最初の値または唯一の値を取得するには、event.common.formInputs.contactType.stringInputs.value[0] を使用します。 Personal
日付のみを許可する dateTimePicker dateInput event.common.formInputs.contactBirthdate.dateInput.msSinceEpoch 1000425600000

別のカードにデータを移行する

お客様がカードの情報を送信した後、次のいずれかを行うには、追加のカードを返却していただく必要があります。

  • 長いフォームを入力する際にユーザーが混乱しないように、個別のセクションを作成します。
  • 最初のカードの情報を確認して確認できるようにし、送信する前に回答を確認できるようにします。
  • フォームの残りの部分を動的に入力します。たとえば、ユーザーに予約を作成するよう求める Chat アプリは、予約の理由を尋ねる最初のカードを表示し、予約の種類に基づいて空き時間が表示される別のカードを表示します。

最初のカードからのデータ入力を転送するには、次の例に示すように、ウィジェットの name とユーザーが入力した値を含む actionParameters を使用して button ウィジェットを作成します。

Node.js

node/contact-form-app/index.js
buttonList: { buttons: [{
  text: "Submit",
  onClick: { action: {
    function: "submitForm",
    parameters: [{
      key: "contactName", value: name }, {
      key: "contactBirthdate", value: birthdate }, {
      key: "contactType", value: type
    }]
  }}
}]}

Python

python/contact-form-app/main.py
'buttonList': { 'buttons': [{
  'text': "Submit",
  'onClick': { 'action': {
    'function': "submitForm",
    'parameters': [{
      'key': "contactName", 'value': name }, {
      'key': "contactBirthdate", 'value': birthdate }, {
      'key': "contactType", 'value': type
    }]
  }}
}]}

Java

java/contact-form-app/src/main/java/com/google/chat/contact/App.java
new GoogleAppsCardV1Widget().setButtonList(new GoogleAppsCardV1ButtonList().setButtons(List.of(new GoogleAppsCardV1Button()
  .setText("Submit")
  .setOnClick(new GoogleAppsCardV1OnClick().setAction(new GoogleAppsCardV1Action()
    .setFunction("submitForm")
    .setParameters(List.of(
      new GoogleAppsCardV1ActionParameter().setKey("contactName").setValue(name),
      new GoogleAppsCardV1ActionParameter().setKey("contactBirthdate").setValue(birthdate),
      new GoogleAppsCardV1ActionParameter().setKey("contactType").setValue(type))))))))));

Apps Script

apps-script/contact-form-app/main.gs
buttonList: { buttons: [{
  text: "Submit",
  onClick: { action: {
    function: "submitForm",
    parameters: [{
      key: "contactName", value: name }, {
      key: "contactBirthdate", value: birthdate }, {
      key: "contactType", value: type
    }]
  }}
}]}

ユーザーがボタンをクリックすると、Chat アプリは CARD_CLICKED インタラクション イベントを受信し、そこからデータを受信できます。

フォームの送信に応答する

カード メッセージまたはダイアログからデータを受信すると、Chat アプリは受信確認またはエラーの返信によって応答します。

次の例では、Chat アプリがテキスト メッセージを送信して、ダイアログまたはカード メッセージから送信されたフォームを正常に受信していることを確認します。

Node.js

node/contact-form-app/index.js
const contactName = event.common.parameters["contactName"];
// Checks to make sure the user entered a contact name.
// If no name value detected, returns an error message.
if (!contactName) {
  const errorMessage = "Don't forget to name your new contact!";
  if (event.dialogEventType === "SUBMIT_DIALOG") {
    return { actionResponse: {
      type: "DIALOG",
      dialogAction: { actionStatus: {
        statusCode: "INVALID_ARGUMENT",
        userFacingMessage: errorMessage
      }}
    }};
  } else {
    return {
      privateMessageViewer: event.user,
      text: errorMessage
    };
  }
}

Python

python/contact-form-app/main.py
contact_name = event.get('common').get('parameters')["contactName"]
# Checks to make sure the user entered a contact name.
# If no name value detected, returns an error message.
if contact_name == "":
  error_message = "Don't forget to name your new contact!"
  if "SUBMIT_DIALOG" == event.get('dialogEventType'):
    return { 'actionResponse': {
      'type': "DIALOG",
      'dialogAction': { 'actionStatus': {
        'statusCode': "INVALID_ARGUMENT",
        'userFacingMessage': error_message
      }}
    }}
  else:
    return {
      'privateMessageViewer': event.get('user'),
      'text': error_message
    }

Java

java/contact-form-app/src/main/java/com/google/chat/contact/App.java
String contactName = event.at("/common/parameters/contactName").asText();
// Checks to make sure the user entered a contact name.
// If no name value detected, returns an error message.
if (contactName.isEmpty()) {
  String errorMessage = "Don't forget to name your new contact!";
  if (event.at("/dialogEventType") != null && "SUBMIT_DIALOG".equals(event.at("/dialogEventType").asText())) {
    return new Message().setActionResponse(new ActionResponse()
      .setType("DIALOG")
      .setDialogAction(new DialogAction().setActionStatus(new ActionStatus()
        .setStatusCode("INVALID_ARGUMENT")
        .setUserFacingMessage(errorMessage))));
  } else {
    return new Message()
      .setPrivateMessageViewer(new User().setName(event.at("/user/name").asText()))
      .setText(errorMessage);
  }
}

Apps Script

apps-script/contact-form-app/main.gs
const contactName = event.common.parameters["contactName"];
// Checks to make sure the user entered a contact name.
// If no name value detected, returns an error message.
if (!contactName) {
  const errorMessage = "Don't forget to name your new contact!";
  if (event.dialogEventType === "SUBMIT_DIALOG") {
    return { actionResponse: {
      type: "DIALOG",
      dialogAction: { actionStatus: {
        statusCode: "INVALID_ARGUMENT",
        userFacingMessage: errorMessage
      }}
    }};
  } else {
    return {
      privateMessageViewer: event.user,
      text: errorMessage
    };
  }
}

ダイアログを処理して閉じるには、確認メッセージを送信するか、元のメッセージまたはカードを更新するか、ダイアログを閉じるかを指定する ActionResponse オブジェクトを返します。手順については、ダイアログを閉じるをご覧ください。

トラブルシューティング

Google Chat アプリまたはカードからエラーが返されると、Chat インターフェースに「エラーが発生しました」というメッセージが表示されます。または「リクエストを処理できません」というメッセージが表示されます。Chat UI にエラー メッセージが表示されない場合でも、Chat アプリまたはカードで予期しない結果が生成されることがあります(カード メッセージが表示されないなど)。

チャット UI にエラー メッセージが表示されない場合でも、チャットアプリのエラー ロギングがオンになっている場合は、エラーの修正に役立つ説明的なエラー メッセージとログデータが利用できます。エラーの表示、デバッグ、修正については、Google Chat エラーのトラブルシューティングと修正をご覧ください。