Manifiestos para complementos de Google Workspace

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

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

Estructura del manifiesto para los complementos de Google Workspace

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

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

  • Para obtener información sobre los archivos de manifiesto de Google Apps Script, consulta Estructura del manifiesto.

  • Para obtener información sobre los archivos de manifiesto de los complementos creados con extremos HTTP, consulta projects.deployments.

Manifiestos para Google Chat

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

En Chat, se ignoran los parámetros de configuración comunes del manifiesto (incluido addons.common). Usa la API de Chat para configurar los siguientes parámetros de configuración de Chat:

Si compilaste el complemento en Apps Script, agrega o actualiza los siguientes objetos en tu manifiesto:

Para configurar los parámetros de Chat de un complemento, consulta Cómo configurar una app de Google Chat.

Ejemplo de configuración del manifiesto de un complemento de Google Workspace

En los siguientes ejemplos, se muestra la parte de un manifiesto que define un complemento de Google Workspace, incluidos los siguientes aspectos:

  • addOns.common define el nombre, el logotipo, los colores y otros parámetros de configuración generales del complemento.

  • El manifiesto define una página principal común, pero también define páginas principales específicas para Calendario de Google, Google Drive, Documentos de Google, Hojas de cálculo de Google y Presentaciones de Google. Gmail usa la página principal predeterminada.

  • La configuración del manifiesto de ejemplo habilita lo siguiente:

    • Activadores de Calendario eventOpen y eventUpdated

    • (Solo Apps Script) Dos soluciones de conferencias de Calendario.

    • Dos acciones universales.

    • Un Drive onItemsSelectedTrigger.

    • Una acción de redacción de Gmail y un activador contextual.

    • Un objeto linkPreviewTriggers de Documentos. Consulta Obtén una vista previa de los vínculos con chips inteligentes.

    • Un objeto createActionTriggers de Documentos. Consulta Crea recursos de terceros desde el menú @.

    • Interfaces específicas para archivos de Documentos, Hojas de cálculo y Presentaciones.

    • Una opción de sidePanelUri y addOnOrigins de Google Meet.

    • (Solo HTTP) Dos HttpOptions para enviar un encabezado de autorización y admitir el consentimiento detallado.

  • El campo oauthScopes establece los permisos de autorización del proyecto.

  • (Solo para Apps Script) urlFetchWhitelist garantiza que los extremos recuperados coincidan con los prefijos de URL HTTPS especificados. Consulta Cómo incluir URLs en la lista de entidades permitidas.

Los vínculos de los ejemplos redireccionan a las descripciones de los campos en la referencia del manifiesto para los complementos de Apps Script y HTTP de Google Workspace.

Los manifiestos incluyen otros componentes. Los campos en addOns se relacionan directamente con los complementos de Google Workspace. En este ejemplo, solo se muestra una parte de un archivo de manifiesto completo y no funciona por sí solo.

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"
      }
    },
    "meet": {
      "homepageTrigger",
      "Web": [
        {
          "sidePanelUrl": "https://myownpersonaldomain.com/sidePanelUrl",
          "supportsScreenSharing": true,
          "addOnOrigins": [
            "https://www.myownpersonaldomain.com",
            "https://www.myownpersonaldomain.com:443"
          ],
          "logoUrl": "https://myownpersonaldomain.com/logoUrl",
          "darkModeLogoUrl": "https://myownpersonaldomain.com/darkModeLogoUrl"
        }
    },
  },
  "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"
      }
    },
    "meet": {
      "homepageTrigger",
      "Web": [
        {
          "sidePanelUrl": "https://myownpersonaldomain.com/sidePanelUrl",
          "supportsScreenSharing": true,
          "addOnOrigins": [
            "https://www.myownpersonaldomain.com",
            "https://www.myownpersonaldomain.com:443"
          ],
          "logoUrl": "https://myownpersonaldomain.com/meetWebLogoUrl",
          "darkModeLogoUrl": "https://myownpersonaldomain.com/darkModeLogoUrl"
        }
      ]
    },
    "httpOptions": {
      "authorizationHeader": "SYSTEM_ID_TOKEN",
      "granularOauthPermissionSupport": "OPT_IN"
    }
  },
  "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

Usas listas de entidades permitidas para designar URLs específicas que están previamente aprobadas para el acceso de tu secuencia de comandos o complemento. Las listas de entidades permitidas ayudan a proteger los datos del usuario. Cuando defines una lista de entidades permitidas, los proyectos de secuencias 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 versionada.

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

  • Recupera o extrae información de una ubicación externa (como extremos HTTPS) con el servicio UrlFetch de Apps Script. Para incluir URLs en la lista de entidades permitidas para la 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 URLs en la lista de entidades permitidas para abrirlas, incluye el campo addOns.common.openLinkUrlPrefixes en tu archivo de manifiesto.

Cómo agregar prefijos a tu lista de entidades permitidas

Cuando especificas listas de entidades permitidas en tu archivo de manifiesto (incluyendo el campo addOns.common.openLinkUrlPrefixes o urlFetchWhitelist), debes incluir una lista de prefijos de URL. Los prefijos que agregues al manifiesto deben satisfacer 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 que coincidan los prefijos de subdominios de URL.
  • Se puede usar un solo comodín * en el campo addOns.common.openLinkUrlPrefixes para que coincidan todos los vínculos, pero no se recomienda, ya que puede exponer los datos del usuario a riesgos y prolongar el proceso de revisión del complemento. Solo usa un comodín 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, se considera que hay una coincidencia.
  • Si la URL es la misma o un elemento secundario del prefijo, se considera que hay 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

Uso de comodines

Puedes usar un solo carácter comodín (*) para que coincida 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 coincide el sufijo)
  • https://example.com/foo (debe haber al menos un subdominio)

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 (se prohíben varios comodines)
  • https://subdomain.*.example.com/foo (los comodines deben usarse como prefijo inicial)