為了避免使用者在 Google Chat 中分享連結時切換背景資訊,你可以在 Chat 訊息中附加資訊卡來預覽連結,方便使用者直接透過 Google Chat 採取行動。
舉例來說,假設有一個 Google Chat 聊天室包含公司所有的客服專員,以及名為 Case-y 的 Chat 應用程式,服務專員經常在 Chat 聊天室中分享客戶服務案件的連結,而且每當有同事時,他們都必須開啟客服案件連結,才能查看指派對象、狀態和主旨等詳細資料。同樣地,如果有人想取得客服案件的擁有權或變更狀態,就必須開啟連結。
透過連結預覽功能,聊天室的常駐 Chat 應用程式 Case-y 可以在有人分享案件連結時,附加顯示指派對象、狀態和主旨的資訊卡。資訊卡上的按鈕可讓服務專員接手處理案件,並直接在聊天室訊息串中變更狀態。
連結預覽功能的運作方式
當使用者在訊息中新增連結時,畫面上會顯示方塊,說明 Chat 應用程式可能會預覽連結。
![表示 Chat 應用程式可以預覽連結的方塊](https://developers.google.cn/static/workspace/chat/images/link-preview-chip.png?authuser=6&hl=zh-tw)
訊息傳送後,連結會傳送到 Chat 應用程式,然後產生資訊卡並附加到使用者的訊息中。
![在訊息中附加資訊卡,預覽了連結的 Chat 應用程式](https://developers.google.cn/static/workspace/chat/images/link-preview-case-details.png?authuser=6&hl=zh-tw)
資訊卡旁邊會顯示連結額外資訊,包括按鈕等互動元素。您的 Chat 應用程式可根據使用者互動 (例如點選按鈕) 來更新附加的資訊卡。
如果有人在訊息中附加資訊卡,不希望 Chat 應用程式預覽自己的連結,可以按一下預覽方塊上的 cancel,禁止系統預覽。使用者隨時可以按一下「移除預覽」移除附加的資訊卡。
必要條件
Node.js
已啟用互動功能的 Google Chat 應用程式。如要建立
請使用 HTTP 服務互動式即時通訊應用程式,請完成快速入門導覽課程。
Apps Script
已啟用互動功能的 Google Chat 應用程式。如要建立
,請完成快速入門導覽課程。
在 Google Cloud 控制台的 Chat 應用程式設定頁面,將特定連結 (例如 example.com
、support.example.com
和 support.example.com/cases/
) 註冊為網址模式,以便讓 Chat 應用程式預覽。
![連結預覽設定選單](https://developers.google.cn/static/workspace/chat/images/link-preview-configuration.png?authuser=6&hl=zh-tw)
- 開啟 Google Cloud 控制台。
- 在「Google Cloud」旁邊按一下向下箭頭 arrow_drop_down,然後開啟 Chat 應用程式的專案。
- 在搜尋欄位中輸入
Google Chat API
,然後按一下「Google Chat API」。
- 依序按一下「Manage」(管理) >「Configuration」(設定)。
- 在「連結預覽」下方,新增或編輯網址模式。
- 如要為新網址格式設定連結預覽,請按一下「新增網址格式」。
- 如要編輯現有網址格式的設定,請按一下向下箭頭 expand_more。
在「主機模式」欄位中,輸入網址模式的網域。Chat 應用程式將預覽這個網域的連結。
如要針對特定子網域 (例如 subdomain.example.com
) 加入 Chat 應用程式預覽連結,請加入子網域。
如要將 Chat 應用程式預覽連結整個網域,請指定萬用字元並以星號 (*) 做為子網域。舉例來說,*.example.com
符合 subdomain.example.com
和 any.number.of.subdomains.example.com
。
在「路徑前置字串」欄位中,輸入要附加至主機模式網域的路徑。
如要比對主機模式網域中的所有網址,請將「路徑前置字串」留空。
舉例來說,如果主機模式是 support.example.com
,如要比對由 support.example.com/cases/
代管的案件網址,請輸入 cases/
。
按一下 [完成]。
按一下 [儲存]。
現在,只要使用者在 Chat 聊天室 (包含您 Chat 應用程式) 的訊息中附上連結預覽網址模式的連結,該應用程式就會預覽該連結。
預覽連結
為特定連結設定連結預覽功能後,
即時通訊應用程式可透過以下方式辨識及預覽連結:
在此附上更多資訊
採用下列形式的 Chat 聊天室中:
Chat 應用程式:如果使用者的訊息含有
符合連結預覽網址模式,您的 Chat 應用程式
收到
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 應用程式可以預覽連結
使用簡單的簡訊回覆
連結。這個範例會附加訊息,重複指出
符合連結預覽網址模式。
附加卡片
如何在預覽連結中附加資訊卡:
傳回
ActionResponse
類型為 UPDATE_USER_MESSAGE_CARDS
。本範例會附加一張簡易資訊卡。
![在訊息中附加資訊卡,預覽了連結的 Chat 應用程式](https://developers.google.cn/static/chat/images/link-preview-case-details.png?authuser=6&hl=zh-tw)
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 Card 服務。
/**
* 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 API 更新這些卡片
以非同步方式載入物件
連結預覽不支援傳回 UPDATE_MESSAGE
類型的 ActionResponse
。由於 UPDATE_MESSAGE
會更新完整訊息,而非僅更新資訊卡,因此只有在 Chat 應用程式建立原始訊息時才能使用這項功能。連結預覽功能會將資訊卡附加到使用者建立的訊息,因此 Chat 應用程式沒有更新資訊卡的權限。
為確保函式會更新 Chat 串流中使用者建立和應用程式建立的資訊卡,請根據 Chat 應用程式或使用者建立訊息,動態設定 ActionResponse
。
您可透過以下兩種方式確認訊息是否由使用者建立:在附件的 onclick
屬性中指定並檢查自訂 actionMethodName
(將訊息辨識為使用者所建立),或查看訊息是否由使用者建立。
如要使用 actionMethodName
正確處理預覽資訊卡上的 CARD_CLICKED
互動事件,請在附加的資訊卡的 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
。步驟如下:
更新資訊卡的常見原因在於按下按鈕。找出前一節「附加卡片」的「指派給我」按鈕。下方的完整範例會更新資訊卡,指出卡片已指派給「您」使用者按一下 [Assign to Me] (指派給我) 後。這個範例會透過檢查傳送者類型,以動態方式設定 ActionResponse
。
完整範例:Case-y 客戶服務即時通訊應用程式
以下是 Case-y 的完整程式碼:Case-y 是一個即時通訊應用程式,可預覽客服專員在 Chat 聊天室中分享的案件連結。
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 Card 服務。
/**
* 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 個網址模式的連結預覽。
- Chat 擴充應用程式會預覽每則訊息中的一個連結。如果單一訊息中有多個可預覽連結,則只有第一個可預覽的連結預覽畫面。
- 即時通訊應用程式只能預覽開頭為
https://
的連結,因此有 https://support.example.com/cases/
預覽畫面,support.example.com/cases/
則不會。
- 除非訊息含有傳送至 Chat 應用程式的其他資訊 (例如斜線指令),否則只有連結網址會透過連結預覽傳送至 Chat 應用程式。
- 附加至預覽連結的資訊卡僅支援
UPDATE_USER_MESSAGE_CARDS
類型的 ActionResponse
,且僅適用於 Chat 應用程式互動事件。連結預覽功能不支援透過 Chat API 更新附加至預覽連結的卡片,因此不支援 UPDATE_MESSAGE
或非同步要求。詳情請參閱更新卡片。
偵錯連結預覽
實作連結預覽時,您可能需要讀取應用程式的記錄檔,對 Chat 應用程式進行偵錯。如要閱讀記錄,請前往 Google Cloud 控制台的記錄檔探索工具。