Raccogliere ed elaborare informazioni degli utenti di Google Chat

Questa guida descrive come le app Google Chat possono raccogliere ed elaborare le informazioni degli utenti creando input dei moduli in interfacce basate su schede.

Una finestra di dialogo con una serie di widget diversi.
Figura 1: un'app di chat di esempio che apre una finestra di dialogo per raccogliere i dati di contatto.

Le app di chat richiedono informazioni agli utenti per eseguire azioni all'interno o all'esterno di Chat, ad esempio:

  • Configura le impostazioni. Ad esempio, per consentire agli utenti di personalizzare le impostazioni di notifica o configurare e aggiungere l'app Chat a uno o più spazi.
  • Creare o aggiornare informazioni in altre applicazioni Google Workspace. Ad esempio, consentire agli utenti di creare un evento di Google Calendar.
  • Consente agli utenti di accedere e aggiornare le risorse in altre app o servizi web. Ad esempio, un'app di chat può aiutare gli utenti ad aggiornare lo stato di un ticket di assistenza direttamente da uno spazio di Chat.

Prerequisiti

HTTP

Un'app Google Chat che riceve e risponde alle interazioni degli utenti. Per crearne uno, completa la guida rapida HTTP.

Apps Script

Un'app Google Chat che riceve e risponde alle interazioni degli utenti. Per crearne uno, completa la guida rapida di Apps Script.

Creare moduli utilizzando le schede

Per raccogliere informazioni, le app di Chat progettano moduli e relativi input e li integrano nelle schede. Per mostrare le schede agli utenti, le app di chat possono utilizzare le seguenti interfacce di Chat:

  • Messaggi che contengono una o più schede.
  • Home page, che è una scheda che viene visualizzata nella scheda Home dei messaggi diretti con l'app Chat.
  • Finestre di dialogo, ovvero schede che si aprono in una nuova finestra da messaggi e home page.

Le app di chat possono creare le schede utilizzando i seguenti widget:

  • Widget di input del modulo che richiedono informazioni agli utenti. (Facoltativo) Puoi aggiungere la convalida ai widget di input del modulo per assicurarti che gli utenti inseriscano e formattino le informazioni in modo corretto. Le app di chat possono utilizzare i seguenti widget di input del modulo:

  • Un widget pulsante in modo che gli utenti possano inviare i valori inseriti nella scheda. Dopo che un utente fa clic sul pulsante, l'app Chat può elaborare le informazioni che riceve.

Nell'esempio seguente, una scheda raccoglie i dati di contatto utilizzando un input di testo, un selettore di data e ora e un input di selezione:

Per altri esempi di widget interattivi che puoi utilizzare per raccogliere informazioni, consulta Progettare una scheda o una finestra di dialogo interattiva.

Aggiungere un menu a discesa

Per personalizzare gli elementi di selezione o consentire agli utenti di selezionare un singolo elemento da un'origine dati dinamica, le app di chat possono utilizzare menu a discesa, che sono un tipo di widget SelectionInput. Ad esempio, la seguente scheda mostra un menu a discesa in cui gli utenti possono selezionare dinamicamente da un elenco di contatti:

Puoi compilare gli elementi per un menu a discesa dalle seguenti origini dati:

Compilare gli elementi da un'origine dati Google Workspace

Per compilare gli elementi dalle origini dati di Google Workspace, ad esempio gli utenti di Google Workspace, specifica il campo platformDataSource all'interno di un oggetto DataSourceConfig. A differenza di altri tipi di input di selezione, puoi omettere gli oggetti SelectionItem perché questi elementi di selezione vengono recuperati dinamicamente da Google Workspace.

Il seguente codice mostra un menu a discesa degli utenti di Google Workspace:

JSON

{
  "sections": [
    {
      "header": "Section Header",
      "widgets": [
        {
          "selectionInput": {
            "name": "contacts",
            "type": "DROPDOWN",
            "label": "Select contact from organization",
            "data_source_configs": [
              {
                "platformDataSource": {
                  "commonDataSource": "USER"
                },
                "min_characters_trigger": 1
              }
            ]
          }
        }
      ]
    }
  ]
}

Compilare gli elementi da un'origine dati esterna

I menu a discesa possono anche compilare elementi da un'origine dati esterna o di terze parti. Per utilizzare un'origine dati esterna, specifica il campo remoteDataSource all'interno di un oggetto DataSourceConfig che contiene la funzione che esegue query e restituisce elementi dall'origine dati.

Per ridurre le richieste a un'origine dati esterna, puoi includere gli elementi suggeriti che vengono visualizzati nel menu a discesa prima che gli utenti digitino nel menu. Per compilare gli elementi suggeriti da un'origine dati esterna, specifica oggetti statici SelectionItem.

Il seguente codice mostra un menu a discesa che esegue query e popola gli elementi da un'origine dati esterna:

JSON

{
  "sections": [
    {
      "header": "Section Header",
      "widgets": [
        {
          "selectionInput": {
            "name": "crm_leads",
            "type": "DROPDOWN",
            "label": "Select CRM Lead",
            "data_source_configs": [
              {
                "remoteDataSource": {
                  "function": "getCrmLeads"
                },
                "min_characters_trigger": 2
              }
            ],
            "items": [
              {
                "text": "Suggested Lead 1",
                "value": "lead-1"
              }
            ]
          }
        }
      ]
    }
  ]
}

Per un esempio completo che mostra come restituire gli elementi suggeriti, consulta la sezione Suggerisci elementi di selezione.

Aggiungere un menu a selezione multipla

Per personalizzare gli elementi di selezione o consentire agli utenti di selezionare elementi da un'origine dati dinamica, le app di chat possono utilizzare menu a selezione multipla, che sono un tipo di widget SelectionInput. Ad esempio, la seguente scheda mostra un menu a selezione multipla in cui gli utenti possono selezionare dinamicamente da un elenco di contatti:

Puoi compilare gli elementi per un menu a selezione multipla dalle seguenti origini dati:

  • Dati di Google Workspace, che includono utenti o spazi di Chat di cui l'utente è membro. Il menu viene compilato solo con elementi della stessa organizzazione Google Workspace.
  • Origini dati esterne, ad esempio un database relazionale. Ad esempio, puoi utilizzare i menu a selezione multipla per aiutare un utente a scegliere da un elenco di lead di vendita di un sistema di gestione dei rapporti con i clienti (CRM).

Compilare gli elementi da un'origine dati Google Workspace

Per utilizzare le origini dati di Google Workspace, specifica il campo platformDataSource nel widget SelectionInput. A differenza di altri tipi di input di selezione, puoi omettere gli oggetti SelectionItem perché questi elementi di selezione vengono recuperati dinamicamente da Google Workspace.

Il seguente codice mostra un menu a selezione multipla degli utenti di Google Workspace. Per compilare gli utenti, l'input di selezione imposta commonDataSource su USER:

JSON

{
  "selectionInput": {
    "name": "contacts",
    "type": "MULTI_SELECT",
    "label": "Selected contacts",
    "multiSelectMaxSelectedItems": 5,
    "multiSelectMinQueryLength": 1,
    "platformDataSource": {
      "commonDataSource": "USER"
    }
  }
}

Il seguente codice mostra un menu a selezione multipla degli spazi Chat. Per compilare gli spazi, l'input di selezione specifica il campo hostAppDataSource. Il menu di selezione multipla imposta anche defaultToCurrentSpace su true, il che rende lo spazio attuale la selezione predefinita nel menu:

JSON

{
  "selectionInput": {
    "name": "spaces",
    "type": "MULTI_SELECT",
    "label": "Selected contacts",
    "multiSelectMaxSelectedItems": 3,
    "multiSelectMinQueryLength": 1,
    "platformDataSource": {
      "hostAppDataSource": {
        "chatDataSource": {
          "spaceDataSource": {
            "defaultToCurrentSpace": true
          }
        }
      }
    }
  }
}

Compilare gli elementi da un'origine dati esterna

I menu a selezione multipla possono anche compilare elementi da un'origine dati esterna o di terze parti. Per utilizzare un'origine dati esterna, specifica il campo externalDataSource nel widget SelectionInput che contiene la funzione che esegue query e restituisce elementi dall'origine dati.

Per ridurre le richieste a un'origine dati esterna, puoi includere gli elementi suggeriti che vengono visualizzati nel menu a selezione multipla prima che gli utenti digitino nel menu. Ad esempio, puoi compilare i contatti cercati di recente per l'utente. Per compilare gli elementi suggeriti da un'origine dati esterna, specifica oggetti statici SelectionItem.

Il seguente esempio di codice mostra un menu a selezione multipla che esegue query e compila gli elementi da un'origine dati esterna:

Node.js

node/chat/selection-input/index.js
selectionInput: {
  name: "contacts",
  type: "MULTI_SELECT",
  label: "Selected contacts",
  multiSelectMaxSelectedItems: 3,
  multiSelectMinQueryLength: 1,
  externalDataSource: { function: FUNCTION_URL },
  // Suggested items loaded by default.
  // The list is static here but it could be dynamic.
  items: [getSuggestedContact("3")]
}

Sostituisci FUNCTION_URL con l'endpoint HTTP che esegue query sull'origine dati esterna.

Python

python/chat/selection-input/main.py
'selectionInput': {
  'name': "contacts",
  'type': "MULTI_SELECT",
  'label': "Selected contacts",
  'multiSelectMaxSelectedItems': 3,
  'multiSelectMinQueryLength': 1,
  'externalDataSource': { 'function': FUNCTION_URL },
  # Suggested items loaded by default.
  # The list is static here but it could be dynamic.
  'items': [get_suggested_contact("3")]
}

Sostituisci FUNCTION_URL con l'endpoint HTTP che esegue query sull'origine dati esterna.

Java

java/chat/selection-input/src/main/java/com/google/chat/selectionInput/App.java
.setSelectionInput(new GoogleAppsCardV1SelectionInput()
  .setName("contacts")
  .setType("MULTI_SELECT")
  .setLabel("Selected contacts")
  .setMultiSelectMaxSelectedItems(3)
  .setMultiSelectMinQueryLength(1)
  .setExternalDataSource(new GoogleAppsCardV1Action().setFunction(FUNCTION_URL))
  // Suggested items loaded by default.
  // The list is static here but it could be dynamic.
  .setItems(List.of(getSuggestedContact("3")))))))))));

Sostituisci FUNCTION_URL con l'endpoint HTTP che esegue query sull'origine dati esterna.

Apps Script

Questo esempio invia un messaggio della scheda restituendo JSON della scheda. Puoi anche utilizzare il servizio di schede Apps Script.

apps-script/chat/selection-input/selection-input.gs
selectionInput: {
  name: "contacts",
  type: "MULTI_SELECT",
  label: "Selected contacts",
  multiSelectMaxSelectedItems: 3,
  multiSelectMinQueryLength: 1,
  externalDataSource: { function: "queryContacts" },
  // Suggested items loaded by default.
  // The list is static here but it could be dynamic.
  items: [getSuggestedContact("3")]
}

Per un esempio completo che mostra come restituire gli elementi suggeriti, consulta la sezione Suggerisci elementi di selezione.

Ricevere dati dai widget interattivi

Ogni volta che gli utenti fanno clic su un pulsante, viene attivata la relativa azione delle app di chat con informazioni sull'interazione. In commonEventObject del payload dell'evento, l'oggetto formInputs contiene tutti i valori inseriti dall'utente.

Puoi recuperare i valori dall'oggetto event.commonEventObject.formInputs.WIDGET_NAME, dove WIDGET_NAME è il campo name che hai specificato per il widget. I valori vengono restituiti come un tipo di dati specifico per il widget.

Di seguito viene mostrata una parte di un oggetto evento in cui un utente ha inserito valori per ogni widget:

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

Per ricevere i dati, l'app Chat gestisce l'oggetto evento per ottenere i valori inseriti dagli utenti nei widget. La tabella seguente mostra come ottenere il valore per un determinato widget di input del modulo. Per ogni widget, la tabella mostra il tipo di dati accettato, la posizione in cui il valore è memorizzato nell'oggetto evento e un valore di esempio.

Widget di input del modulo Tipo di dati di input Valore di input dall'oggetto evento Valore di esempio
textInput stringInputs event.commonEventObject.formInputs.contactName.stringInputs.value[0] Kai O
selectionInput stringInputs Per ottenere il primo o l'unico valore, event.commonEventObject.formInputs.contactType.stringInputs.value[0] Personal
dateTimePicker che accetta solo date. dateInput event.commonEventObject.formInputs.contactBirthdate.dateInput.msSinceEpoch. 1000425600000

Una volta che l'app di chat riceve i dati, può:

  • Per le schede che contengono un menu a selezione multipla, compila o suggerisci elementi in base a ciò che l'utente digita nel menu.
  • Trasferisci i dati a un'altra scheda, in modo che l'utente possa rivedere le proprie informazioni o continuare con la sezione successiva del modulo.
  • Rispondi all'utente per confermare che ha completato correttamente il modulo.

Suggerisci elementi di selezione

Se una scheda contiene un menu a selezione multipla o un menu a discesa che compila gli elementi da un'origine dati esterna, l'app Chat può restituire elementi suggeriti in base a ciò che gli utenti digitano nel menu. Ad esempio, se un utente inizia a digitare Atl per un menu che compila le città degli Stati Uniti, la tua app di chat può suggerire automaticamente Atlanta prima che l'utente finisca di digitare. L'app Chat può suggerire fino a 100 elementi.

Per suggerire e compilare dinamicamente gli elementi in un input di selezione, il widget SelectionInput sulla scheda deve specificare una funzione che esegue query sull'origine dati esterna. Per i menu a selezione multipla, specifica il campo externalDataSource. Per i menu a discesa, specifica il campo remoteDataSource all'interno di un oggetto DataSourceConfig.

Puoi anche configurare il numero di caratteri che un utente digita prima che il menu restituisca i suggerimenti. Per i menu a selezione multipla, imposta il campo multiSelectMinQueryLength. Per i menu a discesa, imposta il campo min_characters_trigger all'interno di DataSourceConfig.

Per restituire gli elementi suggeriti, la funzione deve:

  1. Gestisci un oggetto evento, che l'app Chat riceve quando gli utenti digitano nel menu.
  2. Dall'oggetto evento, recupera il valore digitato dall'utente, che è rappresentato nel campo event.commonEventObject.parameters["autocomplete_widget_query"].
  3. Esegui una query sull'origine dati utilizzando il valore inserito dall'utente per ottenere uno o più SelectionItems da suggerire all'utente.
  4. Restituisci gli elementi suggeriti restituendo l'azione RenderActions con un oggetto modifyCard.

Il seguente esempio di codice mostra come un'app Chat suggerisce dinamicamente elementi nel menu a selezione multipla di una scheda. Quando un utente digita nel menu, la funzione o l'endpoint fornito nel campo externalDataSource del widget esegue una query su un'origine dati esterna e suggerisce elementi che l'utente può selezionare.

Node.js

node/chat/selection-input/index.js
/**
 * Web app that responds to events sent from a Google Chat space.
 *
 * @param {Object} req Request sent from Google Chat space
 * @param {Object} res Response to send back
 */
app.post('/', async (req, res) => {
  // Stores the Google Chat event
  const chatEvent = req.body.chat;

  // Handle user interaction with multiselect.
  if(chatEvent.widgetUpdatedPayload) {
    return res.json(queryContacts(req.body));
  }

  // Replies with a card that contains the multiselect menu.
  return res.json({ hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
    cardsV2: [{
      cardId: "contactSelector",
      card: { sections:[{ widgets: [{
        selectionInput: {
          name: "contacts",
          type: "MULTI_SELECT",
          label: "Selected contacts",
          multiSelectMaxSelectedItems: 3,
          multiSelectMinQueryLength: 1,
          externalDataSource: { function: FUNCTION_URL },
          // Suggested items loaded by default.
          // The list is static here but it could be dynamic.
          items: [getSuggestedContact("3")]
        }
      }]}]}
    }]
  }}}}});
});

/**
 * Get contact suggestions based on text typed by users.
 *
 * @param {Object} event the event object that contains the user's query
 * @return {Object} suggestions
 */
function queryContacts(event) {
  const query = event.commonEventObject.parameters["autocomplete_widget_query"];
  return { action: { modifyOperations: [{ updateWidget: { selectionInputWidgetSuggestions: { suggestions: [
    // The list is static here but it could be dynamic.
    getSuggestedContact("1"), getSuggestedContact("2"), getSuggestedContact("3"), getSuggestedContact("4"), getSuggestedContact("5")
  // Only return items based on the query from the user.
  ].filter(e => !query || e.text.includes(query)) }}}]}};
}

/**
 * Generate a suggested contact given an ID.
 *
 * @param {String} id The ID of the contact to return.
 * @return {Object} The contact formatted as a selection item in the menu.
 */
function getSuggestedContact(id) {
  return {
    value: id,
    startIconUri: "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
    text: "Contact " + id
  };
}

Sostituisci FUNCTION_URL con l'endpoint HTTP che esegue query sull'origine dati esterna.

Python

python/chat/selection-input/main.py
@app.route('/', methods=['POST'])
def post() -> Mapping[str, Any]:
  """Handle requests from Google Chat

  Returns:
      Mapping[str, Any]: The response
  """
  # Stores the Google Chat event
  chatEvent = request.get_json().get('chat')

  # Handle user interaction with multiselect.
  if chatEvent.get('widgetUpdatedPayload') is not None:
    return json.jsonify(query_contacts(request.get_json()))

  # Replies with a card that contains the multiselect menu.
  return json.jsonify({ 'hostAppDataAction': { 'chatDataAction': { 'createMessageAction': {
    'message': { 'cardsV2': [{
      'cardId': "contactSelector",
      'card': { 'sections':[{ 'widgets': [{
        'selectionInput': {
          'name': "contacts",
          'type': "MULTI_SELECT",
          'label': "Selected contacts",
          'multiSelectMaxSelectedItems': 3,
          'multiSelectMinQueryLength': 1,
          'externalDataSource': { 'function': FUNCTION_URL },
          # Suggested items loaded by default.
          # The list is static here but it could be dynamic.
          'items': [get_suggested_contact("3")]
        }
      }]}]}
    }]}
  }}}})


def query_contacts(event: dict) -> dict:
  """Get contact suggestions based on text typed by users.

  Args:
      event (Mapping[str, Any]): The event object that contains the user's query

  Returns:
      Mapping[str, Any]: The response with contact suggestions.
  """
  query = event.get("commonEventObject").get("parameters").get("autocomplete_widget_query")
  return { 'action': { 'modifyOperations': [{ 'updateWidget': { 'selectionInputWidgetSuggestions': { 'suggestions': list(
    filter(lambda e: query is None or query in e["text"], [
      # The list is static here but it could be dynamic.
      get_suggested_contact("1"), get_suggested_contact("2"), get_suggested_contact("3"), get_suggested_contact("4"), get_suggested_contact("5")
    # Only return items based on the query from the user
    ])
  )}}}]}}


def get_suggested_contact(id: str) -> dict:
  """Generate a suggested contact given an ID.

  Args:
      id (str): The ID of the contact to return.

  Returns:
      Mapping[str, Any]: The contact formatted as a selection item in the menu.
  """
  return {
    'value': id,
    'startIconUri': "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
    'text': "Contact " + id
  }

Sostituisci FUNCTION_URL con l'endpoint HTTP che esegue query sull'origine dati esterna.

Java

java/chat/selection-input/src/main/java/com/google/chat/selectionInput/App.java
@SpringBootApplication
@RestController
// Web app that responds to events sent from a Google Chat space.
public class App {
  private static final String FUNCTION_URL = "your-function-url";

  public static void main(String[] args) {
    SpringApplication.run(App.class, args);
  }

  /**
   * Handle requests from Google Chat
   * 
   * @param event the event object sent by Google Chat
   * @return The response to be sent back to Google Chat
   */
  @PostMapping("/")
  @ResponseBody
  public GenericJson onEvent(@RequestBody JsonNode event) throws Exception {
    // Stores the Google Chat event
    JsonNode chatEvent = event.at("/chat");

    // Handle user interaction with multiselect.
    if (!chatEvent.at("/widgetUpdatedPayload").isEmpty()) {
      return queryContacts(event);
    }

    // Replies with a card that contains the multiselect menu.
    Message message = new Message().setCardsV2(List.of(new CardWithId()
      .setCardId("contactSelector")
      .setCard(new GoogleAppsCardV1Card()
        .setSections(List.of(new GoogleAppsCardV1Section().setWidgets(List.of(new GoogleAppsCardV1Widget()
          .setSelectionInput(new GoogleAppsCardV1SelectionInput()
            .setName("contacts")
            .setType("MULTI_SELECT")
            .setLabel("Selected contacts")
            .setMultiSelectMaxSelectedItems(3)
            .setMultiSelectMinQueryLength(1)
            .setExternalDataSource(new GoogleAppsCardV1Action().setFunction(FUNCTION_URL))
            // Suggested items loaded by default.
            // The list is static here but it could be dynamic.
            .setItems(List.of(getSuggestedContact("3")))))))))));

    return new GenericJson() {{
      put("hostAppDataAction", new GenericJson() {{
        put("chatDataAction", new GenericJson() {{
          put("createMessageAction", new GenericJson() {{
            put("message", message);
          }});
        }});
      }});
    }};
  }

  /**
   * Get contact suggestions based on text typed by users.
   *
   * @param event the event object that contains the user's query.
   * @return The response with contact suggestions.
   */
  GenericJson queryContacts(JsonNode event) throws Exception {
    String query = event.at("/commonEventObject/parameters/autocomplete_widget_query").asText();
    List<GoogleAppsCardV1SelectionItem> suggestions = List.of(
      // The list is static here but it could be dynamic.
      getSuggestedContact("1"), getSuggestedContact("2"), getSuggestedContact("3"), getSuggestedContact("4"), getSuggestedContact("5")
    // Only return items based on the query from the user
    ).stream().filter(e -> query == null || e.getText().indexOf(query) > -1).toList();

    return new GenericJson() {{
      put("action", new GenericJson() {{
        put("modifyOperations", List.of(new GenericJson() {{
          put("updateWidget", new GenericJson() {{
            put("selectionInputWidgetSuggestions", new GenericJson() {{
              put("suggestions", suggestions);
            }});
          }});
        }}));
      }});
    }};
  }

  /**
   * Generate a suggested contact given an ID.
   * 
   * @param id The ID of the contact to return.
   * @return The contact formatted as a selection item in the menu.
   */
  GoogleAppsCardV1SelectionItem getSuggestedContact(String id) {
    return new GoogleAppsCardV1SelectionItem()
      .setValue(id)
      .setStartIconUri("https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png")
      .setText("Contact " + id);
  }
}

Sostituisci FUNCTION_URL con l'endpoint HTTP che esegue query sull'origine dati esterna.

Apps Script

Questo esempio invia un messaggio della scheda restituendo JSON della scheda. Puoi anche utilizzare il servizio di schede Apps Script.

apps-script/chat/selection-input/selection-input.gs
/**
* Responds to a Message trigger in Google Chat.
*
* @param {Object} event the event object from Google Chat
* @return {Object} Response from the Chat app.
*/
function onMessage(event) {
  // Replies with a card that contains the multiselect menu.
  return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
    cardsV2: [{
      cardId: "contactSelector",
      card: { sections:[{ widgets: [{
        selectionInput: {
          name: "contacts",
          type: "MULTI_SELECT",
          label: "Selected contacts",
          multiSelectMaxSelectedItems: 3,
          multiSelectMinQueryLength: 1,
          externalDataSource: { function: "queryContacts" },
          // Suggested items loaded by default.
          // The list is static here but it could be dynamic.
          items: [getSuggestedContact("3")]
        }
      }]}]}
    }]
  }}}}};
}

/**
* Get contact suggestions based on text typed by users.
*
* @param {Object} event the event object that contains the user's query
* @return {Object} suggestions
*/
function queryContacts(event) {
  const query = event.commonEventObject.parameters["autocomplete_widget_query"];
  return { action: { modifyOperations: [{ updateWidget: { selectionInputWidgetSuggestions: { suggestions: [
    // The list is static here but it could be dynamic.
    getSuggestedContact("1"), getSuggestedContact("2"), getSuggestedContact("3"), getSuggestedContact("4"), getSuggestedContact("5")
  // Only return items based on the query from the user.
  ].filter(e => !query || e.text.includes(query)) }}}]}};
}

/**
* Generate a suggested contact given an ID.
*
* @param {String} id The ID of the contact to return.
* @return {Object} The contact formatted as a selection item in the menu.
*/
function getSuggestedContact(id) {
  return {
    value: id,
    startIconUri: "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
    text: "Contact " + id
  };
}

Trasferire dati su un'altra scheda

Dopo che un utente ha inviato informazioni da una carta, potrebbe essere necessario restituire carte aggiuntive per eseguire una delle seguenti operazioni:

  • Aiuta gli utenti a compilare moduli più lunghi creando sezioni distinte.
  • Consenti agli utenti di visualizzare l'anteprima e confermare le informazioni della scheda iniziale, in modo che possano rivedere le risposte prima dell'invio.
  • Compila dinamicamente le parti rimanenti del modulo. Ad esempio, per invitare gli utenti a creare un appuntamento, un'app di chat potrebbe mostrare una scheda iniziale che richiede il motivo dell'appuntamento e poi compilare un'altra scheda che fornisce gli orari disponibili in base al tipo di appuntamento.

Per trasferire l'input di dati dalla scheda iniziale, puoi creare il widget button con actionParameters che contengono name del widget e il valore inserito dall'utente, come mostrato nell'esempio seguente:

Node.js

node/chat/contact-form-app/index.js
{ buttonList: { buttons: [{
  text: "SUBMIT",
  onClick: { action: {
    function: FUNCTION_URL,
    parameters: [
      { key: "actionName", value: "submitDialog" },
      // Pass input values as parameters for last dialog step (submission)
      { key: "contactName", value: name },
      { key: "contactBirthdate", value: birthdate },
      { key: "contactType", value: type }
    ]
  }}
}]}}

Sostituisci FUNCTION_URL con l'endpoint HTTP che gestisce i clic sui pulsanti.

Python

python/chat/contact-form-app/main.py
{ 'buttonList': { 'buttons': [{
  'text': "SUBMIT",
  'onClick': { 'action': {
    'function': FUNCTION_URL,
    'parameters': [
      { 'key': "actionName", 'value': "submitDialog" },
      # Pass input values as parameters for last dialog step (submission)
      { 'key': "contactName", 'value': name },
      { 'key': "contactBirthdate", 'value': birthdate },
      { 'key': "contactType", 'value': type }
    ]
  }}
}]}}

Sostituisci FUNCTION_URL con l'endpoint HTTP che gestisce i clic sui pulsanti.

Java

java/chat/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(FUNCTION_URL)
      .setParameters(List.of(
        new GoogleAppsCardV1ActionParameter().setKey("actionName").setValue("submitDialog"),
        // Pass input values as parameters for last dialog step (submission)
        new GoogleAppsCardV1ActionParameter().setKey("contactName").setValue(name),
        new GoogleAppsCardV1ActionParameter().setKey("contactBirthdate").setValue(birthdate),
        new GoogleAppsCardV1ActionParameter().setKey("contactType").setValue(type))))))))))));

Sostituisci FUNCTION_URL con l'endpoint HTTP che gestisce i clic sui pulsanti.

Apps Script

Questo esempio invia un messaggio della scheda restituendo JSON della scheda. Puoi anche utilizzare il servizio di schede Apps Script.

apps-script/chat/contact-form-app/Code.gs
{ buttonList: { buttons: [{
  text: "SUBMIT",
  onClick: { action: {
    function: "submitDialog",
    // Pass input values as parameters for last dialog step (submission)
    parameters: [
      { key: "contactName", value: name },
      { key: "contactBirthdate", value: birthdate },
      { key: "contactType", value: type }
    ]
  }}
}]}}

Quando un utente fa clic sul pulsante, l'app Chat riceve un oggetto evento da cui puoi ricevere dati.

Rispondere all'invio di un modulo

Dopo aver ricevuto i dati da un messaggio o una finestra di dialogo della scheda, l'app di Chat risponde confermando la ricezione o restituendo un errore.

Nell'esempio seguente, un'app di chat invia un messaggio di testo per confermare di aver ricevuto correttamente un modulo inviato da un messaggio della scheda.

Node.js

node/chat/contact-form-app/index.js
return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
  text: "✅ " + event.commonEventObject.parameters["contactName"] + " has been added to your contacts."
}}}}};

Python

python/chat/contact-form-app/main.py
return { 'hostAppDataAction': { 'chatDataAction': { 'createMessageAction': { 'message': {
  'text': "✅ " + event.get('commonEventObject').get('parameters')["contactName"] + " has been added to your contacts."
}}}}}

Java

java/chat/contact-form-app/src/main/java/com/google/chat/contact/App.java
return new GenericJson() {{
  put("hostAppDataAction", new GenericJson() {{
    put("chatDataAction", new GenericJson() {{
      put("createMessageAction", new GenericJson() {{
        put("message", new Message()
          .setText( "✅ " + event.at("/commonEventObject/parameters/contactName").asText() +
                    " has been added to your contacts."));
      }});
    }});
  }});
}};

Apps Script

Questo esempio invia un messaggio della scheda restituendo JSON della scheda. Puoi anche utilizzare il servizio di schede Apps Script.

apps-script/chat/contact-form-app/Code.gs
return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
  text: "✅ " + event.commonEventObject.parameters["contactName"] + " has been added to your contacts."
}}}}};

Per elaborare e chiudere una finestra di dialogo, restituisci un oggetto RenderActions che specifica se vuoi inviare un messaggio di conferma, aggiornare il messaggio o la scheda originale o semplicemente chiudere la finestra di dialogo. Per la procedura, vedi Chiudere una finestra di dialogo.

Risoluzione dei problemi

Questa sezione fornisce i passaggi per la risoluzione dei problemi relativi a codici di errore e comportamenti di runtime specifici durante l'interazione con le finestre di dialogo in Chat.

Le interazioni con le finestre di dialogo restituiscono l'errore "Errore non specificato durante il tentativo di richiamare il componente aggiuntivo"

Quando interagisci con una finestra di dialogo, se visualizzi log degli errori con il messaggio "Errore non specificato durante la chiamata del componente aggiuntivo" e il codice 13, in genere indica un errore interno o che l'endpoint HTTP dell'app Chat non è riuscito a elaborare la richiesta o a restituire una risposta valida.

Per risolvere questo errore:

  • Controlla i log dell'endpoint HTTP per verificare la presenza di eccezioni non gestite o arresti anomali.
  • Verifica che l'endpoint risponda alle richieste entro 30 secondi. Se l'endpoint impiega più di 30 secondi per essere eseguito, Chat non può elaborare la risposta e l'interazione non va a buon fine. Per maggiori dettagli, consulta Limiti di frequenza e best practice.
  • Assicurati che l'endpoint restituisca una risposta valida. Per gli invii di dialoghi, l'endpoint deve restituire un oggetto RenderActions nel formato JSON corretto. Se la risposta non è formattata correttamente o non contiene i campi obbligatori, l'interazione con la finestra di dialogo potrebbe non riuscire.

Quando un'app Google Chat o una scheda restituisce un errore, l'interfaccia di Chat mostra il messaggio "Si è verificato un problema". o "Impossibile elaborare la richiesta". A volte l'interfaccia utente di Chat non mostra alcun messaggio di errore, ma l'app o la scheda Chat produce un risultato imprevisto; ad esempio, un messaggio della scheda potrebbe non essere visualizzato.

Anche se nell'interfaccia utente di Chat potrebbe non essere visualizzato un messaggio di errore, sono disponibili messaggi di errore descrittivi e dati di log per aiutarti a correggere gli errori quando la registrazione degli errori per le app di chat è attivata. Per assistenza nella visualizzazione, nel debug e nella correzione degli errori, consulta Risolvere e correggere gli errori di Google Chat.

App di chat che non sono componenti aggiuntivi: leggi i dati dei moduli inseriti dagli utenti sulle schede

La seguente documentazione si applica alle app di Chat che non sono componenti aggiuntivi di Google Workspace. Per eseguire la migrazione di un'app di Chat che non è un componente aggiuntivo, vedi Convertire un'app Google Chat in un componente aggiuntivo di Google Workspace.

Creare moduli utilizzando le schede

Per un esempio di app di chat che non è un componente aggiuntivo che utilizza un modulo di contatto con un input di testo, un selettore di data e ora e un input di selezione, vedi il seguente codice:

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
        }
      ]
    }
  }
];

Ricevere dati dai widget interattivi

Ogni volta che gli utenti fanno clic su un pulsante, le app di chat che non sono componenti aggiuntivi ricevono un evento di interazione a seconda della posizione del pulsante:

  • Se il pulsante si trova in un messaggio o in una finestra di dialogo, le app di chat che non sono componenti aggiuntivi ricevono un evento di interazione CARD_CLICKED che contiene informazioni sull'interazione. Il payload degli eventi di interazione CARD_CLICKED contiene un oggetto common.formInputs (event.common.formInputs) con tutti i valori inseriti dall'utente.

    Puoi recuperare i valori dall'oggetto common.formInputs.WIDGET_NAME, dove WIDGET_NAME è il campo name che hai specificato per il widget. I valori vengono restituiti come un tipo di dati specifico per il widget (rappresentato come un oggetto Inputs).

    Di seguito viene mostrata una parte di un evento di interazione CARD_CLICKED in cui un utente ha inserito valori per ogni 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 il pulsante si trova in una home page, le app di chat che non sono componenti aggiuntivi ricevono un SUBMIT_FORM evento di interazione. Il payload dell'evento di interazione contiene un commonEventObject.formInputs oggetto (event.commonEventObject.formInputs) con tutti i valori inseriti dall'utente.

    Puoi recuperare i valori dall'oggetto commonEventObject.formInputs.WIDGET_NAME, dove WIDGET_NAME è il campo name che hai specificato per il widget. I valori vengono restituiti come un tipo di dati specifico per il widget (rappresentato come un oggetto Inputs).

    Di seguito viene mostrata una parte di un evento di interazione SUBMIT_FORM in cui un utente ha inserito valori per ogni 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"]
        }}}
      }}
    }
    

Per ricevere i dati, un'app di chat che non è un componente aggiuntivo gestisce l'evento di interazione per ottenere i valori inseriti dagli utenti nei widget. La tabella seguente mostra come ottenere il valore per un determinato widget di input del modulo. Per ogni widget, la tabella mostra il tipo di dati accettato dal widget, dove viene memorizzato il valore nell'evento di interazione e un valore di esempio.

Widget di input del modulo Tipo di dati di input Valore di input dall'evento di interazione Valore di esempio
textInput stringInputs event.common.formInputs.contactName.stringInputs.value[0] Kai O
selectionInput stringInputs Per ottenere il primo o l'unico valore, event.common.formInputs.contactType.stringInputs.value[0] Personal
dateTimePicker che accetta solo date. dateInput event.common.formInputs.contactBirthdate.dateInput.msSinceEpoch. 1000425600000

Trasferire dati su un'altra scheda

Per trasferire i dati inseriti dalla scheda iniziale in un'app di chat che non è un componente aggiuntivo, crea il widget button con actionParameters che contengono name del widget e il valore inserito dall'utente, come mostrato nell'esempio seguente:

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 un utente fa clic sul pulsante, l'app Chat che non è un componente aggiuntivo riceve un evento di interazione CARD_CLICKED da cui puoi ricevere dati.

Rispondere all'invio di un modulo

Nell'esempio seguente, un'app di chat che non è un componente aggiuntivo invia un messaggio di testo per confermare di aver ricevuto correttamente un modulo inviato da un messaggio di dialogo o scheda:

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
    }}
  }};
}

Per elaborare e chiudere una finestra di dialogo in un'app di chat che non è un componente aggiuntivo, restituisci un oggetto ActionResponse che specifica se vuoi inviare un messaggio di conferma, aggiornare il messaggio o la scheda originale o semplicemente chiudere la finestra di dialogo. Per la procedura, vedi Chiudere una finestra di dialogo.