Coletar e processar informações dos usuários do Google Chat

Este guia descreve como os apps do Google Chat podem coletar e processar informações dos usuários criando entradas de formulário em interfaces baseadas em cards.

Uma caixa de diálogo com vários widgets diferentes.
Figura 1: um exemplo de app do Chat que abre uma caixa de diálogo para coletar informações de contato.

Os apps do Chat solicitam informações dos usuários para realizar ações dentro ou fora do Chat, incluindo das seguintes maneiras:

  • Definir configurações. Por exemplo, para permitir que os usuários personalizem as configurações de notificação ou configurem e adicionem o app do Chat a um ou mais espaços.
  • Criar ou atualizar informações em outros aplicativos do Google Workspace. Por exemplo, permitir que os usuários criem um evento do Google Agenda.
  • Permitir que os usuários acessem e atualizem recursos em outros apps ou serviços da Web. Por exemplo, um app do Chat pode ajudar os usuários a atualizar o status de um tíquete de suporte diretamente de um espaço do Chat.

Pré-requisitos

Node.js

Um app do Google Chat que recebe e responde a eventos de interação. Para criar um app interativo do Chat usando um serviço HTTP, conclua este guia de início rápido.

Python

Um app do Google Chat que recebe e responde a eventos de interação. Para criar um app interativo do Chat usando um serviço HTTP, conclua este guia de início rápido.

Java

Um app do Google Chat que recebe e responde a eventos de interação. Para criar um app interativo do Chat usando um serviço HTTP, conclua este guia de início rápido.

Apps Script

Um app do Google Chat que recebe e responde a eventos de interação. Para criar um app interativo do Chat no Apps Script, conclua este guia de início rápido.

Criar formulários usando cards

Para coletar informações, os apps do Chat criam formulários e entradas e os incorporam a cards. Para mostrar cards aos usuários, os apps do Chat podem usar as seguintes interfaces do Chat:

  • Mensagens que contêm um ou mais cards.
  • Páginas iniciais, que são um card que aparece na guia Início em mensagens diretas com o app do Chat.
  • Caixas de diálogo, que são cards que são abertos em uma nova janela de mensagens e páginas iniciais.

Os apps do Chat podem criar os cards usando os seguintes widgets:

  • Widgets de entrada de formulário que solicitam informações dos usuários. Opcionalmente, você pode adicionar validação aos widgets de entrada de formulário para garantir que os usuários insiram e formatem as informações corretamente. Os apps do Chat podem usar os seguintes widgets de entrada de formulário:

    • Entradas de texto (textInput) para texto livre ou sugerido.
    • As entradas de seleção (selectionInput) são elementos de interface selecionáveis, como caixas de seleção, botões de opção e menus suspensos. Os widgets de entrada de seleção também podem preencher itens de fontes de dados estáticas ou dinâmicas. Por exemplo, os usuários podem selecionar uma lista de espaços do Chat de que fazem parte.
    • Seletores de data e hora (dateTimePicker) para entradas de data e hora.
  • Um widget de botão para que os usuários possam enviar os valores inseridos no card. Depois que um usuário clica no botão, o app do Chat pode então processar as informações recebidas.

No exemplo a seguir, um card coleta informações de contato usando uma entrada de texto, um seletor de data e hora e uma entrada de seleção:

Para conferir um exemplo de app do Chat que usa esse formulário de contato, consulte o código a seguir:

Node.js

node/contact-form-app/index.js
/**
 * The section of the contact card that contains the form input widgets. Used in a dialog and card message.
 * To add and preview widgets, use the Card Builder: https://addons.gsuite.google.com/uikit/builder
 */
const CONTACT_FORM_WIDGETS = [
  {
    "textInput": {
      "name": "contactName",
      "label": "First and last name",
      "type": "SINGLE_LINE"
    }
  },
  {
    "dateTimePicker": {
      "name": "contactBirthdate",
      "label": "Birthdate",
      "type": "DATE_ONLY"
    }
  },
  {
    "selectionInput": {
      "name": "contactType",
      "label": "Contact type",
      "type": "RADIO_BUTTON",
      "items": [
        {
          "text": "Work",
          "value": "Work",
          "selected": false
        },
        {
          "text": "Personal",
          "value": "Personal",
          "selected": false
        }
      ]
    }
  }
];

Python

python/contact-form-app/main.py
# The section of the contact card that contains the form input widgets. Used in a dialog and card message.
# To add and preview widgets, use the Card Builder: https://addons.gsuite.google.com/uikit/builder
CONTACT_FORM_WIDGETS = [
  {
    "textInput": {
      "name": "contactName",
      "label": "First and last name",
      "type": "SINGLE_LINE"
    }
  },
  {
    "dateTimePicker": {
      "name": "contactBirthdate",
      "label": "Birthdate",
      "type": "DATE_ONLY"
    }
  },
  {
    "selectionInput": {
      "name": "contactType",
      "label": "Contact type",
      "type": "RADIO_BUTTON",
      "items": [
        {
          "text": "Work",
          "value": "Work",
          "selected": False
        },
        {
          "text": "Personal",
          "value": "Personal",
          "selected": False
        }
      ]
    }
  }
]

Java

java/contact-form-app/src/main/java/com/google/chat/contact/App.java
// The section of the contact card that contains the form input widgets. Used in a dialog and card message.
// To add and preview widgets, use the Card Builder: https://addons.gsuite.google.com/uikit/builder
final static private List<GoogleAppsCardV1Widget> CONTACT_FORM_WIDGETS = List.of(
  new GoogleAppsCardV1Widget().setTextInput(new GoogleAppsCardV1TextInput()
    .setName("contactName")
    .setLabel("First and last name")
    .setType("SINGLE_LINE")),
  new GoogleAppsCardV1Widget().setDateTimePicker(new GoogleAppsCardV1DateTimePicker()
    .setName("contactBirthdate")
    .setLabel("Birthdate")
    .setType("DATE_ONLY")),
  new GoogleAppsCardV1Widget().setSelectionInput(new GoogleAppsCardV1SelectionInput()
    .setName("contactType")
    .setLabel("Contact type")
    .setType("RADIO_BUTTON")
    .setItems(List.of(
      new GoogleAppsCardV1SelectionItem()
        .setText("Work")
        .setValue("Work")
        .setSelected(false),
      new GoogleAppsCardV1SelectionItem()
        .setText("Personal")
        .setValue("Personal")
        .setSelected(false)))));

Apps Script

apps-script/contact-form-app/contactForm.gs
/**
 * The section of the contact card that contains the form input widgets. Used in a dialog and card message.
 * To add and preview widgets, use the Card Builder: https://addons.gsuite.google.com/uikit/builder
 */
const CONTACT_FORM_WIDGETS = [
  {
    "textInput": {
      "name": "contactName",
      "label": "First and last name",
      "type": "SINGLE_LINE"
    }
  },
  {
    "dateTimePicker": {
      "name": "contactBirthdate",
      "label": "Birthdate",
      "type": "DATE_ONLY"
    }
  },
  {
    "selectionInput": {
      "name": "contactType",
      "label": "Contact type",
      "type": "RADIO_BUTTON",
      "items": [
        {
          "text": "Work",
          "value": "Work",
          "selected": false
        },
        {
          "text": "Personal",
          "value": "Personal",
          "selected": false
        }
      ]
    }
  }
];

Para mais exemplos de widgets interativos que podem ser usados para coletar informações, consulte Criar um card ou uma caixa de diálogo interativa.

Receber dados de widgets interativos

Sempre que os usuários clicam em um botão, os apps do Chat recebem um evento de interação dependente do local do botão:

  • Se o botão estiver em uma mensagem ou caixa de diálogo, os apps do Chat vão receber um CARD_CLICKED evento de interação que contém informações sobre a interação. O payload dos eventos de interação CARD_CLICKED contém um common.formInputs objeto com todos os valores inseridos pelo usuário.

    É possível recuperar os valores do objeto common.formInputs.WIDGET_NAME, em que WIDGET_NAME é o name campo especificado para o widget. Os valores são retornados como um tipo de dados específico para o widget (representado como um Inputs objeto).

    A seguir, mostramos uma parte de um evento de interação CARD_CLICKED em que um usuário inseriu valores para cada widget:

    HTTP

    {
      "type": "CARD_CLICKED",
      "common": { "formInputs": {
        "contactName": { "stringInputs": {
          "value": ["Kai 0"]
        }},
        "contactBirthdate": { "dateInput": {
          "msSinceEpoch": 1000425600000
        }},
        "contactType": { "stringInputs": {
          "value": ["Personal"]
        }}
      }}
    }
    

    Apps Script

    {
      "type": "CARD_CLICKED",
      "common": { "formInputs": {
        "contactName": { "": { "stringInputs": {
          "value": ["Kai 0"]
        }}},
        "contactBirthdate": { "": { "dateInput": {
          "msSinceEpoch": 1000425600000
        }}},
          "contactType": { "": { "stringInputs": {
          "value": ["Personal"]
        }}}
      }}
    }
    
  • Se o botão estiver em uma página inicial, os apps do Chat vão receber um SUBMIT_FORM evento de interação. O payload do evento de interação contém um commonEventObject.formInputs objeto com todos os valores inseridos pelo usuário.

    É possível recuperar os valores do objeto commonEventObject.formInputs.WIDGET_NAME, em que WIDGET_NAME é o campo name especificado para o widget. Os valores são retornados como um tipo de dados específico para o widget (representado como um Inputs objeto).

    A seguir, mostramos uma parte de um evento de interação SUBMIT_FORM em que um usuário inseriu valores para cada widget:

    HTTP

    {
      "type": "SUBMIT_FORM",
      "commonEventObject": { "formInputs": {
        "contactName": { "stringInputs": {
          "value": ["Kai 0"]
        }},
        "contactBirthdate": { "dateInput": {
          "msSinceEpoch": 1000425600000
        }},
        "contactType": { "stringInputs": {
          "value": ["Personal"]
        }}
      }}
    }
    

    Apps Script

    {
      "type": "SUBMIT_FORM",
      "commonEventObject": { "formInputs": {
        "contactName": { "": { "stringInputs": {
          "value": ["Kai 0"]
        }}},
        "contactBirthdate": { "": { "dateInput": {
          "msSinceEpoch": 1000425600000
        }}},
          "contactType": { "": { "stringInputs": {
          "value": ["Personal"]
        }}}
      }}
    }
    

Para receber os dados, o app do Chat processa o evento de interação para receber os valores que os usuários inserem nos widgets. A tabela a seguir mostra como receber o valor de um determinado widget de entrada de formulário. Para cada widget, a tabela mostra o tipo de dados que o widget aceita, onde o valor é armazenado no evento de interação e um valor de exemplo.

Widget de entrada de formulário Tipo de dados de entrada Valor de entrada do evento de interação Valor de exemplo
textInput stringInputs event.common.formInputs.contactName.stringInputs.value[0] Kai O
selectionInput stringInputs Para receber o primeiro ou único valor, event.common.formInputs.contactType.stringInputs.value[0] Personal
dateTimePicker que aceita apenas datas. dateInput event.common.formInputs.contactBirthdate.dateInput.msSinceEpoch. 1000425600000

Transferir dados para outro card

Depois que um usuário envia informações de um card, talvez seja necessário retornar outros cards para fazer o seguinte:

  • Ajudar os usuários a preencher formulários mais longos criando seções distintas.
  • Permitir que os usuários visualizem e confirmem as informações do card inicial para que possam revisar as respostas antes de enviar.
  • Preencher dinamicamente as partes restantes do formulário. Por exemplo, para pedir aos usuários que criem um agendamento, um app do Chat pode mostrar um card inicial que solicita o motivo do agendamento e, em seguida, preenche outro card que fornece horários disponíveis com base no tipo de agendamento.

Para transferir a entrada de dados do card inicial, crie o button widget com actionParameters que contenham o name do widget e o valor inserido pelo usuário, conforme mostrado no exemplo a seguir:

Node.js

node/contact-form-app/index.js
buttonList: { buttons: [{
  text: "Submit",
  onClick: { action: {
    function: "submitForm",
    parameters: [{
      key: "contactName", value: name }, {
      key: "contactBirthdate", value: birthdate }, {
      key: "contactType", value: type
    }]
  }}
}]}

Python

python/contact-form-app/main.py
'buttonList': { 'buttons': [{
  'text': "Submit",
  'onClick': { 'action': {
    'function': "submitForm",
    'parameters': [{
      'key': "contactName", 'value': name }, {
      'key': "contactBirthdate", 'value': birthdate }, {
      'key': "contactType", 'value': type
    }]
  }}
}]}

Java

java/contact-form-app/src/main/java/com/google/chat/contact/App.java
new GoogleAppsCardV1Widget().setButtonList(new GoogleAppsCardV1ButtonList().setButtons(List.of(new GoogleAppsCardV1Button()
  .setText("Submit")
  .setOnClick(new GoogleAppsCardV1OnClick().setAction(new GoogleAppsCardV1Action()
    .setFunction("submitForm")
    .setParameters(List.of(
      new GoogleAppsCardV1ActionParameter().setKey("contactName").setValue(name),
      new GoogleAppsCardV1ActionParameter().setKey("contactBirthdate").setValue(birthdate),
      new GoogleAppsCardV1ActionParameter().setKey("contactType").setValue(type))))))))));

Apps Script

apps-script/contact-form-app/main.gs
buttonList: { buttons: [{
  text: "Submit",
  onClick: { action: {
    function: "submitForm",
    parameters: [{
      key: "contactName", value: name }, {
      key: "contactBirthdate", value: birthdate }, {
      key: "contactType", value: type
    }]
  }}
}]}

Quando um usuário clica no botão, o app do Chat recebe um CARD_CLICKED evento de interação do qual é possível receber dados.

Responder a um envio de formulário

Depois de receber os dados de uma mensagem de card ou caixa de diálogo, o app do Chat responde confirmando o recebimento ou retornando um erro.

No exemplo a seguir, um app do Chat envia uma mensagem de texto para confirmar que recebeu um formulário enviado de uma caixa de diálogo ou mensagem de card.

Node.js

node/contact-form-app/index.js
const contactName = event.common.parameters["contactName"];
// Checks to make sure the user entered a contact name.
// If no name value detected, returns an error message.
const errorMessage = "Don't forget to name your new contact!";
if (!contactName && event.dialogEventType === "SUBMIT_DIALOG") {
  return { actionResponse: {
    type: "DIALOG",
    dialogAction: { actionStatus: {
      statusCode: "INVALID_ARGUMENT",
      userFacingMessage: errorMessage
    }}
  }};
}

Python

python/contact-form-app/main.py
contact_name = event.get('common').get('parameters')["contactName"]
# Checks to make sure the user entered a contact name.
# If no name value detected, returns an error message.
error_message = "Don't forget to name your new contact!"
if contact_name == "" and "SUBMIT_DIALOG" == event.get('dialogEventType'):
  return { 'actionResponse': {
    'type': "DIALOG",
    'dialogAction': { 'actionStatus': {
      'statusCode': "INVALID_ARGUMENT",
      'userFacingMessage': error_message
    }}
  }}

Java

java/contact-form-app/src/main/java/com/google/chat/contact/App.java
String contactName = event.at("/common/parameters/contactName").asText();
// Checks to make sure the user entered a contact name.
// If no name value detected, returns an error message.
String errorMessage = "Don't forget to name your new contact!";
if (contactName.isEmpty() && event.at("/dialogEventType") != null && "SUBMIT_DIALOG".equals(event.at("/dialogEventType").asText())) {
  return new Message().setActionResponse(new ActionResponse()
    .setType("DIALOG")
    .setDialogAction(new DialogAction().setActionStatus(new ActionStatus()
      .setStatusCode("INVALID_ARGUMENT")
      .setUserFacingMessage(errorMessage))));
}

Apps Script

apps-script/contact-form-app/main.gs
const contactName = event.common.parameters["contactName"];
// Checks to make sure the user entered a contact name.
// If no name value detected, returns an error message.
const errorMessage = "Don't forget to name your new contact!";
if (!contactName && event.dialogEventType === "SUBMIT_DIALOG") {
  return { actionResponse: {
    type: "DIALOG",
    dialogAction: { actionStatus: {
      statusCode: "INVALID_ARGUMENT",
      userFacingMessage: errorMessage
    }}
  }};
}

Para processar e fechar uma caixa de diálogo, retorne um ActionResponse objeto que especifica se você quer enviar uma mensagem de confirmação, atualizar a mensagem ou o card original ou apenas fechar a caixa de diálogo. Para conferir as etapas, consulte Fechar uma caixa de diálogo.

Resolver problemas

Quando um app ou card do Google Chat retorna um erro, a interface do Chat mostra uma mensagem dizendo "Algo deu errado." ou "Não foi possível processar sua solicitação". Às vezes, a interface do Chat não mostra nenhuma mensagem de erro, mas o app ou card do Chat produz um resultado inesperado. Por exemplo, uma mensagem de card pode não aparecer.

Embora uma mensagem de erro não seja mostrada na interface do Chat, mensagens de erro descritivas e dados de registro estão disponíveis para ajudar a corrigir erros quando o registro de erros para apps do Chat está ativado. Para receber ajuda para visualizar, depurar e corrigir erros, consulte Resolver e corrigir erros do Google Chat.