เพื่อป้องกันไม่ให้ผู้ใช้เปลี่ยนบริบทเมื่อผู้ใช้แชร์ลิงก์ใน Google Chat แอป Chat จะแสดงตัวอย่างลิงก์ได้โดยแนบการ์ดไปกับข้อความเพื่อให้ข้อมูลเพิ่มเติมและช่วยให้ผู้ใช้ดำเนินการจาก Google Chat ได้โดยตรง
ตัวอย่างเช่น สมมติว่าพื้นที่ใน Google Chat ที่มีตัวแทนฝ่ายบริการลูกค้าของบริษัททั้งหมด 1 รายร่วมกับแอป Chat ชื่อ Case-y ตัวแทนมักจะแชร์ลิงก์เคสฝ่ายบริการลูกค้าในพื้นที่ใน Chat และทุกครั้งที่เพื่อนร่วมงานต้องเปิดลิงก์ของเคสเพื่อดูรายละเอียดต่างๆ เช่น ผู้รับมอบหมาย สถานะ และเรื่อง ในทำนองเดียวกัน หากมีผู้ต้องการเป็นเจ้าของเคสหรือเปลี่ยนสถานะ ก็จะต้องเปิดลิงก์
การแสดงตัวอย่างลิงก์จะช่วยให้ Case-y ที่เป็นแอป Chat ของพื้นที่ทำงานสามารถแนบการ์ดที่แสดงผู้ได้รับมอบหมาย สถานะ และเรื่องได้ทุกครั้งที่มีคนแชร์ลิงก์เคส ปุ่มบนการ์ดจะช่วยให้ตัวแทนเข้าเป็นเจ้าของเคสและเปลี่ยนสถานะจากสตรีมแชทได้โดยตรง
วิธีการทำงานของการแสดงตัวอย่างลิงก์
เมื่อมีคนเพิ่มลิงก์ในข้อความ ชิปจะปรากฏขึ้นเพื่อให้บุคคลดังกล่าวทราบว่าแอป Chat อาจดูตัวอย่างลิงก์
หลังจากส่งข้อความ ระบบจะส่งลิงก์ไปยังแอป Chat ซึ่งจะสร้างและแนบการ์ดไปกับข้อความของผู้ใช้
ด้านข้างของลิงก์ การ์ดจะให้ข้อมูลเพิ่มเติมเกี่ยวกับลิงก์นั้น ซึ่งรวมถึงองค์ประกอบแบบอินเทอร์แอกทีฟ เช่น ปุ่ม แอป Chat จะอัปเดตการ์ดที่แนบมาเพื่อตอบสนองการโต้ตอบของผู้ใช้ เช่น การคลิกปุ่ม
หากผู้ใช้ไม่ต้องการให้แอป Chat แสดงตัวอย่างลิงก์ของตนเองโดยการแนบการ์ดลงในข้อความ ผู้ใช้จะไม่สามารถดูตัวอย่างได้โดยคลิก cancel บนชิปตัวอย่าง ผู้ใช้นำการ์ดที่แนบออกได้ทุกเมื่อโดยคลิกนำตัวอย่างออก
ลงทะเบียนลิงก์ที่เจาะจง เช่น example.com
, support.example.com
และ support.example.com/cases/
เป็นรูปแบบ URL ในหน้าการกำหนดค่าของแอป Chat ในคอนโซล Google Cloud เพื่อให้แอป Chat แสดงตัวอย่างได้
- เปิดคอนโซล Google Cloud
- ถัดจาก "Google Cloud" ให้คลิกลูกศรลง arrow_drop_down แล้วเปิดโปรเจ็กต์ของแอป Chat
- พิมพ์
Google Chat API
ในช่องค้นหา แล้วคลิก Google Chat API
- คลิกจัดการ > การกำหนดค่า
- ในส่วน "ตัวอย่างลิงก์" ให้เพิ่มหรือแก้ไขรูปแบบ URL
- หากต้องการกำหนดค่าตัวอย่างลิงก์สำหรับรูปแบบ URL ใหม่ ให้คลิกเพิ่มรูปแบบ URL
- หากต้องการแก้ไขการกำหนดค่าสำหรับรูปแบบ URL ที่มีอยู่ ให้คลิกลูกศรลง expand_more
ในช่อง รูปแบบโฮสต์ ให้ป้อนโดเมนของรูปแบบ URL แอป Chat จะแสดงตัวอย่างลิงก์ไปยังโดเมนนี้
หากต้องการให้ลิงก์ตัวอย่างแอป Chat ของโดเมนย่อยที่เจาะจง เช่น subdomain.example.com
ให้รวมโดเมนย่อยดังกล่าว
หากต้องการให้ลิงก์แสดงตัวอย่างแอป Chat สําหรับทั้งโดเมน ให้ระบุอักขระไวลด์การ์ดที่มีเครื่องหมายดอกจัน (*) เป็นโดเมนย่อย ตัวอย่างเช่น *.example.com
ตรงกับ subdomain.example.com
และ any.number.of.subdomains.example.com
ในช่องคำนำหน้าเส้นทาง ให้ป้อนเส้นทางเพื่อต่อท้ายโดเมนรูปแบบโฮสต์
หากต้องการจับคู่ URL ทั้งหมดในโดเมนรูปแบบโฮสต์ ให้เว้นคำนำหน้าเส้นทางว่างไว้
ตัวอย่างเช่น ถ้ารูปแบบโฮสต์คือ support.example.com
ในการจับคู่ URL สำหรับกรณีที่โฮสต์ที่ support.example.com/cases/
ให้ป้อน cases/
คลิกเสร็จ
คลิกบันทึก
ในตอนนี้ เมื่อมีคนใส่ลิงก์ที่ตรงกับรูปแบบ URL ตัวอย่างลิงก์กับข้อความในพื้นที่ใน Chat ที่มีแอป Chat ของคุณ แอปจะแสดงตัวอย่างลิงก์นั้น
แสดงตัวอย่างลิงก์
หลังจากกำหนดค่าการแสดงตัวอย่างลิงก์สำหรับลิงก์หนึ่งๆ แล้ว แอปใน Chat จะจดจำและดูตัวอย่างลิงก์ด้วยการแนบข้อมูลเพิ่มเติมได้
ภายในพื้นที่ใน Chat ที่มีแอปใน Chat เมื่อข้อความของผู้ใช้มีลิงก์ที่ตรงกับรูปแบบ URL ของตัวอย่างลิงก์ แอป Chat จะได้รับเหตุการณ์การโต้ตอบ MESSAGE
เพย์โหลด JSON สำหรับเหตุการณ์การโต้ตอบจะมีช่อง matchedUrl
ดังนี้
JSON
"message": {
. . . // other message attributes redacted
"matchedUrl": {
"url": "https://support.example.com/cases/case123"
},
. . . // other message attributes redacted
}
การตรวจหาช่อง matchedUrl
ในเพย์โหลดของเหตุการณ์ MESSAGE
จะช่วยให้แอป Chat เพิ่มข้อมูลลงในข้อความได้ด้วยลิงก์ตัวอย่าง แอป Chat จะตอบกลับด้วยข้อความธรรมดาหรือแนบการ์ดก็ได้
ตอบกลับด้วย SMS
หากต้องการคำตอบง่ายๆ แอป Chat จะดูตัวอย่างลิงก์ได้โดยการตอบข้อความง่ายๆ ไปยังลิงก์ ตัวอย่างนี้จะแนบข้อความที่แสดง 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 แบบไม่พร้อมกันไม่ได้
การแสดงตัวอย่างลิงก์จะไม่รองรับการแสดงผล ActionResponse
ประเภท UPDATE_MESSAGE
เนื่องจาก UPDATE_MESSAGE
จะอัปเดตข้อความทั้งหมด ไม่ใช่เพียงการ์ด ดังนั้นแอป Chat จึงจะสร้างข้อความต้นฉบับไว้เท่านั้น การแสดงตัวอย่างลิงก์จะแนบการ์ดไปกับข้อความที่ผู้ใช้สร้าง ดังนั้นแอป Chat จึงไม่มีสิทธิ์อัปเดต
หากต้องการให้ฟังก์ชันอัปเดตทั้งการ์ดที่ผู้ใช้สร้างขึ้นและที่แอปสร้างขึ้นในสตรีม Chat ให้ตั้งค่า ActionResponse
แบบไดนามิกโดยพิจารณาว่าแอป Chat หรือผู้ใช้เป็นผู้สร้างข้อความหรือไม่
- หากผู้ใช้สร้างข้อความ ให้ตั้งค่า
ActionResponse
เป็น UPDATE_USER_MESSAGE_CARDS
- หากแอป Chat สร้างข้อความขึ้น ให้ตั้งค่า
ActionResponse
เป็น UPDATE_MESSAGE
ซึ่งทำได้ 2 วิธี ได้แก่ การระบุและตรวจหา actionMethodName
ที่กำหนดเองซึ่งเป็นส่วนหนึ่งของพร็อพเพอร์ตี้ onclick
ของการ์ดที่แนบมา (ซึ่งระบุว่าข้อความสร้างขึ้นโดยผู้ใช้) หรือตรวจสอบว่าข้อความสร้างโดยผู้ใช้หรือไม่
หากต้องการใช้ actionMethodName
เพื่อจัดการเหตุการณ์การโต้ตอบ CARD_CLICKED
ในการ์ดที่แสดงตัวอย่างอย่างเหมาะสม ให้ตั้งค่า actionMethodName
ที่กำหนดเองเป็นส่วนหนึ่งของพร็อพเพอร์ตี้ onclick
ของการ์ดที่แนบมา
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"
ซึ่งระบุปุ่มที่เป็นส่วนหนึ่งของตัวอย่างลิงก์ คุณจะแสดงผล ActionResponse
ที่ถูกต้องแบบไดนามิกได้โดยตรวจหา actionMethodName
ที่ตรงกัน
ตัวเลือกที่ 2: ตรวจสอบประเภทผู้ส่ง
ตรวจสอบดูว่า message.sender.type
คือ HUMAN
หรือ BOT
หากเป็น HUMAN
ให้ตั้งค่า ActionResponse
เป็น UPDATE_USER_MESSAGE_CARDS
หรือตั้งค่า ActionResponse
เป็น UPDATE_MESSAGE
ดังนี้
เหตุผลทั่วไปในการอัปเดตการ์ดคือการคลิก กดปุ่มมอบหมายให้กับฉันจากส่วนก่อนหน้าในหัวข้อแนบการ์ด ตัวอย่างที่สมบูรณ์ต่อไปนี้จะอัปเดตการ์ดเพื่อให้การ์ดระบุว่าเป็น "คุณ" หลังจากที่ผู้ใช้คลิกมอบหมายให้กับฉัน ตัวอย่างนี้จะตั้งค่า ActionResponse
แบบไดนามิกโดยตรวจสอบประเภทผู้ส่ง
ตัวอย่างแบบเต็ม: กรณีตัวอย่างคือแอป Chat ฝ่ายบริการลูกค้า
ต่อไปนี้เป็นโค้ดที่สมบูรณ์ของ Case-y ซึ่งเป็นแอป Chat ที่แสดงตัวอย่างลิงก์ไปยังเคสที่แชร์ในพื้นที่ใน 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 ก็ได้
/**
* 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 แต่ละแอปรองรับการแสดงตัวอย่างลิงก์สำหรับรูปแบบ URL สูงสุด 5 รูปแบบ
- แอป Chat จะแสดงตัวอย่าง 1 ลิงก์ต่อข้อความ หากข้อความเดียวมีลิงก์ที่แสดงตัวอย่างได้หลายลิงก์ จะมีเพียงลิงก์ตัวอย่างแรกที่แสดงตัวอย่างได้
- แอป Chat จะแสดงตัวอย่างเฉพาะลิงก์ที่ขึ้นต้นด้วย
https://
ดังนั้น https://support.example.com/cases/
จึงจะแสดงตัวอย่าง แต่ support.example.com/cases/
จะไม่แสดงตัวอย่าง
- ระบบจะส่งเฉพาะ URL ของลิงก์ไปยังแอป Chat ผ่านตัวอย่างลิงก์เท่านั้น เว้นแต่ว่าข้อความจะมีข้อมูลอื่นๆ ที่ส่งไปยังแอป Chat เช่น คำสั่งเครื่องหมายทับ
- การ์ดที่แนบมากับลิงก์ตัวอย่างรองรับเฉพาะ
ActionResponse
ประเภท UPDATE_USER_MESSAGE_CARDS
และตอบสนองต่อเหตุการณ์การโต้ตอบในแอป Chat เท่านั้น ตัวอย่างลิงก์ไม่รองรับคำขอ UPDATE_MESSAGE
หรือคำขออัปเดตการ์ดที่แนบมากับลิงก์แสดงตัวอย่างผ่าน Chat API แบบไม่พร้อมกัน หากต้องการดูข้อมูลเพิ่มเติม โปรดดูหัวข้ออัปเดตการ์ด
แสดงตัวอย่างลิงก์แก้ไขข้อบกพร่อง
เมื่อใช้ตัวอย่างลิงก์ คุณอาจต้องแก้ไขข้อบกพร่องของแอป Chat โดยการอ่านบันทึกของแอป หากต้องการอ่านบันทึก ให้ไปที่ Logs Explorer ในคอนโซล Google Cloud