Visualizar links em mensagens do Google Chat

Para evitar a mudança de contexto quando os usuários compartilham um link no Google Chat, o app de chat pode visualizar o link anexando um card à mensagem que oferece mais informações e permite que as pessoas realizem ações diretamente no Google Chat.

No Google Chat, os complementos aparecem para os usuários como apps do Google Chat. Para saber mais, consulte a Visão geral do Extend Google Chat.

Por exemplo, imagine um espaço do Google Chat que inclui todos os agentes de atendimento ao cliente de uma empresa e um app de chat chamado Case-y. Os agentes compartilham links de casos de atendimento ao cliente no espaço de chat com frequência. E sempre que fazem isso, os colegas precisam abrir o link do caso para conferir detalhes como responsável, status e assunto. Da mesma forma, se alguém quiser assumir a propriedade de um caso ou mudar o status, ele precisará abrir o link.

A visualização de links permite que o app de chat residente do espaço, Case-y, anexe um card mostrando o atribuído, o status e o assunto sempre que alguém compartilhar um link de caso. Os botões no card permitem que os agentes assumam a propriedade do caso e mudem o status diretamente na transmissão do chat.

Quando alguém adiciona um link à mensagem, um ícone aparece para informar que um app de chat pode mostrar uma prévia do link.

Ícone indicando que um app de chat pode mostrar uma prévia de um link

Depois de enviar a mensagem, o link é enviado ao app Chat, que gera e anexa o card à mensagem do usuário.

App de chat com a visualização de um link anexando um card à mensagem

Além do link, o card oferece mais informações sobre ele, incluindo elementos interativos, como botões. O app Chat pode atualizar o card anexado em resposta a interações do usuário, como cliques em botões.

Se alguém não quiser que o app Chat mostre uma prévia do link anexando um card à mensagem, é possível impedir a visualização clicando em no ícone de visualização. Os usuários podem remover o card anexado a qualquer momento clicando em Remover visualização.

Pré-requisitos

Node.js

Um complemento do Google Workspace que estende o Google Chat. Para criar um, conclua o Guia de início rápido do HTTP.

Apps Script

Um complemento do Google Workspace que estende o Google Chat. Para criar um, conclua o Guia de início rápido do Apps Script.

Registre links específicos, como example.com, support.example.com e support.example.com/cases/, como padrões de URL na página de configuração do seu app de chat no console do Google Cloud para que ele possa mostrar uma prévia deles.

Menu de configuração das visualizações de links

  1. Abra o Console do Google Cloud.
  2. Ao lado de "Google Cloud", clique na seta para baixo e abra o projeto do app de chat.
  3. No campo de pesquisa, digite Google Chat API e clique em API Google Chat.
  4. Clique em Gerenciar > Configuração.
  5. Em "Visualizações de link", adicione ou edite um padrão de URL.
    1. Para configurar as visualizações de link de um novo padrão de URL, clique em Adicionar padrão de URL.
    2. Para editar a configuração de um padrão de URL, clique na seta para baixo .
  6. No campo Padrão de host, insira o domínio do padrão de URL. O app de chat vai mostrar uma prévia dos links para esse domínio.

    Para que o app do Chat mostre links de visualização para um subdomínio específico, como subdomain.example.com, inclua o subdomínio.

    Para que o app de chat mostre links de visualização para todo o domínio, especifique um caractere curinga com um asterisco (*) como subdomínio. Por exemplo, *.example.com corresponde a subdomain.example.com e any.number.of.subdomains.example.com.

  7. No campo Prefixo do caminho, insira um caminho para anexar ao domínio do padrão do host.

    Para corresponder a todos os URLs no domínio do padrão do host, deixe o Prefixo do caminho em branco.

    Por exemplo, se o padrão do host for support.example.com, para corresponder a URLs de casos hospedados em support.example.com/cases/, insira cases/.

  8. Clique em Concluído.

  9. Clique em Salvar.

Agora, sempre que alguém incluir um link que corresponda a um padrão de URL de visualização de link em uma mensagem em um espaço do Chat que inclua seu app, o link será mostrado na prévia.

Depois de configurar a visualização de links para um determinado link, o app de chat poderá reconhecer e visualizar o link anexando mais informações a ele.

Nos espaços de chat que incluem seu app de chat, quando a mensagem de alguém contém um link que corresponde a um padrão de URL de visualização de link, o app recebe um objeto de evento com um MessagePayload. No payload, o objeto message.matchedUrl contém o link que o usuário incluiu na mensagem:

JSON

message: {
  matchedUrl: {
    url: "https://support.example.com/cases/case123"
  },
  ... // other message attributes redacted
}

Ao verificar a presença do campo matchedUrl no payload do evento MESSAGE, o app de chat pode adicionar informações à mensagem com o link de visualização. O app do Chat pode responder com uma mensagem de texto básica ou anexar um card.

Responder com uma mensagem de texto

Para respostas básicas, o app de chat pode mostrar uma prévia de um link respondendo com uma mensagem de texto para um link. Este exemplo anexa uma mensagem que repete o URL do link que corresponde a um padrão de URL de visualização de link.

Node.js

/**
 * Google Cloud Function that handles messages that have links whose
 * URLs match URL patterns configured for link previewing.
 *
 *
 * @param {Object} req Request sent from Google Chat space
 * @param {Object} res Response to send back
 */
exports.previewLinks = function previewLinks(req, res) {
  const chatEvent = req.body.chat;

  // Handle MESSAGE events
  if(chatEvent.messagePayload) {
    return res.send(handlePreviewLink(chatEvent.messagePayload.message));
  // Handle button clicks
  } else if(chatEvent.buttonClickedPayload) {
    return res.send(handleCardClick(chatEvent.buttonClickedPayload.message));
  }
};

/**
 * Respond to messages that have links whose URLs match URL patterns configured
 * for link previewing.
 *
 * @param {Object} chatMessage The chat message object from Google Workspace Add On event.
 * @return {Object} Response to send back depending on the matched URL.
 */
function handlePreviewLink(chatMessage) {
  // If the Chat app does not detect a link preview URL pattern, reply
  // with a text message that says so.
  if (!chatMessage.matchedUrl) {
    return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
      text: 'No matchedUrl detected.'
    }}}}};
  }

  // Reply with a text message for URLs of the subdomain "text"
  if (chatMessage.matchedUrl.url.includes("text.example.com")) {
    return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
      text: 'event.chat.messagePayload.message.matchedUrl.url: ' + chatMessage.matchedUrl.url
    }}}}};
  }
}

Apps Script

/**
 * Reply to messages that have links whose URLs match the pattern
 * "text.example.com" configured for link previewing.
 *
 * @param {Object} event The event object from Google Workspace Add-on.
 *
 * @return {Object} The action response.
 */
function onMessage(event) {
  // Stores the Google Chat event as a variable.
  const chatMessage = event.chat.messagePayload.message;

  // If the Chat app doesn't detect a link preview URL pattern, reply
  // with a text message that says so.
  if (!chatMessage.matchedUrl) {
    return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
      text: 'No matchedUrl detected.'
    }}}}};
  }

  // Reply with a text message for URLs of the subdomain "text".
  if (chatMessage.matchedUrl.url.includes("text.example.com")) {
    return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
      text: 'event.chat.messagePayload.message.matchedUrl.url: ' + chatMessage.matchedUrl.url
    }}}}};
  }
}

Para anexar um card a um link com visualização, retorne a ação DataActions com o objeto ChatDataActionMarkup do tipo UpdateInlinePreviewAction.

No exemplo abaixo, um app de chat adiciona um card de pré-visualização às mensagens que contêm o padrão de URL support.example.com.

App de chat com a visualização de um link anexando um card à mensagem

Node.js

/**
 * Google Cloud Function that handles messages that have links whose
 * URLs match URL patterns configured for link previewing.
 *
 *
 * @param {Object} req Request sent from Google Chat space
 * @param {Object} res Response to send back
 */
exports.previewLinks = function previewLinks(req, res) {
  const chatEvent = req.body.chat;

  // Handle MESSAGE events
  if(chatEvent.messagePayload) {
    return res.send(handlePreviewLink(chatEvent.messagePayload.message));
  // Handle button clicks
  } else if(chatEvent.buttonClickedPayload) {
    return res.send(handleCardClick(chatEvent.buttonClickedPayload.message));
  }
};

/**
 * Respond to messages that have links whose URLs match URL patterns configured
 * for link previewing.
 *
 * @param {Object} chatMessage The chat message object from Google Workspace Add On event.
 * @return {Object} Response to send back depending on the matched URL.
 */
function handlePreviewLink(chatMessage) {
  // Attach a card to the message for URLs of the subdomain "support"
  if (chatMessage.matchedUrl.url.includes("support.example.com")) {
    // A hard-coded card is used in this example. In a real-life scenario,
    // the case information would be fetched and used to build the card.
    return { hostAppDataAction: { chatDataAction: { updateInlinePreviewAction: { cardsV2: [{
      cardId: 'attachCard',
      card: {
        header: {
          title: 'Example Customer Service Case',
          subtitle: 'Case basics',
        },
        sections: [{ widgets: [
        { decoratedText: { topLabel: 'Case ID', text: 'case123'}},
        { decoratedText: { topLabel: 'Assignee', text: 'Charlie'}},
        { decoratedText: { topLabel: 'Status', text: 'Open'}},
        { decoratedText: { topLabel: 'Subject', text: 'It won\'t turn on...' }},
        { buttonList: { buttons: [{
          text: 'OPEN CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123'
          }},
        }, {
          text: 'RESOLVE CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123?resolved=y',
          }},
        }, {
          text: 'ASSIGN TO ME',
          // Use runtime environment variable set with self URL
          onClick: { action: { function: process.env.BASE_URL }}
        }]}}
        ]}]
      }
    }]}}}};
  }
}

Apps Script

Este exemplo envia uma mensagem de cartão retornando o card JSON. Também é possível usar o serviço de cards do Apps Script.

/**
 * Attach a card to messages that have links whose URLs match the pattern
 * "support.example.com" configured for link previewing.
 *
 * @param {Object} event The event object from Google Workspace Add-on.
 *
 * @return {Object} The action response.
 */
function onMessage(event) {
  // Stores the Google Chat event as a variable.
  const chatMessage = event.chat.messagePayload.message;

  // Attach a card to the message for URLs of the subdomain "support".
  if (chatMessage.matchedUrl.url.includes("support.example.com")) {
    // A hard-coded card is used in this example. In a real-life scenario,
    // the case information would be fetched and used to build the card.
    return { hostAppDataAction: { chatDataAction: { updateInlinePreviewAction: { cardsV2: [{
      cardId: 'attachCard',
      card: {
        header: {
          title: 'Example Customer Service Case',
          subtitle: 'Case summary',
        },
        sections: [{ widgets: [
        { decoratedText: { topLabel: 'Case ID', text: 'case123'}},
        { decoratedText: { topLabel: 'Assignee', text: 'Charlie'}},
        { decoratedText: { topLabel: 'Status', text: 'Open'}},
        { decoratedText: { topLabel: 'Subject', text: 'It won\'t turn on...' }},
        { buttonList: { buttons: [{
          text: 'OPEN CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123'
          }},
        }, {
          text: 'RESOLVE CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123?resolved=y',
          }},
        }, {
          text: 'ASSIGN TO ME',
          // Clicking this button triggers the execution of the function
          // "assign" from the Apps Script project.
          onClick: { action: { function: 'assign'}}
        }]}}
        ]}]
      }
    }]}}}};
  }
}

O app de chat pode atualizar um card de visualização de link quando os usuários interagem com ele, como clicar em um botão no card.

Para atualizar o card, seu app de chat precisa retornar a ação DataActions com um dos seguintes objetos ChatDataActionMarkup:

Para determinar quem enviou a mensagem, use o payload do evento (buttonClickedPayload) para verificar se o remetente (message.sender.type) está definido como HUMAN (usuário) ou BOT (app Chat).

O exemplo a seguir mostra como um app de chat atualiza uma visualização de link sempre que um usuário clica no botão Atribuir a mim, atualiza o campo Assignee do card e desativa o botão.

App de chat com a prévia de um link com uma versão atualizada de um card anexado a uma mensagem

Node.js

/**
 * Google Cloud Function that handles messages that have links whose
 * URLs match URL patterns configured for link previewing.
 *
 *
 * @param {Object} req Request sent from Google Chat space
 * @param {Object} res Response to send back
 */
exports.previewLinks = function previewLinks(req, res) {
  const chatEvent = req.body.chat;

  // Handle MESSAGE events
  if(chatEvent.messagePayload) {
    return res.send(handlePreviewLink(chatEvent.messagePayload.message));
  // Handle button clicks
  } else if(chatEvent.buttonClickedPayload) {
    return res.send(handleCardClick(chatEvent.buttonClickedPayload.message));
  }
};

/**
 * Respond to clicks by assigning user and updating the card that was attached to a
 * message with a previewed link.
 *
 * @param {Object} chatMessage The chat message object from Google Workspace Add On event.
 * @return {Object} Action response depending on the original message.
 */
function handleCardClick(chatMessage) {
  // Creates the updated card that displays "You" for the assignee
  // and that disables the button.
  //
  // A hard-coded card is used in this example. In a real-life scenario,
  // an actual assign action would be performed before building the card.
  const message = { cardsV2: [{
    cardId: 'attachCard',
    card: {
      header: {
        title: 'Example Customer Service Case',
        subtitle: 'Case basics',
      },
      sections: [{ widgets: [
        { decoratedText: { topLabel: 'Case ID', text: 'case123'}},
        // The assignee is now "You"
        { decoratedText: { topLabel: 'Assignee', text: 'You'}},
        { decoratedText: { topLabel: 'Status', text: 'Open'}},
        { decoratedText: { topLabel: 'Subject', text: 'It won\'t turn on...' }},
        { buttonList: { buttons: [{
          text: 'OPEN CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123'
          }},
        }, {
          text: 'RESOLVE CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123?resolved=y',
          }},
        }, {
          text: 'ASSIGN TO ME',
          // The button is now disabled
          disabled: true,
          // Use runtime environment variable set with self URL
          onClick: { action: { function: process.env.BASE_URL }}
        }]}}
      ]}]
    }
  }]};

  // Checks whether the message event originated from a human or a Chat app
  // to return the adequate action response.
  if(chatMessage.sender.type === 'HUMAN') {
    return { hostAppDataAction: { chatDataAction: { updateInlinePreviewAction: message }}};
  } else {
    return { hostAppDataAction: { chatDataAction: { updateMessageAction: message }}};
  }
}

Apps Script

Este exemplo envia uma mensagem de cartão retornando o card JSON. Também é possível usar o serviço de cards do Apps Script.

/**
 * Assigns and updates the card that's attached to a message with a
 * previewed link of the pattern "support.example.com".
 *
 * @param {Object} event The event object from the Google Workspace Add-on.
 *
 * @return {Object} Action response depending on the message author.
 */
function assign(event) {
  // Creates the updated card that displays "You" for the assignee
  // and that disables the button.
  //
  // A hard-coded card is used in this example. In a real-life scenario,
  // an actual assign action would be performed before building the card.
  const message = { cardsV2: [{
    cardId: 'attachCard',
    card: {
      header: {
        title: 'Example Customer Service Case',
        subtitle: 'Case summary',
      },
      sections: [{ widgets: [
        { decoratedText: { topLabel: 'Case ID', text: 'case123'}},
        // The assignee is now "You"
        { decoratedText: { topLabel: 'Assignee', text: 'You'}},
        { decoratedText: { topLabel: 'Status', text: 'Open'}},
        { decoratedText: { topLabel: 'Subject', text: 'It won\'t turn on...' }},
        { buttonList: { buttons: [{
          text: 'OPEN CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123'
          }},
        }, {
          text: 'RESOLVE CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123?resolved=y',
          }},
        }, {
          text: 'ASSIGN TO ME',
          // The button is now disabled
          disabled: true,
          onClick: { action: { function: 'assign'}}
        }]}}
      ]}]
    }
  }]};

  // Use the adequate action response type. It depends on whether the message
  // the preview link card is attached to was created by a human or a Chat app.
  if(event.chat.buttonClickedPayload.message.sender.type === 'HUMAN') {
    return { hostAppDataAction: { chatDataAction: { updateInlinePreviewAction: message }}};
  } else {
    return { hostAppDataAction: { chatDataAction: { updateMessageAction: message }}};
  }
}

Limites e considerações

Ao configurar as prévias de links no seu app Chat, observe estes limites e considerações:

  • Cada app de chat oferece suporte a visualizações de link para até cinco padrões de URL.
  • Os apps de chat mostram uma prévia de um link por mensagem. Se vários links com visualização estiverem presentes em uma única mensagem, apenas o primeiro será visualizado.
  • Os apps de chat só mostram links que começam com https://, então https://support.example.com/cases/ mostra uma prévia, mas support.example.com/cases/ não.
  • A menos que a mensagem inclua outras informações enviadas ao app Chat, como um comando de barra, apenas o URL do link é enviado ao app Chat pelas visualizações de link.
  • Se um usuário postar o link, um app do Chat só poderá atualizar o card de visualização de link se os usuários interagirem com ele, como clicando em um botão. Não é possível chamar o método update() da API Chat no recurso Message para atualizar a mensagem de um usuário de forma assíncrona.
  • Os apps de chat precisam mostrar uma prévia dos links para todos no espaço. Portanto, a mensagem precisa omitir o campo privateMessageViewer.

Ao implementar as visualizações de link, talvez seja necessário depurar o app Chat lendo os registros dele. Para ler os registros, acesse o Explorador de registros no console do Google Cloud.