Respuestas de selección visual

Usa una respuesta de selección visual si deseas que el usuario seleccione una de varias opciones para continuar con tu acción. Puedes usar los siguientes tipos de respuesta de selección visual como parte de un mensaje:

  • Cómo mostrar en lista
  • Recopilación
  • Explorar colección

Cuando definas una respuesta de selección visual, usa un candidata con la función de superficie RICH_RESPONSE para que Asistente de Google solo muestre la respuesta en dispositivos compatibles. Solo puedes usar una respuesta enriquecida por objeto content en un mensaje.

Agrega una respuesta de selección visual

Las respuestas de selección visual usan el relleno de ranuras en una escena para presentar opciones que un usuario puede seleccionar y controlar un elemento seleccionado. Cuando los usuarios seleccionan un elemento, Asistente pasa el valor del elemento seleccionado a tu webhook como argumento. Luego, en el valor del argumento, recibirás la clave del elemento seleccionado.

Antes de poder usar una respuesta de selección visual, debes definir un tipo que represente la respuesta que un usuario seleccionará más adelante. En tu webhook, anula ese tipo con el contenido que deseas mostrar para la selección.

Para agregar una respuesta de selección visual a una escena en Actions Builder, sigue estos pasos:

  1. En la escena, agrega una ranura a la sección Relleno de ranuras.
  2. Selecciona un tipo definido con anterioridad para tu respuesta de selección visual y asígnale un nombre. El webhook usa este nombre de espacio para hacer referencia al tipo más adelante.
  3. Marca la casilla Llamar a tu webhook y proporciona el nombre del controlador de eventos en el webhook que deseas usar para la respuesta de selección visual.
  4. Marca la casilla Enviar mensajes.
  5. En el mensaje, proporciona el contenido JSON o YAML adecuado según la respuesta de selección visual que quieras mostrar.
  6. En tu webhook, sigue los pasos que se indican en Cómo manejar los elementos seleccionados.

Consulta las secciones lista, colección y exploración de colecciones a continuación para conocer las propiedades del mensaje disponibles y ejemplos de anulación de tipos.

Controla los elementos seleccionados

Las respuestas de selección visual requieren que controles la selección de un usuario en tu código de webhook. Cuando el usuario selecciona algo de una respuesta de selección visual, Asistente de Google llena el espacio con ese valor.

En el siguiente ejemplo, el código de webhook recibe y almacena la opción seleccionada en una variable:

Node.js

app.handle('Option', conv => {
  // Note: 'prompt_option' is the name of the slot.
  const selectedOption = conv.session.params.prompt_option;
  conv.add(`You selected ${selectedOption}.`);
});

JSON

{
  "responseJson": {
    "session": {
      "id": "session_id",
      "params": {
        "prompt_option": "ITEM_1"
      }
    },
    "prompt": {
      "override": false,
      "firstSimple": {
        "speech": "You selected ITEM_1.",
        "text": "You selected ITEM_1."
      }
    }
  }
}

Cómo mostrar en lista

Ejemplo de una respuesta de selección de lista en un dispositivo móvil

Una lista les presenta a los usuarios una lista vertical de varios elementos y les permite seleccionar uno mediante la entrada táctil o de voz. Cuando un usuario selecciona un elemento de la lista, Asistente genera una consulta de usuario (burbuja de chat) que contiene el título del elemento de la lista.

Son útiles para casos en los que es importante desambiguar las opciones o cuando el usuario debe elegir entre las opciones que se deben analizar en su totalidad. Por ejemplo, ¿a qué "Peter" necesitas hablar? ¿Peter Jons o Peter Hans?

Las listas deben contener un mínimo de 2 y un máximo de 30. La cantidad de elementos que se muestra inicialmente depende del dispositivo del usuario, y el número de inicio común es de 10 elementos.

Cómo crear una lista

Cuando creas una lista, tu mensaje solo contiene claves para cada elemento que un usuario puede seleccionar. En tu webhook, debes definir los elementos que corresponden a esas claves en función del tipo Entry.

Los elementos de lista definidos como objetos Entry tienen las siguientes características de visualización:

  • Título
    • Fuente y tamaño de fuente fijos
    • Longitud máxima: 1 línea (truncada con puntos suspensivos...)
    • Debe ser único (para admitir la selección por voz)
  • Descripción (opcional)
    • Fuente y tamaño de fuente fijos
    • Longitud máxima: 2 líneas (truncadas con puntos suspensivos...)
  • Imagen (opcional)
    • Tamaño: 48 x 48 px

Las respuestas de selección visual requieren que anules un tipo por su nombre de ranura mediante un tipo de entorno de ejecución en el modo TYPE_REPLACE. En el controlador de eventos del webhook, haz referencia al tipo que se debe anular por su nombre de espacio (definido en Agrega respuestas de selección) en la propiedad name.

Después de reemplazar un tipo, el tipo resultante representa la lista de elementos que el usuario puede elegir desde ese Asistente.

Propiedades

El tipo de respuesta de lista tiene las siguientes propiedades:

Propiedad Tipo Requisito Descripción
items array de ListItem Obligatorio Representa un elemento de la lista que los usuarios pueden seleccionar. Cada ListItem contiene una clave que se asigna a un tipo al que se hace referencia para el elemento de la lista.
title string Opcional Título de texto sin formato de la lista, restringido a una sola línea Si no se especifica un título, se contraerá la altura de la tarjeta.
subtitle string Opcional Subtítulo de texto sin formato de la lista.

Código de muestra

En los siguientes ejemplos, se define el contenido del mensaje en el código de webhook o en el webhookResponse de JSON. Sin embargo, también puedes definir el contenido del mensaje en Actions Builder (como YAML o JSON).

Node.js

const ASSISTANT_LOGO_IMAGE = new Image({
  url: 'https://developers.google.com/assistant/assistant_96.png',
  alt: 'Google Assistant logo'
});

app.handle('List', conv => {
  conv.add('This is a list.');

  // Override type based on slot 'prompt_option'
  conv.session.typeOverrides = [{
    name: 'prompt_option',
    mode: 'TYPE_REPLACE',
    synonym: {
      entries: [
        {
          name: 'ITEM_1',
          synonyms: ['Item 1', 'First item'],
          display: {
             title: 'Item #1',
             description: 'Description of Item #1',
             image: ASSISTANT_LOGO_IMAGE,
                }
        },
        {
          name: 'ITEM_2',
          synonyms: ['Item 2', 'Second item'],
          display: {
             title: 'Item #2',
             description: 'Description of Item #2',
             image: ASSISTANT_LOGO_IMAGE,
                }
        },
        {
          name: 'ITEM_3',
          synonyms: ['Item 3', 'Third item'],
          display: {
             title: 'Item #3',
             description: 'Description of Item #3',
             image: ASSISTANT_LOGO_IMAGE,
                }
        },
        {
          name: 'ITEM_4',
          synonyms: ['Item 4', 'Fourth item'],
          display: {
             title: 'Item #4',
             description: 'Description of Item #4',
             image: ASSISTANT_LOGO_IMAGE,
                }
        },
        ]
    }
  }];

  // Define prompt content using keys
  conv.add(new List({
    title: 'List title',
    subtitle: 'List subtitle',
    items: [
      {
        key: 'ITEM_1'
      },
      {
        key: 'ITEM_2'
      },
      {
        key: 'ITEM_3'
      },
      {
        key: 'ITEM_4'
      }
    ],
  }));
});

JSON

{
 "responseJson": {
   "session": {
     "id": "session_id",
     "params": {},
     "typeOverrides": [
       {
         "name": "prompt_option",
         "synonym": {
           "entries": [
             {
               "name": "ITEM_1",
               "synonyms": [
                 "Item 1",
                 "First item"
               ],
               "display": {
                 "title": "Item #1",
                 "description": "Description of Item #1",
                 "image": {
                   "alt": "Google Assistant logo",
                   "height": 0,
                   "url": "https://developers.google.com/assistant/assistant_96.png",
                   "width": 0
                 }
               }
             },
             {
               "name": "ITEM_2",
               "synonyms": [
                 "Item 2",
                 "Second item"
               ],
               "display": {
                 "title": "Item #2",
                 "description": "Description of Item #2",
                 "image": {
                   "alt": "Google Assistant logo",
                   "height": 0,
                   "url": "https://developers.google.com/assistant/assistant_96.png",
                   "width": 0
                 }
               }
             },
             {
               "name": "ITEM_3",
               "synonyms": [
                 "Item 3",
                 "Third item"
               ],
               "display": {
                 "title": "Item #3",
                 "description": "Description of Item #3",
                 "image": {
                   "alt": "Google Assistant logo",
                   "height": 0,
                   "url": "https://developers.google.com/assistant/assistant_96.png",
                   "width": 0
                 }
               }
             },
             {
               "name": "ITEM_4",
               "synonyms": [
                 "Item 4",
                 "Fourth item"
               ],
               "display": {
                 "title": "Item #4",
                 "description": "Description of Item #4",
                 "image": {
                   "alt": "Google Assistant logo",
                   "height": 0,
                   "url": "https://developers.google.com/assistant/assistant_96.png",
                   "width": 0
                 }
               }
             }
           ]
         },
         "typeOverrideMode": "TYPE_REPLACE"
       }
     ]
   },
   "prompt": {
     "override": false,
     "content": {
       "list": {
         "items": [
           {
             "key": "ITEM_1"
           },
           {
             "key": "ITEM_2"
           },
           {
             "key": "ITEM_3"
           },
           {
             "key": "ITEM_4"
           }
         ],
         "subtitle": "List subtitle",
         "title": "List title"
       }
     },
     "firstSimple": {
       "speech": "This is a list.",
       "text": "This is a list."
     }
   }
 }
}

Recopilación

Una colección se desplaza horizontalmente y permite a los usuarios seleccionar un elemento con la entrada táctil o de voz. En comparación con las listas, las colecciones tienen mosaicos grandes y permiten contenido más enriquecido. Los mosaicos que conforman una colección son similares a la tarjeta básica con imagen. Cuando los usuarios seleccionan un elemento de una colección, Asistente genera una consulta de usuario (burbuja de chat) que contiene el título del elemento.

Las colecciones son útiles cuando se le presentan varias opciones al usuario, pero no se requiere una comparación directa entre ellas (en comparación con las listas). En general, se recomienda usar listas en lugar de colecciones, ya que son más fáciles de analizar y de interactuar con la voz.

Las colecciones deben contener un mínimo de 2 y un máximo de 10 mosaicos. En dispositivos con pantalla, los usuarios pueden deslizarse hacia la izquierda o la derecha para desplazarse por las tarjetas de una colección antes de seleccionar un elemento.

Cómo crear una colección

Cuando creas una colección, tu mensaje solo contiene claves para cada elemento que un usuario puede seleccionar. En el webhook, debes definir los elementos que corresponden a esas claves según el tipo Entry.

Los elementos de la colección definidos como objetos Entry tienen las siguientes características de visualización:

  • Imagen (opcional)
    • La imagen debe tener 128 dp de alto x 232 dp de ancho
    • Si la relación de aspecto de la imagen no coincide con el cuadro de límite de la imagen, entonces la imagen se centra con barras en ambos lados.
    • Si el vínculo de la imagen está roto, se usa una imagen de marcador de posición.
  • Título (obligatorio)
    • El texto sin formato no es compatible con Markdown. Las mismas opciones de formato que la respuesta enriquecida de la tarjeta básica
    • La altura de la tarjeta se contrae si no se especifica un título.
    • Debe ser único (para admitir la selección por voz)
  • Descripción (opcional)
    • El texto sin formato no es compatible con Markdown. Las mismas opciones de formato que la respuesta enriquecida de la tarjeta básica

Las respuestas de selección visual requieren que anules un tipo por su nombre de ranura mediante un tipo de entorno de ejecución en el modo TYPE_REPLACE. En el controlador de eventos del webhook, haz referencia al tipo que se debe anular por su nombre de espacio (definido en Agrega respuestas de selección) en la propiedad name.

Después de reemplazar un tipo, el tipo resultante representa la colección de elementos que el usuario puede elegir de ese Asistente.

Propiedades

El tipo de respuesta de colección tiene las siguientes propiedades:

Propiedad Tipo Requisito Descripción
items array de CollectionItem Obligatorio Representa un elemento de la colección que los usuarios pueden seleccionar. Cada CollectionItem contiene una clave que se asigna a un tipo al que se hace referencia para el elemento de la colección.
title string Opcional Título de texto sin formato de la colección Los títulos deben ser únicos en una colección para admitir la selección de voz.
subtitle string Opcional Subtítulo de texto sin formato de la colección.
image_fill ImageFill Opcional Es el borde entre la tarjeta y el contenedor de la imagen que se usará cuando la relación de aspecto de la imagen no coincida.

Código de muestra

En los siguientes ejemplos, se define el contenido del mensaje en el código de webhook o en la respuesta de webhook de JSON. Sin embargo, también puedes definir el contenido del mensaje en Actions Builder (como YAML o JSON).

Node.js

const ASSISTANT_LOGO_IMAGE = new Image({
  url: 'https://developers.google.com/assistant/assistant_96.png',
  alt: 'Google Assistant logo'
});

app.handle('Collection', conv => {
  conv.add("This is a collection.");

  // Override type based on slot 'prompt_option'
  conv.session.typeOverrides = [{
    name: 'prompt_option',
    mode: 'TYPE_REPLACE',
    synonym: {
      entries: [
        {
          name: 'ITEM_1',
          synonyms: ['Item 1', 'First item'],
          display: {
             title: 'Item #1',
             description: 'Description of Item #1',
             image: ASSISTANT_LOGO_IMAGE,
                }
        },
        {
          name: 'ITEM_2',
          synonyms: ['Item 2', 'Second item'],
          display: {
             title: 'Item #2',
             description: 'Description of Item #2',
             image: ASSISTANT_LOGO_IMAGE,
                }
        },
        {
          name: 'ITEM_3',
          synonyms: ['Item 3', 'Third item'],
          display: {
             title: 'Item #3',
             description: 'Description of Item #3',
             image: ASSISTANT_LOGO_IMAGE,
                }
        },
        {
          name: 'ITEM_4',
          synonyms: ['Item 4', 'Fourth item'],
          display: {
             title: 'Item #4',
             description: 'Description of Item #4',
             image: ASSISTANT_LOGO_IMAGE,
                }
        },
        ]
    }
  }];

  // Define prompt content using keys
  conv.add(new Collection({
    title: 'Collection Title',
    subtitle: 'Collection subtitle',
    items: [
      {
        key: 'ITEM_1'
      },
      {
        key: 'ITEM_2'
      },
      {
        key: 'ITEM_3'
      },
      {
        key: 'ITEM_4'
      }
    ],
  }));
});

JSON

{
  "responseJson": {
    "session": {
      "id": "ABwppHHz--uQEEy3CCOANyB0J58oF2Yw5JEX0oXwit3uxDlRwzbEIK3Bcz7hXteE6hWovrLX9Ahpqu8t-jYnQRFGpAUqSuYjZ70",
      "params": {},
      "typeOverrides": [
        {
          "name": "prompt_option",
          "synonym": {
            "entries": [
              {
                "name": "ITEM_1",
                "synonyms": [
                  "Item 1",
                  "First item"
                ],
                "display": {
                  "title": "Item #1",
                  "description": "Description of Item #1",
                  "image": {
                    "alt": "Google Assistant logo",
                    "height": 0,
                    "url": "https://developers.google.com/assistant/assistant_96.png",
                    "width": 0
                  }
                }
              },
              {
                "name": "ITEM_2",
                "synonyms": [
                  "Item 2",
                  "Second item"
                ],
                "display": {
                  "title": "Item #2",
                  "description": "Description of Item #2",
                  "image": {
                    "alt": "Google Assistant logo",
                    "height": 0,
                    "url": "https://developers.google.com/assistant/assistant_96.png",
                    "width": 0
                  }
                }
              },
              {
                "name": "ITEM_3",
                "synonyms": [
                  "Item 3",
                  "Third item"
                ],
                "display": {
                  "title": "Item #3",
                  "description": "Description of Item #3",
                  "image": {
                    "alt": "Google Assistant logo",
                    "height": 0,
                    "url": "https://developers.google.com/assistant/assistant_96.png",
                    "width": 0
                  }
                }
              },
              {
                "name": "ITEM_4",
                "synonyms": [
                  "Item 4",
                  "Fourth item"
                ],
                "display": {
                  "title": "Item #4",
                  "description": "Description of Item #4",
                  "image": {
                    "alt": "Google Assistant logo",
                    "height": 0,
                    "url": "https://developers.google.com/assistant/assistant_96.png",
                    "width": 0
                  }
                }
              }
            ]
          },
          "typeOverrideMode": "TYPE_REPLACE"
        }
      ]
    },
    "prompt": {
      "override": false,
      "content": {
        "collection": {
          "imageFill": "UNSPECIFIED",
          "items": [
            {
              "key": "ITEM_1"
            },
            {
              "key": "ITEM_2"
            },
            {
              "key": "ITEM_3"
            },
            {
              "key": "ITEM_4"
            }
          ],
          "subtitle": "Collection subtitle",
          "title": "Collection Title"
        }
      },
      "firstSimple": {
        "speech": "This is a collection.",
        "text": "This is a collection."
      }
    }
  }
}

Explorar colección

Al igual que una colección, la exploración de colecciones es una respuesta enriquecida que permite a los usuarios desplazarse por las tarjetas de opciones. La exploración de colecciones está diseñada específicamente para contenido web y abre la tarjeta seleccionada en un navegador web (o en un navegador de AMP si todas las tarjetas están habilitadas para AMP).

Las respuestas de exploración de la colección contienen un mínimo de 2 y un máximo de 10 mosaicos. En dispositivos con pantalla, los usuarios pueden deslizar el dedo hacia arriba o abajo para desplazarse por las tarjetas antes de seleccionar un elemento.

Cómo crear una exploración de colecciones

Cuando crees una exploración de colección, considera cómo interactuarán los usuarios con este mensaje. Cada colección que explora item abre su URL definida, por lo que debes proporcionar detalles útiles al usuario.

Los elementos de navegación de la colección tienen las siguientes características de visualización:

  • Imagen (opcional)
    • Se fuerza la imagen a 128 dp de alto x 232 dp de ancho.
    • Si la relación de aspecto de la imagen no coincide con el cuadro de límite de la imagen, la imagen se centrará con barras en ambos lados o en la parte inferior y superior. El color de las barras se determina según la propiedad ImageFill de navegación de la colección.
    • Si un vínculo de imagen está roto, se usa un marcador de posición en su lugar.
  • Título (obligatorio)
  • Descripción (opcional)
  • Pie de página (opcional)
    • Texto sin formato; no se admite Markdown.

Propiedades

El tipo de respuesta de navegación de colecciones tiene las siguientes propiedades:

Propiedad Tipo Requisito Descripción
item objeto Obligatorio Representa un elemento de la colección que los usuarios pueden seleccionar.
image_fill ImageFill Opcional Es el borde entre la tarjeta y el contenedor de la imagen que se usará cuando la relación de aspecto de la imagen no coincida.

La navegación de colección item tiene las siguientes propiedades:

Propiedad Tipo Requisito Descripción
title string Obligatorio Título de texto sin formato del elemento de la colección.
description string Opcional Descripción del elemento de la colección.
footer string Opcional Texto de pie de página del elemento de la colección, que se muestra debajo de la descripción
image Image Opcional Imagen que se muestra para el elemento de la colección.
openUriAction OpenUrl Obligatorio URI que se abrirá cuando se seleccione el elemento de la colección.

Código de muestra

En los siguientes ejemplos, se define el contenido del mensaje en el código de webhook o en la respuesta de webhook de JSON. Sin embargo, también puedes definir el contenido del mensaje en Actions Builder (como YAML o JSON).

YAML

candidates:
  - first_simple:
      variants:
        - speech: This is a collection browse.
    content:
      collection_browse:
        items:
          - title: Item #1
            description: Description of Item #1
            footer: Footer of Item #1
            image:
              url: 'https://developers.google.com/assistant/assistant_96.png'
            open_uri_action:
              url: 'https://www.example.com'
          - title: Item #2
            description: Description of Item #2
            footer: Footer of Item #2
            image:
              url:  'https://developers.google.com/assistant/assistant_96.png'
            open_uri_action:
              url: 'https://www.example.com'
        image_fill: WHITE

JSON

{
 "candidates": [
   {
     "firstSimple": {
       "speech": "This is a collection browse.",
       "text": "This is a collection browse."
     },
     "content": {
       "collectionBrowse": {
         "items": [
           {
             "title": "Item #1",
             "description": "Description of Item #1",
             "footer": "Footer of Item #1",
             "image": {
               "url": "https://developers.google.com/assistant/assistant_96.png"
             },
             "openUriAction": {
               "url": "https://www.example.com"
             }
           },
           {
             "title": "Item #2",
             "description": "Description of Item #2",
             "footer": "Footer of Item #2",
             "image": {
               "url": "https://developers.google.com/assistant/assistant_96.png"
             },
             "openUriAction": {
               "url": "https://www.example.com"
             }
           }
         ],
         "imageFill": "WHITE"
       }
     }
   }
 ]
}

Node.js

// Collection Browse
app.handle('collectionBrowse', (conv) => {
  conv.add('This is a collection browse.');
  conv.add(new CollectionBrowse({
    'imageFill': 'WHITE',
    'items':
      [
        {
          'title': 'Item #1',
          'description': 'Description of Item #1',
          'footer': 'Footer of Item #1',
          'image': {
            'url': 'https://developers.google.com/assistant/assistant_96.png'
          },
          'openUriAction': {
            'url': 'https://www.example.com'
          }
        },
        {
          'title': 'Item #2',
          'description': 'Description of Item #2',
          'footer': 'Footer of Item #2',
          'image': {
            'url': 'https://developers.google.com/assistant/assistant_96.png'
          },
          'openUriAction': {
            'url': 'https://www.example.com'
          }
        }
      ]
  }));
});

JSON

{
  "responseJson": {
    "session": {
      "id": "session_id",
      "params": {},
      "languageCode": ""
    },
    "prompt": {
      "override": false,
      "content": {
        "collectionBrowse": {
          "imageFill": "WHITE",
          "items": [
            {
              "title": "Item #1",
              "description": "Description of Item #1",
              "footer": "Footer of Item #1",
              "image": {
                "url": "https://developers.google.com/assistant/assistant_96.png"
              },
              "openUriAction": {
                "url": "https://www.example.com"
              }
            },
            {
              "title": "Item #2",
              "description": "Description of Item #2",
              "footer": "Footer of Item #2",
              "image": {
                "url": "https://developers.google.com/assistant/assistant_96.png"
              },
              "openUriAction": {
                "url": "https://www.example.com"
              }
            }
          ]
        }
      },
      "firstSimple": {
        "speech": "This is a collection browse.",
        "text": "This is a collection browse."
      }
    }
  }
}