ユーザーが Google Chat でリンクを共有したときにコンテキストが切り替わるのを防ぐために、Chat 用アプリでリンクをプレビューできます。カードをメッセージに添付して、ユーザーが Google Chat から直接操作を行えるようにします。
たとえば、企業のカスタマー サービス エージェントすべてと、Case-y という名前の Chat アプリを含む Google Chat スペースがあるとします。エージェントは、カスタマー サービスのケースへのリンクを Chat スペースで頻繁に共有します。担当者が共有する際は毎回、ケースのリンクを開いて割り当て先、ステータス、件名などの詳細を確認する必要があります。同様に、誰かがケースのオーナー権限を取得したり、ステータスを変更したりする場合は、リンクを開く必要があります。
リンクのプレビューを使用すると、スペースに常駐する Chat アプリである Case-y が、ケースリンクを共有するたびに割り当て先、ステータス、件名を示すカードを添付できます。エージェントはカードのボタンを使用して、ケースの所有権を取得し、チャット ストリームから直接ステータスを変更できます。
リンク プレビューの仕組み
他のユーザーがメッセージにリンクを追加すると、Chat 用アプリでリンクがプレビューされる可能性があることを示すチップが表示されます。
メッセージを送信すると、リンクが Chat アプリに送信されます。Chat アプリ側でカードが生成され、ユーザーのメッセージに添付されます。
リンクの横には、ボタンなどのインタラクティブな要素を含め、リンクに関する追加情報が表示されます。Chat アプリでは、ボタンのクリックなどのユーザー操作に応じて、添付されたカードを更新できます。
メッセージにカードを追加して Chat 用アプリでリンクをプレビューしたくない場合は、プレビュー チップの cancel をクリックしてプレビューできないようにすることができます。添付されたカードは、[プレビューを削除] をクリックしていつでも削除できます。
前提条件
Node.js
インタラクティブ機能を有効にする Google Chat アプリ。新しい
HTTP サービスを使用したインタラクティブな Chat アプリについては、こちらのクイックスタートを完了します。
Apps Script
インタラクティブ機能を有効にする Google Chat アプリ。新しい
対話型の Chat アプリを使用するには、このクイックスタートを完了します。
Google Cloud コンソールの Chat アプリの構成ページで、特定のリンク(example.com
、support.example.com
、support.example.com/cases/
など)を URL パターンとして登録し、Chat アプリでプレビューできるようにします。
- Google Cloud コンソールを開きます。
- [Google Cloud]の横で下矢印 arrow_drop_down をクリックし、Chat アプリのプロジェクトを開きます。
- 検索フィールドに「
Google Chat API
」と入力し、[Google Chat API] をクリックします。
- [管理] > [構成] をクリックします。
- [リンク プレビュー] で URL パターンを追加または編集します。
- 新しい URL パターンのリンク プレビューを設定するには、[URL パターンを追加] をクリックします。
- 既存の URL パターンの構成を編集するには、下矢印 expand_more をクリックします。
[ホストパターン] に、URL パターンのドメインを入力します。Chat アプリでこのドメインへのリンクがプレビューされます。
特定のサブドメイン(subdomain.example.com
など)の Chat 用アプリのプレビュー リンクを表示するには、そのサブドメインを含めます。
ドメイン全体で Chat 用アプリのプレビュー リンクを表示するには、サブドメインとしてアスタリスク(*)付きのワイルドカード文字を指定します。たとえば、*.example.com
は subdomain.example.com
および any.number.of.subdomains.example.com
と一致します。
[パスの接頭辞] に、ホストパターン ドメインに追加するパスを入力します。
ホストパターン ドメイン内のすべての URL を一致させるには、[パスの接頭辞] を空白のままにします。
たとえば、ホストパターンが support.example.com
の場合、support.example.com/cases/
でホストされているケースの URL を照合するには「cases/
」と入力します。
[完了] をクリックします。
[保存] をクリックします。
これで、Chat 用アプリを含む Chat スペース内のメッセージにリンク プレビュー URL のパターンに一致するリンクが投稿されるたびに、そのリンクがアプリでプレビューされるようになりました。
リンクをプレビューする
リンクのプレビューを設定すると
リンクを認識してプレビューするには、
情報を追加します。
自分の名前リンクが含まれる Chat スペースには、
Chat 用アプリで、誰かのメッセージに
リンク プレビュー URL パターンと一致した場合、
が
MESSAGE
インタラクション イベント。JSON
インタラクション イベントのペイロードには、matchedUrl
フィールドが含まれています。
JSON
"message": {
. . . // other message attributes redacted
"matchedUrl": {
"url": "https://support.example.com/cases/case123"
},
. . . // other message attributes redacted
}
MESSAGE
イベントに matchedUrl
フィールドが存在するかどうかを確認する
Chat アプリはスペースに
リンクのプレビューが表示されます。Chat 用アプリは
簡単なテキスト メッセージで返信するか、カードを添付します。
テキスト メッセージで返信する
Chat 用アプリでリンクをプレビューすれば、簡単に回答できます。
シンプルなテキスト メッセージで返信する
追加できますこの例では、メッセージに URL が記載されているリンク URL が
リンク プレビュー URL パターンに一致します。
カードを添付
プレビューしたリンクにカードを添付するには:
返す
ActionResponse
UPDATE_USER_MESSAGE_CARDS
型の。この例では、単純なカードがアタッチされます。
Node.js
/**
* Responds to messages that have links whose URLs match URL patterns
* configured for link previewing.
*
* @param {Object} req Request sent from Google Chat.
* @param {Object} res Response to send back.
*/
exports.onMessage = (req, res) => {
if (req.method === 'GET' || !req.body.message) {
return res.send(
'Hello! This function is meant to be used in a Google Chat Space.');
}
// Checks for the presence of event.message.matchedUrl and attaches a card
// if present
if (req.body.message.matchedUrl) {
return res.json({
'actionResponse': {'type': 'UPDATE_USER_MESSAGE_CARDS'},
'cardsV2': [
{
'cardId': 'attachCard',
'card': {
'header': {
'title': 'Example Customer Service Case',
'subtitle': 'Case basics',
},
'sections': [
{
'widgets': [
{'keyValue': {'topLabel': 'Case ID', 'content': 'case123'}},
{'keyValue': {'topLabel': 'Assignee', 'content': 'Charlie'}},
{'keyValue': {'topLabel': 'Status', 'content': 'Open'}},
{
'keyValue': {
'topLabel': 'Subject', 'content': 'It won"t turn on...',
}
},
],
},
{
'widgets': [
{
'buttons': [
{
'textButton': {
'text': 'OPEN CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123',
},
},
},
},
{
'textButton': {
'text': 'RESOLVE CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123?resolved=y',
},
},
},
},
{
'textButton': {
'text': 'ASSIGN TO ME',
'onClick': {
'action': {
'actionMethodName': 'assign',
},
},
},
},
],
},
],
},
],
},
},
],
});
}
// If the Chat app doesn’t detect a link preview URL pattern, it says so.
return res.json({'text': 'No matchedUrl detected.'});
};
Apps Script
この例では、メッセージにカード メッセージを送信する際に、
カード JSON。
また、
Apps Script カードサービス。
/**
* Responds to messages that have links whose URLs match URL patterns
* configured for link previewing.
*
* @param {Object} event The event object from Chat API.
* @return {Object} Response from the Chat app attached to the message with
* the previewed link.
*/
function onMessage(event) {
// Checks for the presence of event.message.matchedUrl and attaches a card
// if present
if (event.message.matchedUrl) {
return {
'actionResponse': {
'type': 'UPDATE_USER_MESSAGE_CARDS',
},
'cardsV2': [{
'cardId': 'attachCard',
'card': {
'header': {
'title': 'Example Customer Service Case',
'subtitle': 'Case basics',
},
'sections': [{
'widgets': [
{'keyValue': {'topLabel': 'Case ID', 'content': 'case123'}},
{'keyValue': {'topLabel': 'Assignee', 'content': 'Charlie'}},
{'keyValue': {'topLabel': 'Status', 'content': 'Open'}},
{
'keyValue': {
'topLabel': 'Subject', 'content': 'It won\'t turn on...',
},
},
],
},
{
'widgets': [{
'buttons': [
{
'textButton': {
'text': 'OPEN CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123',
},
},
},
},
{
'textButton': {
'text': 'RESOLVE CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123?resolved=y',
},
},
},
},
{
'textButton': {
'text': 'ASSIGN TO ME',
'onClick': {'action': {'actionMethodName': 'assign'}},
},
},
],
}],
}],
},
}],
};
}
// If the Chat app doesn’t detect a link preview URL pattern, it says so.
return {'text': 'No matchedUrl detected.'};
}
カードを更新する
プレビューされたリンクに添付されたカードを更新するには、
ActionResponse
UPDATE_USER_MESSAGE_CARDS
型。Chat アプリは、
ユーザーの返信としてリンクをプレビューする
Chat 用アプリのインタラクション イベント。
Chat アプリでは Chat API を呼び出してこれらのカードを更新できない
使用できます。
リンク プレビューでは、UPDATE_MESSAGE
型の ActionResponse
を返すことはできません。UPDATE_MESSAGE
はカードだけでなくメッセージ全体を更新するため、Chat 用アプリが元のメッセージを作成した場合にのみ機能します。リンク プレビューでは、ユーザーが作成したメッセージにカードが添付されるため、Chat 用アプリにはカードを更新する権限がありません。
Chat ストリームでユーザーが作成したカードとアプリが作成したカードの両方が関数によって更新されるようにするには、メッセージを作成したのが Chat アプリかユーザーかに基づいて ActionResponse
を動的に設定します。
これを行うには、添付されたカードの onclick
プロパティ(メッセージがユーザー作成であることを示すもの)の一部としてカスタム actionMethodName
を指定して確認する方法と、メッセージがユーザーによって作成されたかどうかを確認する方法の 2 つがあります。
プレビューされたカードの CARD_CLICKED
インタラクション イベントを適切に処理するために actionMethodName
を使用するには、添付されたカードの onclick
プロパティの一部としてカスタム actionMethodName
を設定します。
JSON
. . . // Preview card details
{
"textButton": {
"text": "ASSIGN TO ME",
"onClick": {
// actionMethodName identifies the button to help determine the
// appropriate ActionResponse.
"action": {
"actionMethodName": "assign",
}
}
}
}
. . . // Preview card details
"actionMethodName": "assign"
によってボタンがリンク プレビューの一部として識別されるため、一致する actionMethodName
を確認することで、正しい ActionResponse
を動的に返すことができます。
方法 2: 送信者の種類を確認する
message.sender.type
が HUMAN
か BOT
かを確認します。HUMAN
の場合は、ActionResponse
を UPDATE_USER_MESSAGE_CARDS
に設定し、それ以外の場合は ActionResponse
を UPDATE_MESSAGE
に設定します。手順は次のとおりです。
カードが更新されるのは、通常、ボタンがクリックされたためです。前のセクション「カードを添付」で [自分に割り当て] ボタンを思い出してください。次の完全な例では、カードが更新され、「You」に割り当てられていることが示されます。ユーザーが [自分に割り当て] をクリックした後に表示されます。この例では、送信者の種類を確認して、ActionResponse
を動的に設定します。
完全な例: Case-y(カスタマー サービスの Chat 用アプリ)
カスタマー サービス エージェントが共同作業する Chat スペースで共有されたケースへのリンクをプレビューする Chat アプリ、Case-y の完全なコードを次に示します。
Node.js
/**
* Responds to messages that have links whose URLs match URL patterns
* configured for link previewing.
*
* @param {Object} req Request sent from Google Chat.
* @param {Object} res Response to send back.
*/
exports.onMessage = (req, res) => {
if (req.method === 'GET' || !req.body.message) {
return res.send(
'Hello! This function is meant to be used in a Google Chat Space.');
}
// Respond to button clicks on attached cards
if (req.body.type === 'CARD_CLICKED') {
// Checks whether the message event originated from a human or a Chat app
// and sets actionResponse.type to "UPDATE_USER_MESSAGE_CARDS if human or
// "UPDATE_MESSAGE" if Chat app.
const actionResponseType = req.body.action.actionMethodName === 'HUMAN' ?
'UPDATE_USER_MESSAGE_CARDS' :
'UPDATE_MESSAGE';
if (req.body.action.actionMethodName === 'assign') {
return res.json(createMessage(actionResponseType, 'You'));
}
}
// Checks for the presence of event.message.matchedUrl and attaches a card
// if present
if (req.body.message.matchedUrl) {
return res.json(createMessage());
}
// If the Chat app doesn’t detect a link preview URL pattern, it says so.
return res.json({'text': 'No matchedUrl detected.'});
};
/**
* Message to create a card with the correct response type and assignee.
*
* @param {string} actionResponseType
* @param {string} assignee
* @return {Object} a card with URL preview
*/
function createMessage(
actionResponseType = 'UPDATE_USER_MESSAGE_CARDS',
assignee = 'Charlie'
) {
return {
'actionResponse': {'type': actionResponseType},
'cardsV2': [
{
'cardId': 'previewLink',
'card': {
'header': {
'title': 'Example Customer Service Case',
'subtitle': 'Case basics',
},
'sections': [
{
'widgets': [
{'keyValue': {'topLabel': 'Case ID', 'content': 'case123'}},
{'keyValue': {'topLabel': 'Assignee', 'content': assignee}},
{'keyValue': {'topLabel': 'Status', 'content': 'Open'}},
{
'keyValue': {
'topLabel': 'Subject', 'content': 'It won"t turn on...',
},
},
],
},
{
'widgets': [
{
'buttons': [
{
'textButton': {
'text': 'OPEN CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123',
},
},
},
},
{
'textButton': {
'text': 'RESOLVE CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123?resolved=y',
},
},
},
},
{
'textButton': {
'text': 'ASSIGN TO ME',
'onClick': {
'action': {
'actionMethodName': 'assign',
},
},
},
},
],
},
],
},
],
}
},
],
};
}
Apps Script
この例では、メッセージにカード メッセージを送信する際に、
カード JSON。
また、
Apps Script カードサービス。
/**
* Responds to messages that have links whose URLs match URL patterns
* configured for link previews.
*
* @param {Object} event The event object from Chat API.
* @return {Object} Response from the Chat app attached to the message with
* the previewed link.
*/
function onMessage(event) {
// Checks for the presence of event.message.matchedUrl and attaches a card
// if present
if (event.message.matchedUrl) {
return {
'actionResponse': {
'type': 'UPDATE_USER_MESSAGE_CARDS',
},
'cardsV2': [{
'cardId': 'previewLink',
'card': {
'header': {
'title': 'Example Customer Service Case',
'subtitle': 'Case basics',
},
'sections': [{
'widgets': [
{'keyValue': {'topLabel': 'Case ID', 'content': 'case123'}},
{'keyValue': {'topLabel': 'Assignee', 'content': 'Charlie'}},
{'keyValue': {'topLabel': 'Status', 'content': 'Open'}},
{
'keyValue': {
'topLabel': 'Subject', 'content': 'It won\'t turn on...',
}
},
],
},
{
'widgets': [{
'buttons': [
{
'textButton': {
'text': 'OPEN CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123',
},
},
},
},
{
'textButton': {
'text': 'RESOLVE CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123?resolved=y',
},
},
},
},
{
'textButton': {
'text': 'ASSIGN TO ME',
'onClick': {'action': {'actionMethodName': 'assign'}}
},
},
],
}],
}],
},
}],
};
}
// If the Chat app doesn’t detect a link preview URL pattern, it says so.
return {'text': 'No matchedUrl detected.'};
}
/**
* Updates a card that was attached to a message with a previewed link.
*
* @param {Object} event The event object from Chat API.
* @return {Object} Response from the Chat app. Either a new card attached to
* the message with the previewed link, or an update to an existing card.
*/
function onCardClick(event) {
// Checks whether the message event originated from a human or a Chat app
// and sets actionResponse to "UPDATE_USER_MESSAGE_CARDS if human or
// "UPDATE_MESSAGE" if Chat app.
const actionResponseType = event.message.sender.type === 'HUMAN' ?
'UPDATE_USER_MESSAGE_CARDS' :
'UPDATE_MESSAGE';
// To respond to the correct button, checks the button's actionMethodName.
if (event.action.actionMethodName === 'assign') {
return assignCase(actionResponseType);
}
}
/**
* Updates a card to say that "You" are the assignee after clicking the Assign
* to Me button.
*
* @param {String} actionResponseType Which actionResponse the Chat app should
* use to update the attached card based on who created the message.
* @return {Object} Response from the Chat app. Updates the card attached to
* the message with the previewed link.
*/
function assignCase(actionResponseType) {
return {
'actionResponse': {
// Dynamically returns the correct actionResponse type.
'type': actionResponseType,
},
'cardsV2': [{
'cardId': 'assignCase',
'card': {
'header': {
'title': 'Example Customer Service Case',
'subtitle': 'Case basics',
},
'sections': [{
'widgets': [
{'keyValue': {'topLabel': 'Case ID', 'content': 'case123'}},
{'keyValue': {'topLabel': 'Assignee', 'content': 'You'}},
{'keyValue': {'topLabel': 'Status', 'content': 'Open'}},
{
'keyValue': {
'topLabel': 'Subject', 'content': 'It won\'t turn on...',
}
},
],
},
{
'widgets': [{
'buttons': [
{
'textButton': {
'text': 'OPEN CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123',
},
},
},
},
{
'textButton': {
'text': 'RESOLVE CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123?resolved=y',
},
},
},
},
{
'textButton': {
'text': 'ASSIGN TO ME',
'onClick': {'action': {'actionMethodName': 'assign'}},
},
},
],
}],
}],
},
}],
};
}
制限事項と考慮事項
Chat 用アプリのリンク プレビューを構成する際は、次の制限と考慮事項に留意してください。
- 各 Chat アプリは、最大 5 つの URL パターンのリンク プレビューをサポートしています。
- Chat アプリでは、メッセージごとに 1 つのリンクがプレビューされます。1 つのメールにプレビュー可能なリンクが複数ある場合は、最初のプレビュー可能なリンクのみがプレビューされます。
- Chat アプリでは、
https://
で始まるリンクのみがプレビューされるため、https://support.example.com/cases/
はプレビューしますが、support.example.com/cases/
はプレビューしません。
- Chat アプリに送信されるその他の情報(スラッシュ コマンドなど)がメッセージに含まれている場合を除き、リンク プレビューによって Chat アプリに送信されるのはリンク URL のみです。
- プレビューされたリンクに添付されるカードは、
UPDATE_USER_MESSAGE_CARDS
タイプの ActionResponse
のみをサポートし、Chat でのアプリの操作イベントに応じてのみサポートされます。リンク プレビューは、UPDATE_MESSAGE
や、Chat API を介してプレビュー リンクに添付されたカードを更新する非同期リクエストをサポートしていません。詳しくは、カードを更新するをご覧ください。
- Chat アプリではスペース内の全員のリンクをプレビューする必要があるため、
メッセージで
privateMessageViewer
を省略する必要があります。
表示されます。
リンクのプレビューをデバッグする
リンク プレビューを実装する際、場合によっては、アプリのログを確認して Chat 用アプリをデバッグする必要があります。ログを読むには、Google Cloud コンソールのログ エクスプローラにアクセスします。