Manifests para complementos do Google Workspace

Um complemento usa um arquivo manifesto para configurar determinados detalhes sobre o app e a operação dele.

Esta documentação aborda os detalhes da configuração de um manifesto para um complemento do Google Workspace.

Estrutura de manifesto para complementos do Google Workspace

Os complementos do Google Workspace usam o arquivo de manifesto para definir vários aspectos da aparência e do comportamento deles.

As propriedades de manifesto para complementos do Google Workspace são organizadas na seção addOns da estrutura de objetos do manifesto.

Manifestos para o Google Chat

Se o complemento do Google Workspace estender o Google Chat, você precisará configurar um app do Google Chat ativando e configurando a API Google Chat no console do Google Cloud.

As configurações de configuração de manifesto comuns (incluindo addons.common) são ignoradas no Chat. Em vez de usar o manifesto do complemento, use a API Chat para configurar as seguintes configurações do Chat:

Se você criou o complemento no Apps Script, também é necessário adicionar ou atualizar os seguintes objetos no manifesto:

Para saber como configurar o Chat em um complemento, consulte Configurar um app do Google Chat.

Exemplo de configuração de manifesto de complemento do Google Workspace

O exemplo de manifesto a seguir mostra a seção de um arquivo de manifesto que define um complemento do Google Workspace, incluindo os seguintes aspectos:

  • A seção addOns.common do manifesto define o nome, o URL do logotipo, as cores e outras configurações gerais independentes do host para o complemento.
  • O manifesto define uma página inicial comum, mas também define páginas iniciais específicas para Agenda, Drive, Documentos, Planilhas e Apresentações. O Gmail usa a página inicial padrão.
  • As configurações de exemplo do manifesto permitem o seguinte:
    • Acionadores eventOpen e eventUpdated da agenda.
    • (Somente Apps Script) Duas soluções de conferência do Google Agenda.
    • Duas ações universais.
    • Um onItemsSelectedTrigger do Drive.
    • Uma ação de composição do Gmail e um acionador contextual.
    • Um objeto linkPreviewTriggers do Documentos. Para saber mais sobre esse acionador, consulte Visualizar links com ícones inteligentes.
    • Um objeto createActionTriggers do Documentos. Para saber mais sobre esse gatilho, consulte Criar recursos de terceiros no menu "@".
    • Interfaces específicas para arquivos nos apps Documentos, Planilhas e Apresentações.
  • O campo oauthScopes define os escopos de autorização do projeto (geralmente necessário para complementos).
  • (Somente Apps Script) O campo urlFetchWhitelist garante que todos os endpoints buscados correspondam a uma lista especificada de prefixos de URL HTTPS. Para mais informações, consulte Lista de permissões de URLs.

Os links no exemplo direcionam para as descrições do campo na documentação de referência do manifesto correspondente para os complementos do Apps Script e do HTTP do 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"
  ]
}

Adicionar URLs à lista de permissões

Você usa listas de permissões para designar URLs específicos que são pré-aprovados para acesso pelo seu script ou complemento. As listas de permissões ajudam a proteger os dados do usuário. Quando você define uma lista de permissões, os projetos de script não podem acessar URLs que não foram adicionados a ela.

Esse campo é opcional quando você instala uma implantação de teste, mas é obrigatório quando você cria uma implantação com versão.

Use as listas de permissões quando o script ou complemento realizar as seguintes ações:

  • Recupera informações de um local externo (como endpoints HTTPS) usando o serviço UrlFetch do Apps Script. Para permitir a extração de URLs, inclua o campo urlFetchWhitelist no arquivo de manifesto.
  • Abre ou exibe um URL em resposta a uma ação do usuário (obrigatório para complementos do Google Workspace que abrem ou exibem URLs externos ao Google). Para permitir a abertura de URLs, inclua o campo addOns.common.openLinkUrlPrefixes no arquivo de manifesto.

Adicionar prefixos à lista de permissões

Ao especificar listas de permissões no arquivo de manifesto (incluindo o campo addOns.common.openLinkUrlPrefixes ou urlFetchWhitelist), é necessário incluir uma lista de prefixos de URL. Os prefixos adicionados ao manifesto precisam atender aos seguintes requisitos:

  • Cada prefixo precisa ser um URL válido.
  • Cada prefixo precisa usar https://, não http://.
  • Cada prefixo precisa ter um domínio completo.
  • Cada prefixo precisa ter um caminho não vazio. Por exemplo, https://www.google.com/ é válido, mas https://www.google.com não é.
  • Você pode usar caracteres curinga para corresponder a prefixos de subdomínio de URL.
  • Um único caractere curinga * pode ser usado no campo addOns.common.openLinkUrlPrefixes para corresponder a todos os links, mas isso não é recomendado, porque pode expor os dados de um usuário e prolongar o processo de análise do complemento. Use um curinga apenas se a funcionalidade do complemento exigir.

Ao determinar se um URL corresponde a um prefixo na lista de permissões, as seguintes regras se aplicam:

  • A correspondência de caminho diferencia maiúsculas de minúsculas.
  • Se o prefixo for idêntico ao URL, haverá uma correspondência.
  • Se o URL for o mesmo ou uma versão secundária do prefixo, ele será considerado uma correspondência.

Por exemplo, o prefixo https://example.com/foo corresponde aos seguintes URLs:

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

Usar caracteres curinga

É possível usar um único caractere curinga (*) para corresponder a um subdomínio nos campos urlFetchWhitelist e addOns.common.openLinkUrlPrefixes. Não é possível usar mais de um caractere curinga para corresponder a vários subdomínios, e ele precisa representar o prefixo principal do URL.

Por exemplo, o prefixo https://*.example.com/foo corresponde aos seguintes URLs:

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

O prefixo https://*.example.com/foo não corresponde aos seguintes URLs:

  • https://subdomain.example.com/bar (desconformidade do sufixo)
  • https://example.com/foo (pelo menos um subdomínio precisa estar presente)

Algumas das regras de prefixo são aplicadas quando você tenta salvar o manifesto. Por exemplo, os prefixos a seguir causam um erro se estiverem presentes no manifesto quando você tentar salvar:

  • https://*.*.example.com/foo (vários caracteres curinga são proibidos)
  • https://subdomain.*.example.com/foo (os caracteres curinga precisam ser usados como prefixo)