Manifiestos para complementos de Google Workspace

Un complemento usa un archivo manifest para configurar ciertos detalles sobre la app y su funcionamiento.

En esta documentación, se abordan los detalles para configurar un manifiesto para un complemento de Google Workspace.

Estructura del manifiesto para complementos de Google Workspace

Los complementos de Google Workspace usan el archivo de manifiesto para definir varios aspectos de su apariencia y comportamiento.

Las propiedades del manifiesto de los complementos de Google Workspace se organizan en la sección addOns de la estructura del objeto del manifiesto.

Manifiestos para Google Chat

Si tu complemento de Google Workspace extiende Google Chat, debes configurar una app de Google Chat habilitando y configurando la API de Google Chat en la consola de Google Cloud.

Los parámetros de configuración comunes del manifiesto (incluidos addons.common) se ignoran en Chat. En lugar de usar el manifiesto del complemento, usas la API de Chat para configurar los siguientes parámetros de configuración de Chat:

Si compilaste el complemento en Apps Script, también debes agregar o actualizar los siguientes objetos en tu manifiesto:

Si deseas conocer los pasos para configurar Chat en un complemento, consulta Cómo configurar una app de Google Chat.

Ejemplo de configuración del manifiesto de complementos de Google Workspace

En la siguiente muestra de manifiesto, se muestra la sección de un archivo de manifiesto que define un complemento de Google Workspace, incluidos los siguientes aspectos:

  • La sección addOns.common del manifiesto define el nombre, la URL del logotipo, los colores y otros parámetros de configuración generales independientes del host para el complemento.
  • El manifiesto define una página principal común, pero también define páginas principales específicas de Calendario, Drive, Documentos, Hojas de cálculo y Presentaciones. Gmail usa la página principal predeterminada.
  • La configuración del manifiesto de ejemplo habilita lo siguiente:
  • El campo oauthScopes establece los alcances de autorización para el proyecto (por lo general, es obligatorio para los complementos).
  • (Solo para Apps Script) El campo urlFetchWhitelist es un campo que garantiza que los extremos recuperados coincidan con una lista especificada de prefijos de URLs HTTPS. Para obtener más información, consulta Cómo incluir URLs en la lista de entidades permitidas.

Los vínculos del ejemplo dirigen a las descripciones de ese campo en la documentación de referencia correspondiente del manifiesto para los complementos de Apps Script y HTTP de Google Workspace.

Apps Script

{
  "addOns": {
    "calendar": {
      "createSettingsUrlFunction": "getConferenceSettingsPageUrl",
      "conferenceSolution": [{
        "id": "my-video-conf",
        "logoUrl": "https://lh3.googleusercontent.com/...",
        "name": "My Video Conference",
        "onCreateFunction": "onCreateMyVideoConference"
      }, {
        "id": "my-streamed-conf",
        "logoUrl": "https://lh3.googleusercontent.com/...",
        "name": "My Streamed Conference",
        "onCreateFunction": "onCreateMyStreamedConference"
      }],
      "currentEventAccess": "READ_WRITE",
      "eventOpenTrigger": {
        "runFunction": "onCalendarEventOpen"
      },
      "eventUpdateTrigger": {
        "runFunction": "onCalendarEventUpdate"
      },
      "eventAttachmentTrigger": {
        "label": "My Event Attachment",
        "runFunction": "onCalendarEventAddAttachment"
      },
      "homepageTrigger": {
        "runFunction": "onCalendarHomePageOpen",
        "enabled": true
      }
    },
    "common": {
      "homepageTrigger": {
        "runFunction": "onDefaultHomePageOpen",
        "enabled": true
      },
      "layoutProperties": {
        "primaryColor": "#ff392b",
        "secondaryColor": "#d68617"
      },
      "logoUrl": "https://ssl.gstatic.com/docs/script/images/logo/script-64.png",
      "name": "Demo Google Workspace Add-on",
      "openLinkUrlPrefixes": [
        "https://mail.google.com/",
        "https://script.google.com/a/google.com/d/",
        "https://drive.google.com/a/google.com/file/d/",
        "https://www.example.com/"
      ],
      "universalActions": [{
        "label": "Open settings",
        "runFunction": "getSettingsCard"
      }, {
        "label": "Open Help URL",
        "openLink": "https://www.example.com/help"
      }],
      "useLocaleFromApp": true
    },
    "drive": {
      "homepageTrigger": {
        "runFunction": "onDriveHomePageOpen",
        "enabled": true
      },
      "onItemsSelectedTrigger": {
        "runFunction": "onDriveItemsSelected"
      }
    },
    "gmail": {
      "composeTrigger": {
        "selectActions": [
          {
            "text": "Add images to email",
            "runFunction": "getInsertImageComposeCards"
          }
        ],
        "draftAccess": "METADATA"
      },
      "contextualTriggers": [
        {
          "unconditional": {},
          "onTriggerFunction": "onGmailMessageOpen"
        }
      ]
    },
    "docs": {
      "homepageTrigger": {
        "runFunction": "onEditorsHomepage"
      },
      "onFileScopeGrantedTrigger": {
        "runFunction": "onFileScopeGrantedEditors"
      },
      "linkPreviewTriggers": [
        {
        "runFunction": "onLinkPreview",
        "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "example-path"
            }
        ],
        "labelText": "Link preview",
        "localizedLabelText": {
          "es": "Link preview localized in Spanish"
        },
        "logoUrl": "https://www.example.com/images/smart-chip-icon.png"
        }
      ],
      "createActionTriggers": [
        {
          "id": "exampleId",
          "labelText": "Example label text",
          "localizedLabelText": {
            "es": "Label text localized in Spanish"
          },
          "runFunction": "exampleFunction",
          "logoUrl": "https://www.example.com/images/case.png"
        }
      ]
    },
    "sheets": {
      "homepageTrigger": {
        "runFunction": "onEditorsHomepage"
      },
      "onFileScopeGrantedTrigger": {
        "runFunction": "onFileScopeGrantedEditors"
      }
    },
    "slides": {
      "homepageTrigger": {
        "runFunction": "onEditorsHomepage"
      },
      "onFileScopeGrantedTrigger": {
        "runFunction": "onFileScopeGrantedEditors"
      }
    }
  },
  "oauthScopes": [
    "https://www.googleapis.com/auth/calendar.addons.execute",
    "https://www.googleapis.com/auth/calendar.addons.current.event.read",
    "https://www.googleapis.com/auth/calendar.addons.current.event.write",
    "https://www.googleapis.com/auth/drive.addons.metadata.readonly",
    "https://www.googleapis.com/auth/gmail.addons.current.action.compose",
    "https://www.googleapis.com/auth/gmail.addons.current.message.metadata",
    "https://www.googleapis.com/auth/userinfo.email",
    "https://www.googleapis.com/auth/script.external_request",
    "https://www.googleapis.com/auth/script.locale",
    "https://www.googleapis.com/auth/script.scriptapp",
    "https://www.googleapis.com/auth/drive.file",
    "https://www.googleapis.com/auth/documents.currentonly",
    "https://www.googleapis.com/auth/spreadsheets.currentonly",
    "https://www.googleapis.com/auth/presentations.currentonly",
    "https://www.googleapis.com/auth/workspace.linkpreview"
  ],
  "urlFetchWhitelist": [
    "https://www.example.com/myendpoint/"
  ]
}

HTTP

{
  "addOns": {
    "calendar": {
      "currentEventAccess": "READ_WRITE",
      "eventOpenTrigger": {
        "runFunction": "https://myownpersonaldomain.com/mypage?trigger=onCalendarEventOpen"
      },
      "eventUpdateTrigger": {
        "runFunction": "https://myownpersonaldomain.com/mypage?trigger=onCalendarEventUpdate"
      },
      "eventAttachmentTrigger": {
        "label": "My Event Attachment",
        "runFunction": "https://myownpersonaldomain.com/mypage?trigger=onCalendarEventAddAttachment"
      },
      "homepageTrigger": {
        "runFunction": "https://myownpersonaldomain.com/mypage?trigger=onCalendarHomePageOpen",
        "enabled": true
      }
    },
    "common": {
      "homepageTrigger": {
        "runFunction": "https://myownpersonaldomain.com/mypage?trigger=onDefaultHomePageOpen",
        "enabled": true
      },
      "layoutProperties": {
        "primaryColor": "#ff392b",
        "secondaryColor": "#d68617"
      },
      "logoUrl": "https://ssl.gstatic.com/docs/script/images/logo/script-64.png",
      "name": "Demo Google Workspace Add-on",
      "openLinkUrlPrefixes": [
        "https://mail.google.com/",
        "https://script.google.com/a/google.com/d/",
        "https://drive.google.com/a/google.com/file/d/",
        "https://www.example.com/"
      ],
      "universalActions": [{
        "label": "Open settings",
        "runFunction": "https://myownpersonaldomain.com/mypage?trigger=getSettingsCard"
      }, {
        "label": "Open Help URL",
        "openLink": "https://www.example.com/help"
      }],
      "useLocaleFromApp": true
    },
    "drive": {
      "homepageTrigger": {
        "runFunction": "https://myownpersonaldomain.com/mypage?trigger=onDriveHomePageOpen",
        "enabled": true
      },
      "onItemsSelectedTrigger": {
        "runFunction": "https://myownpersonaldomain.com/mypage?trigger=onDriveItemsSelected"
      }
    },
    "gmail": {
      "composeTrigger": {
        "actions": [
          {
            "label": "Add images to email",
            "runFunction": "https://myownpersonaldomain.com/mypage?trigger=getInsertImageComposeCards"
          }
        ],
        "draftAccess": "METADATA"
      },
      "contextualTriggers": [
        {
          "unconditional": {},
          "onTriggerFunction": "https://myownpersonaldomain.com/mypage?trigger=onGmailMessageOpen"
        }
      ]
    },
    "docs": {
      "homepageTrigger": {
        "runFunction": "https://myownpersonaldomain.com/mypage?trigger=onEditorsHomepage"
      },
      "onFileScopeGrantedTrigger": {
        "runFunction": "https://myownpersonaldomain.com/mypage?trigger=onFileScopeGrantedEditors"
      },
      "linkPreviewTriggers": [
        {
          "runFunction": "https://myownpersonaldomain.com/mypage?trigger=onLinkPreview",
          "patterns": [
              {
                "hostPattern": "example.com",
                "pathPrefix": "example-path"
              }
          ],
          "labelText": "Link preview",
          "localizedLabelText": {
            "es": "Link preview localized in Spanish"
          },
          "logoUrl": "https://www.example.com/images/smart-chip-icon.png"
        }
      ],
      "createActionTriggers": [
        {
          "id": "exampleId",
          "labelText": "Example label text",
          "localizedLabelText": {
            "es": "Label text localized in Spanish"
          },
          "runFunction": "https://myownpersonaldomain.com/mypage?trigger=onCreateAction",
          "logoUrl": "https://www.example.com/images/case.png"
        }
      ]
    },
    "sheets": {
      "homepageTrigger": {
        "runFunction": "https://myownpersonaldomain.com/mypage?trigger=onEditorsHomepage"
      },
      "onFileScopeGrantedTrigger": {
        "runFunction": "https://myownpersonaldomain.com/mypage?trigger=onFileScopeGrantedEditors"
      }
    },
    "slides": {
      "homepageTrigger": {
        "runFunction": "https://myownpersonaldomain.com/mypage?trigger=onEditorsHomepage"
      },
      "onFileScopeGrantedTrigger": {
        "runFunction": "https://myownpersonaldomain.com/mypage?trigger=onFileScopeGrantedEditors"
      }
    }
  },
  "oauthScopes": [
    "https://www.googleapis.com/auth/calendar.addons.execute",
    "https://www.googleapis.com/auth/calendar.addons.current.event.read",
    "https://www.googleapis.com/auth/calendar.addons.current.event.write",
    "https://www.googleapis.com/auth/drive.addons.metadata.readonly",
    "https://www.googleapis.com/auth/gmail.addons.current.action.compose",
    "https://www.googleapis.com/auth/gmail.addons.current.message.metadata",
    "https://www.googleapis.com/auth/userinfo.email",
    "https://www.googleapis.com/auth/script.external_request",
    "https://www.googleapis.com/auth/script.locale",
    "https://www.googleapis.com/auth/script.scriptapp",
    "https://www.googleapis.com/auth/drive.file",
    "https://www.googleapis.com/auth/documents.currentonly",
    "https://www.googleapis.com/auth/spreadsheets.currentonly",
    "https://www.googleapis.com/auth/presentations.currentonly",
    "https://www.googleapis.com/auth/workspace.linkpreview"
  ]
}

URLs de la lista de entidades permitidas

Las listas de entidades permitidas se usan para designar URLs específicas que están preaprovadas para que tu secuencia de comandos o complemento las use. Las listas de entidades permitidas ayudan a proteger los datos del usuario. Cuando defines una lista de entidades permitidas, los proyectos de secuencia de comandos no pueden acceder a las URLs que no se agregaron a la lista.

Este campo es opcional cuando instalas una implementación de prueba, pero es obligatorio cuando creas una implementación con control de versiones.

Usas listas de entidades permitidas cuando tu secuencia de comandos o complemento realiza las siguientes acciones:

  • Recupera o recupera información de una ubicación externa (como extremos HTTPS) con el servicio UrlFetch de Apps Script. Para incluir en la lista de entidades permitidas las URLs de recuperación, incluye el campo urlFetchWhitelist en tu archivo de manifiesto.
  • Abre o muestra una URL en respuesta a una acción del usuario (obligatorio para los complementos de Google Workspace que abren o muestran URLs externas a Google). Para incluir en la lista de entidades permitidas las URLs que se abrirán, incluye el campo addOns.common.openLinkUrlPrefixes en tu archivo de manifiesto.

Agrega prefijos a tu lista de entidades permitidas

Cuando especifiques listas de entidades permitidas en tu archivo de manifiesto (incluye el campo addOns.common.openLinkUrlPrefixes o urlFetchWhitelist), debes incluir una lista de prefijos de URL. Los prefijos que agregues al manifiesto deben cumplir con los siguientes requisitos:

  • Cada prefijo debe ser una URL válida.
  • Cada prefijo debe usar https://, no http://.
  • Cada prefijo debe tener un dominio completo.
  • Cada prefijo debe tener una ruta de acceso no vacía. Por ejemplo, https://www.google.com/ es válido, pero https://www.google.com no lo es.
  • Puedes usar comodines para hacer coincidir los prefijos de subdominios de URL.
  • Se puede usar un solo comodín * en el campo addOns.common.openLinkUrlPrefixes para que coincida con todos los vínculos, pero no se recomienda, ya que puede exponer los datos de un usuario y prolongar el proceso de revisión de complementos. Usa un comodín solo si la funcionalidad de tu complemento lo requiere.

Cuando se determina si una URL coincide con un prefijo en la lista de entidades permitidas, se aplican las siguientes reglas:

  • La coincidencia de rutas distingue mayúsculas de minúsculas.
  • Si el prefijo es idéntico a la URL, hay una coincidencia.
  • Si la URL es la misma o es secundaria del prefijo, hay una coincidencia.

Por ejemplo, el prefijo https://example.com/foo coincide con las siguientes URLs:

  • https://example.com/foo
  • https://example.com/foo/
  • https://example.com/foo/bar
  • https://example.com/foo?bar
  • https://example.com/foo#bar

Usa comodines

Puedes usar un solo carácter comodín (*) para que coincida con un subdominio en los campos urlFetchWhitelist y addOns.common.openLinkUrlPrefixes. No puedes usar más de un comodín para hacer coincidir varios subdominios, y el comodín debe representar el prefijo inicial de la URL.

Por ejemplo, el prefijo https://*.example.com/foo coincide con las siguientes URLs:

  • https://subdomain.example.com/foo
  • https://any.number.of.subdomains.example.com/foo

El prefijo https://*.example.com/foo no coincide con las siguientes URLs:

  • https://subdomain.example.com/bar (no coincidencia de sufijos)
  • https://example.com/foo (debe haber al menos un subdominio presente)

Algunas de las reglas de prefijo se aplican cuando intentas guardar el manifiesto. Por ejemplo, los siguientes prefijos generan un error si están presentes en tu manifiesto cuando intentas guardarlo:

  • https://*.*.example.com/foo (no se permiten varios comodines)
  • https://subdomain.*.example.com/foo (los comodines se deben usar como prefijo inicial)