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


Chat 用アプリは、Chat 内外でアクションを実行するために、次のような方法でユーザーに情報をリクエストします。
- 設定を行います。たとえば、ユーザーが通知設定をカスタマイズしたり、Chat 用アプリを 1 つ以上のスペースに構成して追加したりできるようにします。
- 他の Google Workspace アプリケーションで情報を作成または更新します。たとえば、ユーザーが Google カレンダーの予定を作成できるようにします。
- 他のアプリやウェブ サービスのリソースにアクセスして更新できるようにします。たとえば、Chat アプリを使用すると、Chat スペースから直接サポート チケットのステータスを更新できます。
前提条件
HTTP
Google Chat を拡張する Google Workspace アドオン。作成するには、HTTP クイックスタートを完了します。
Apps Script
Google Chat を拡張する Google Workspace アドオン。作成するには、Apps Script のクイックスタートを完了します。
カードを使用してフォームを作成する
情報を収集するために、Chat 用アプリはフォームとその入力を設計し、カードに組み込みます。ユーザーにカードを表示するために、Chat 用アプリは次の Chat インターフェースを使用できます。
- 1 つ以上のカードを含む Chat メッセージ。
- ダイアログ: メッセージやホームページから新しいウィンドウで開くカード。
Chat 用アプリは、次のウィジェットを使用してカードを構築できます。
ユーザーに情報をリクエストするフォーム入力ウィジェット。必要に応じて、フォーム入力ウィジェットに検証を追加して、ユーザーが情報を正しく入力してフォーマットできるようにすることができます。Chat 用アプリでは、次のフォーム入力ウィジェットを使用できます。
- 自由形式または候補のテキスト用のテキスト入力(
textInput
)。 選択入力(
selectionInput
)は、チェックボックス、ラジオボタン、プルダウン メニューなどの選択可能な UI 要素です。選択入力ウィジェットは、Google Workspace データ(Chat スペースなど)または動的データソースから項目を入力して候補を表示することもできます。詳しくは、次のセクション 複数選択メニューを追加するをご覧ください。日付と時刻のエントリ用の日時ピッカー(
dateTimePicker
)。
- 自由形式または候補のテキスト用のテキスト入力(
ユーザーがカードに入力した値を送信できるようにする button ウィジェット。ユーザーがボタンをクリックすると、Chat 用アプリは受信した情報を処理できます。
次の例では、カードがテキスト入力、日時選択ツール、選択入力を使用して連絡先情報を収集しています。
情報を収集するために使用できるインタラクティブ ウィジェットの例については、Google Chat API ドキュメントのインタラクティブなカードやダイアログの設計をご覧ください。
複数選択メニューを追加する
選択項目をカスタマイズしたり、ユーザーが動的データソースから項目を選択できるようにするには、Chat 用アプリで複数選択メニューを使用できます。これは SelectionInput
ウィジェットの一種です。たとえば、次のカードには、ユーザーが連絡先リストから動的に選択できる複数選択メニューが表示されます。
マルチセレクト メニューの項目は、次のデータソースから設定できます。
- Google Workspace データ。ユーザーまたはユーザーがメンバーになっている Chat スペースが含まれます。メニューには、同じ Google Workspace 組織のアイテムのみが表示されます。
- リレーショナル データベースなどの外部データソース。たとえば、顧客管理(CRM)システムの販売見込み顧客のリストからユーザーが選択できるように、複数選択メニューを使用できます。
Google Workspace データソースからアイテムを入力する
Google Workspace データソースを使用するには、SelectionInput
ウィジェットで platformDataSource
フィールドを指定します。他の選択入力タイプとは異なり、これらの選択項目は Google Workspace から動的に取得されるため、SelectionItem
オブジェクトは省略します。
次のコードは、Google Workspace ユーザーの複数選択メニューを示しています。ユーザーを入力するには、選択入力で commonDataSource
を USER
に設定します。
JSON
{
"selectionInput": {
"name": "contacts",
"type": "MULTI_SELECT",
"label": "Selected contacts",
"multiSelectMaxSelectedItems": 5,
"multiSelectMinQueryLength": 1,
"platformDataSource": {
"commonDataSource": "USER"
}
}
}
次のコードは、Chat スペースの複数選択メニューを示しています。スペースを入力するには、選択入力で hostAppDataSource
フィールドを指定します。マルチ選択メニューでは、defaultToCurrentSpace
も true
に設定されます。これにより、現在のスペースがメニューのデフォルトの選択になります。
JSON
{
"selectionInput": {
"name": "spaces",
"type": "MULTI_SELECT",
"label": "Selected contacts",
"multiSelectMaxSelectedItems": 3,
"multiSelectMinQueryLength": 1,
"platformDataSource": {
"hostAppDataSource": {
"chatDataSource": {
"spaceDataSource": {
"defaultToCurrentSpace": true
}
}
}
}
}
}
外部データソースからアイテムを入力する
マルチセレクト メニューには、サードパーティまたは外部のデータソースから項目を入力することもできます。外部データソースを使用するには、データソースからアイテムをクエリして返す関数を含む SelectionInput
ウィジェットで externalDataSource
フィールドを指定します。
外部データソースへのリクエストを減らすには、ユーザーがメニューに入力する前に、マルチセレクト メニューに表示される候補アイテムを含めることができます。たとえば、ユーザーが最近検索した連絡先を自動入力できます。外部データソースから候補アイテムを入力するには、静的 SelectionItem
オブジェクトを指定します。
次のコードは、外部データソースからアイテムをクエリして入力する複数選択メニューを示しています。
JSON
{
"selectionInput": {
"name": "contacts",
"type": "MULTI_SELECT",
"label": "Selected contacts",
"multiSelectMaxSelectedItems": 3,
"multiSelectMinQueryLength": 1,
"externalDataSource": { "function": "FUNCTION" },
// Suggested items loaded by default.
// The list is static here but it could be dynamic.
"items": [FUNCTION]
}
}
FUNCTION
は、外部データベースをクエリする HTTP URL または Apps Script 関数名に置き換えます。候補アイテムを返す方法を示す完全な例については、複数選択アイテムを提案するのセクションをご覧ください。
インタラクティブ ウィジェットからデータを受け取る
ユーザーがボタンをクリックするたびに、その Chat 用アプリのアクションがトリガーされ、操作に関する情報が渡されます。イベント ペイロードの commonEventObject
で、formInputs
オブジェクトにはユーザーが入力した値が含まれます。
オブジェクト commonEventObject.formInputs.WIDGET_NAME
から値を取得できます。ここで、WIDGET_NAME はウィジェットに指定した name
フィールドです。値は、ウィジェットの特定のデータ型として返されます。
次の例は、ユーザーが各ウィジェットの値を入力したイベント オブジェクトの一部を示しています。
{
"commonEventObject": { "formInputs": {
"contactName": { "stringInputs": {
"value": ["Kai 0"]
}},
"contactBirthdate": { "dateInput": {
"msSinceEpoch": 1000425600000
}},
"contactType": { "stringInputs": {
"value": ["Personal"]
}}
}}
}
データを受け取るには、Chat 用アプリがイベント オブジェクトを処理して、ユーザーがウィジェットに入力した値を取得します。次の表は、特定のフォーム入力ウィジェットの値を取得する方法を示しています。各ウィジェットについて、ウィジェットが受け入れるデータ型、イベント オブジェクトに値が格納される場所、値の例が表に示されています。
フォーム入力ウィジェット | 入力データのタイプ | イベント オブジェクトからの入力値 | 値の例 |
---|---|---|---|
textInput |
stringInputs |
event.commonEventObject.formInputs.contactName.stringInputs.value[0] |
Kai O |
selectionInput |
stringInputs |
最初または唯一の値を取得するには、event.commonEventObject.formInputs.contactType.stringInputs.value[0] |
Personal |
日付のみを受け付ける dateTimePicker 。 |
dateInput |
event.commonEventObject.formInputs.contactBirthdate.dateInput.msSinceEpoch 。 |
1000425600000 |
Chat 用アプリがデータを受信すると、次の操作を行うことができます。
- 複数選択メニューを含むカードでは、ユーザーがメニューに入力した内容に基づいて項目を入力または候補表示します。
- データを別のカードに転送して、ユーザーが情報を確認したり、フォームの次のセクションに進んだりできるようにします。
- ユーザーに返信し、フォームが正常に送信されたことを確認します。
複数選択アイテムを提案する
カードに外部データソースから項目を入力する複数選択メニューが含まれている場合、Chat 用アプリはユーザーがメニューに入力した内容に基づいて候補項目を返すことができます。たとえば、ユーザーが米国の都市を入力するメニューで Atl
の入力を開始した場合、ユーザーが入力を完了する前に、Chat 用アプリで Atlanta
を自動提案できます。Chat 用アプリは最大 100 個の項目を提案できます。
マルチセレクト メニューで項目を提案して動的に入力するには、カードの SelectionInput
ウィジェットで、外部データソースをクエリする関数を指定する必要があります。候補アイテムを返すには、関数で次の処理を行う必要があります。
- ユーザーがメニューに入力したときに Chat 用アプリが受け取るイベント オブジェクトを処理します。
- イベント オブジェクトから、ユーザーが入力した値を取得します。この値は
event.commonEventObject.parameters["autocomplete_widget_query"]
フィールドで表されます。 - ユーザー入力値を使用してデータソースにクエリを実行し、ユーザーに提案する 1 つ以上の
SelectionItems
を取得します。 modifyCard
オブジェクトを含むアクションRenderActions
を返すことで、提案アイテムを返します。
次のコードサンプルは、Chat 用アプリがカードのマルチセレクト メニューで項目を動的に提案する方法を示しています。ユーザーがメニューに入力すると、ウィジェットの externalDataSource
フィールドで指定された関数またはエンドポイントが外部データソースにクエリを実行し、ユーザーが選択できる項目を提案します。
Node.js
/**
* Google Cloud Function that responds to events sent from a
* Google Chat space.
*
* @param {Object} req Request sent from Google Chat space
* @param {Object} res Response to send back
*/
exports.selectionInput = function selectionInput(req, res) {
if (req.method === 'GET' || !req.body.chat) {
return res.send('Hello! This function is meant to be used ' +
'in a Google Chat Space.');
}
// Stores the Google Chat event
const chatEvent = req.body.chat;
// Handle user interaction with multiselect.
if(chatEvent.widgetUpdatedPayload) {
return res.send(queryContacts(req.body));
}
// Replies with a card that contains the multiselect menu.
return res.send({ hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
cardsV2: [{
cardId: "contactSelector",
card: { sections:[{ widgets: [{
selectionInput: {
name: "contacts",
type: "MULTI_SELECT",
label: "Selected contacts",
multiSelectMaxSelectedItems: 3,
multiSelectMinQueryLength: 1,
externalDataSource: { function: "FUNCTION_URL" },
// Suggested items loaded by default.
// The list is static here but it could be dynamic.
items: [getSuggestedContact("3")]
}
}]}]}
}]
}}}}});
};
/**
* Get contact suggestions based on text typed by users.
*
* @param {Object} event the event object that contains the user's query
* @return {Object} suggestions
*/
function queryContacts(event) {
const query = event.commonEventObject.parameters["autocomplete_widget_query"];
return { action: { modifyOperations: [{ updateWidget: { selectionInputWidgetSuggestions: { suggestions: [
// The list is static here but it could be dynamic.
getSuggestedContact("1"), getSuggestedContact("2"), getSuggestedContact("3"), getSuggestedContact("4"), getSuggestedContact("5")
// Only return items based on the query from the user.
].filter(e => !query || e.text.includes(query)) }}}]}};
}
/**
* Generate a suggested contact given an ID.
*
* @param {String} id The ID of the contact to return.
* @return {Object} The contact formatted as a selection item in the menu.
*/
function getSuggestedContact(id) {
return {
value: id,
startIconUri: "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
text: "Contact " + id
};
}
FUNCTION_URL
は、外部データソースをクエリする HTTP エンドポイントに置き換えます。
Apps Script
/**
* Responds to a Message trigger in Google Chat.
*
* @param {Object} event the event object from Google Chat
* @return {Object} Response from the Chat app.
*/
function onMessage(event) {
// Replies with a card that contains the multiselect menu.
return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
cardsV2: [{
cardId: "contactSelector",
card: { sections:[{ widgets: [{
selectionInput: {
name: "contacts",
type: "MULTI_SELECT",
label: "Selected contacts",
multiSelectMaxSelectedItems: 3,
multiSelectMinQueryLength: 1,
externalDataSource: { function: "queryContacts" },
// Suggested items loaded by default.
// The list is static here but it could be dynamic.
items: [getSuggestedContact("3")]
}
}]}]}
}]
}}}}};
}
/**
* Get contact suggestions based on text typed by users.
*
* @param {Object} event the event object that contains the user's query
* @return {Object} suggestions
*/
function queryContacts(event) {
const query = event.commonEventObject.parameters["autocomplete_widget_query"];
return { action: { modifyOperations: [{ updateWidget: { selectionInputWidgetSuggestions: { suggestions: [
// The list is static here but it could be dynamic.
getSuggestedContact("1"), getSuggestedContact("2"), getSuggestedContact("3"), getSuggestedContact("4"), getSuggestedContact("5")
// Only return items based on the query from the user.
].filter(e => !query || e.text.includes(query)) }}}]}};
}
/**
* Generate a suggested contact given an ID.
*
* @param {String} id The ID of the contact to return.
* @return {Object} The contact formatted as a selection item in the menu.
*/
function getSuggestedContact(id) {
return {
value: id,
startIconUri: "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
text: "Contact " + id
};
}
別のカードにデータを転送する
ユーザーがカードから情報を送信した後、次のいずれかを行うために追加のカードを返す必要がある場合があります。
- 長いフォームを複数のセクションに分割して、ユーザーが入力しやすくします。
- ユーザーが最初のカードの情報をプレビューして確認できるようにします。これにより、ユーザーは回答を送信する前に確認できます。
- フォームの残りの部分を動的に入力します。たとえば、ユーザーに予定の作成を促すために、Chat 用アプリは、予定の理由を尋ねる最初のカードを表示し、予定の種類に基づいて利用可能な時間を表示する別のカードに入力します。
最初のカードから入力されたデータを転送するには、次の例に示すように、ウィジェットの name
とユーザーが入力した値を含む actionParameters
を使用して button
ウィジェットをビルドします。
Node.js
{
"buttonList": { "buttons": [{
"text": "Submit",
"onClick": { "action": {
"function": "FUNCTION_URL", // Must be an `https` endpoint.
"parameters": [
{
"key": "WIDGET_NAME",
"value": "USER_INPUT_VALUE"
},
// Can specify multiple parameters
]
}}
}]}
}
Apps Script
{
"buttonList": { "buttons": [{
"text": "Submit",
"onClick": { "action": {
"function": "submitForm",
"parameters": [
{
"key": "WIDGET_NAME",
"value": "USER_INPUT_VALUE"
},
// Can specify multiple parameters
]
}}
}]}
}
ここで、WIDGET_NAME はウィジェットの name
で、USER_INPUT_VALUE はユーザーが入力したものです。たとえば、個人の名前を収集するテキスト入力の場合、ウィジェット名は contactName
で、値の例は Kai O
です。
ユーザーがボタンをクリックすると、Chat 用アプリはイベント オブジェクトを受け取ります。このオブジェクトからデータを受け取ることができます。
フォームの送信に対応する
カード メッセージまたはダイアログからデータを受信すると、Chat 用アプリは受信を確認するか、エラーを返して応答します。
次の例では、Chat 用アプリがテキスト メッセージを送信して、カード メッセージから送信されたフォームを正常に受信したことを確認しています。
Node.js
/**
* Google Cloud Function that handles all Google Workspace Add On events for
* the contact manager app.
*
* @param {Object} req Request sent from Google Chat space
* @param {Object} res Response to send back
*/
exports.contactManager = function contactManager(req, res) {
const chatEvent = req.body.chat;
const chatMessage = chatEvent.messagePayload.message;
// Handle message payloads in the event object
if(chatEvent.messagePayload) {
return res.send(handleMessage(chatMessage, chatEvent.user));
// Handle button clicks on the card
} else if(chatEvent.buttonClickedPayload) {
switch(req.body.commonEventObject.parameters.actionName) {
case "openDialog":
return res.send(openDialog());
case "openNextCard":
return res.send(openNextCard(req.body));
case "submitForm":
return res.send(submitForm(req.body));
}
}
};
/**
* Submits information from a dialog or card message.
*
* @param {Object} event the interactive event with form inputs.
* @return {Object} a message response that posts a private message.
*/
function submitForm(event) {
const chatUser = event.chat.user;
const contactName = event.commonEventObject.parameters["contactName"];
return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
privateMessageViewer: chatUser,
text: "✅ " + contactName + " has been added to your contacts."
}}}}};
}
Apps Script
/**
* Sends private text message that confirms submission.
*
* @param {Object} event the interactive event with form inputs.
* @return {Object} a message response that posts a private message.
*/
function submitForm(event) {
const chatUser = event.chat.user;
const contactName = event.commonEventObject.parameters["contactName"];
return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
privateMessageViewer: chatUser,
text: "✅ " + contactName + " has been added to your contacts."
}}}}};
}
ダイアログを処理して閉じるには、確認メッセージを送信するか、元のメッセージまたはカードを更新するか、ダイアログを閉じるだけかを指定する RenderActions
オブジェクトを返します。手順については、ダイアログを閉じるをご覧ください。
トラブルシューティング
Google Chat 用アプリまたはカードがエラーを返すと、Chat インターフェースに「エラーが発生しました」というメッセージが表示されます。または「リクエストを処理できません。」と表示されることがあります。Chat UI にエラー メッセージが表示されない場合でも、Chat 用アプリやカードで予期しない結果が生じることがあります。たとえば、カード メッセージが表示されないことがあります。
Chat UI にエラー メッセージが表示されない場合でも、Chat 用アプリのエラー ロギングが有効になっている場合は、エラーの修正に役立つ説明的なエラー メッセージとログデータを利用できます。エラーの表示、デバッグ、修正については、Google Chat のエラーのトラブルシューティングと修正をご覧ください。