Skip to content

Instantly share code, notes, and snippets.

  • Select an option

  • Save jhacksworth/a42eaeff943994ad66e91552631bf2b5 to your computer and use it in GitHub Desktop.

Select an option

Save jhacksworth/a42eaeff943994ad66e91552631bf2b5 to your computer and use it in GitHub Desktop.

Revisions

  1. @imthenachoman imthenachoman created this gist Aug 12, 2023.
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,430 @@
    # Developing a GAS Powered Google Workspace Add-on And Launching It To The Marketplace <!-- omit in toc -->

    This guide will walk you through creating a public [Google Workspace Add-on](https://workspace.google.com/products/add-ons/), and launching it in the [Google Workspace Marketplace](https://workspace.google.com/marketplace/) for as free ***as possible***.

    This guide was written as I developed and launched my first add-on: [Nacho Auto Vacation for Gmail™](https://workspace.google.com/marketplace/search/Nacho%20Auto%20Vacation%20for%20Gmail%E2%84%A2).

    # Table of Contents <!-- omit in toc -->

    - [About](#about)
    - [Before You Start](#before-you-start)
    - [Google Account Types](#google-account-types)
    - [Internal vs. External Google Workspace Add-Ons](#internal-vs-external-google-workspace-add-ons)
    - [Why Google Apps Script Over Other Runtimes](#why-google-apps-script-over-other-runtimes)
    - [Remember The Quotas](#remember-the-quotas)
    - [Pre-Requisites](#pre-requisites)
    - [The Main Event](#the-main-event)
    - [Developing The Add-on](#developing-the-add-on)
    - [Scopes](#scopes)
    - [WYSIWYG Card Builder](#wysiwyg-card-builder)
    - [Add-on Manifest File](#add-on-manifest-file)
    - [Testing Your Add-On](#testing-your-add-on)
    - [Publishing The Add-on](#publishing-the-add-on)
    - [Prepare](#prepare)
    - [Homepage, Privacy Policy, and Terms of Service](#homepage-privacy-policy-and-terms-of-service)
    - [Demo Video (Maybe)](#demo-video-maybe)
    - [Create A Google Cloud Platform Project](#create-a-google-cloud-platform-project)
    - [Configure Your Add-on's OAuth Consent Screen](#configure-your-add-ons-oauth-consent-screen)
    - [OAuth Consent Screen Additional Verfification (Maybe)](#oauth-consent-screen-additional-verfification-maybe)
    - [Associate Your GAS Project To Your GCP Project](#associate-your-gas-project-to-your-gcp-project)
    - [Create A Deployment/Version Of Your GAS Project](#create-a-deploymentversion-of-your-gas-project)
    - [Final Steps](#final-steps)
    - [Appendix](#appendix)
    - [Naming Your Add-on](#naming-your-add-on)
    - [Website and Domain Name](#website-and-domain-name)
    - [Verifying Your Domain In Google Search Console](#verifying-your-domain-in-google-search-console)
    - [Publishing Your Google Site To Your Domain](#publishing-your-google-site-to-your-domain)
    - [References](#references)

    # About

    I use [Out of Office events in Google Calendar](https://support.google.com/calendar/answer/7638168#:~:text=Show%20when%20you%E2%80%99re%20out%20of%20office) and [Gmail's vacation responder](https://support.google.com/mail/answer/25922) to stay organized. But you have to make updates in two places: set an OOO event in the calender and then enable Gmail's vacation responder. *Not this guy.*

    I realized I could automate this with [Google Apps Script](https://www.google.com/script/start/) (GAS): every time there is an OOO event in my calendar, automatically enable/disable Gmail's vacation responder. WIN! (I've said it before and I'll say it again, ***GAS is the best productivity enhancement tool that exists, bar none***. It has some issues/gaps that can be annoying. If Google addresses those, GAS could take over the world. But I digress. :P)

    As I was developing the automation, I realized I could packge this up as an add-on and publish it to the marketplace. I figure if I want to enable my Gmail vacation responder when I have a Google Calendar OOO event then others must want theirs to do this too. So it made sense to launch this as an add-on.

    I'd never developed or published an add-on before. As I was looking into it, I realized that, while it is not super complicated, it is not readily obvious -- especially for anyone just getting into add-on development. Google does have a guide on [developing](https://developers.google.com/apps-script/add-ons/how-tos/building-workspace-addons) and [publishing](https://developers.google.com/apps-script/add-ons/how-tos/publish-add-on-overview) an add-on but it leaves a lot of unanswered questions.

    So I thought I would put together what I learned in this guide -- a playbook for anyone else who wants to develop their own add-on.

    The flow of this guide does not align with the flow/process I took because somethings I learned in the end that I wish I had known at the start.

    # Before You Start

    While Google's documentation does leave a lot of unanswered questions, it is a great place to start. I do highly recommend going through the various pages (on the left side navigation) on [https://developers.google.com/apps-script/add-ons/overview](https://developers.google.com/apps-script/add-ons/overview).

    Below are some key items/topics I think are worth highlighting.

    ## Google Account Types

    Google has two product offerings. Which kind you are use or need to use will depend on your situation/use-case/needs.

    They have:

    - The **free tier** (I don't know what they officially call it)
    - The **[paid tier](https://workspace.google.com/pricing.html)** called [Google Workspace](https://workspace.google.com/)

    The best I can tell, you do not need a **Google Workspace** account to develop and launch a Google Workspace Add-on. But if your add-on is for interacting with capabilities/features that are only available in Google Workspace then you'll need a paid Google Workspace account.

    For example, my add-on relies on creating [Out of Office events in Google Calendar](https://support.google.com/calendar/answer/7638168#:~:text=Show%20when%20you%E2%80%99re%20out%20of%20office) and that is only available with the paid Google Workspace account. Otherwise, how will you test your add-on?

    ## Internal vs. External Google Workspace Add-Ons

    I recommend reading through [How can I mark my app as internal-only so it doesn't require verification?](https://support.google.com/cloud/answer/9110914#zippy=%2Chow-can-i-mark-my-app-as-internal-only-so-it-doesnt-require-verification). Essentially:

    - **internal** - only for your use by users in your Google Workspace organization
    - **external** - for use by anyone in the public domain/realm

    **Note**: This document/guide is geared towards **external**. You'll need/want to check with your organization's Google Workspace admins for their process on launching an internal add-on for your organization.

    ## Why Google Apps Script Over Other Runtimes

    You you can build an add-on in any runtime on your own backend as long as it [returns properly formatted JSON](https://developers.google.com/workspace/add-ons/overview). If you have a complex add-on then you might need your own infrastructure (server) and back-end. But, if you don't, then you can [build your add-on in Google Apps Script](https://developers.google.com/apps-script/add-ons/overview). I've said it before and I'll say it again, ***GAS is the best productivity enhancement tool that exists, bar none***.

    If you're just starting out in your add-on journey, start with building your add-on in GAS and if you hit a wall, you can move to your on backend.

    ## Remember The Quotas

    The major downside to using Google Apps Script as the runtime for your add-on is you're at the mercy of [Google Apps Script quotas](https://developers.google.com/apps-script/guides/services/quotas). So keep those in mind. But, again, start with building your add-on in GAS and if you hit a wall, you can move to your on backend.

    ## Pre-Requisites

    Before you develop and launch an add-on, there are a few things you're going to need. Some of these I knew before I started, some I didn't realize till I got to the end -- and had to start all over. Save yourself the headache I had by making sure you are prepared.

    | What | Required | Details |
    | ------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | Development experience | preferred | There are some critical SDLC paradigms this guide does not cover like plan and design. You don't need to know or do these things but you'll save yourself a lot of headache if you do. |
    | [GAS](https://www.google.com/script/start/) | yes | This guide assumes you know the basics/fundamentals. If you don't, I highly recommend going through Google's tutorials and example scripts on https://www.google.com/script/start/. |
    | Google Account | yes | Needless to say, you'll need a Google account to do anything. See [Google Account Types](#google-account-types) |
    | Add-on name | yes | See [Naming Your Add-On](#naming-your-add-on) |
    | Website and Domain Name | yes | See [Website and Domain Name](#website-and-domain-name) |
    | Read Google's add-on documentation | preferred | My guide covers everything in Google's guide, but in more detail but I still recommend going through Google's at https://developers.google.com/apps-script/add-ons/how-tos/building-workspace-addons. |
    | Graphic assets | yes | See https://developers.google.com/workspace/marketplace/create-listing#graphic_assets for details on what you'll need. |

    # The Main Event

    Now that we've gotten the boring stuff out of the way, let's dive in.

    ## Developing The Add-on

    You're not developing and launching the same add-on I did, so I'm not going to get into the specifics of my add-on. All of my add-on's code is available at https://github.com/imthenachoman/Nacho-Auto-Vacation-for-Gmail if you want to see it.

    Google's guide is at https://developers.google.com/apps-script/add-ons/how-tos/building-workspace-addons. I will highlight the things I think are important based on my experience in developing my add-on.

    ### Scopes

    Unlike a normal GAS project, you need to explicitly list the scopes your code needs/uses in your project's [manifest file](https://developers.google.com/apps-script/concepts/manifests) in the [`oauthScopes`](https://developers.google.com/apps-script/manifest#Manifest.FIELDS.oauthScopes) array property. See https://developers.google.com/apps-script/add-ons/concepts/workspace-manifests for more details.

    _**IMPORTANT: Certain scopes are [restricted scopes](https://developers.google.com/apps-script/add-ons/concepts/workspace-scopes#restricted_scopes). If your add-on uses [restricted scopes](https://support.google.com/cloud/answer/9110914#restricted-scopes), your add-on will have additional review and requirements. You'll know if your add-on uses restricted scopes when you [configure your add-on's OAuth consent screen](#configure-your-add-ons-oauth-consent-screen). If it does, you'll have to go through an [additional review](#oauth-consent-screen-additional-verfification-maybe).**_

    There are two ways to determine which scopes your project uses:

    1. [View scopes from the GAS editor](https://developers.google.com/apps-script/concepts/scopes#viewing_scopes)
    2. Check Google's reference documentation for what scopes are necessary for different functions/methods/calls

    For example, my add-on makes a call to the Gmail API [`users.settings.updateVacation`](https://developers.google.com/gmail/api/reference/rest/v1/users.settings/updateVacation) which requires the scope `https://www.googleapis.com/auth/gmail.settings.basic`.

    Here is an [excerpt of the scopes I use in my add-on](https://github.com/imthenachoman/Nacho-Auto-Vacation-for-Gmail/blob/25011da98b9bd271d486f35cc06508688b620a4a/appsscript.json#L19) from [my manifest file](https://github.com/imthenachoman/Nacho-Auto-Vacation-for-Gmail/blob/main/appsscript.json):

    ``` json
    ...
    "oauthScopes": [
    "https://www.googleapis.com/auth/gmail.addons.execute",
    "https://www.googleapis.com/auth/gmail.settings.basic",
    "https://www.googleapis.com/auth/calendar.addons.execute",
    "https://www.googleapis.com/auth/calendar.events.readonly",
    "https://www.googleapis.com/auth/script.scriptapp",
    "https://www.googleapis.com/auth/userinfo.email"
    ],
    ...
    ```

    | Scope | Type | So thiss project can.... |
    | -------------------------------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
    | https://www.googleapis.com/auth/gmail.addons.execute | | ... run as a Gmail add-on |
    | https://www.googleapis.com/auth/gmail.settings.basic | restricted | ... [enable or disable the user's vacation responder setting in Gmail](https://developers.google.com/gmail/api/reference/rest/v1/users.settings/updateVacation) |
    | https://www.googleapis.com/auth/calendar.addons.execute | | ... run as a Calendar add-on |
    | https://www.googleapis.com/auth/calendar.events.readonly | sensitive | ... [list events from your calendar](https://developers.google.com/calendar/api/v3/reference/events/list) |
    | https://www.googleapis.com/auth/script.scriptapp | sensitive | ... create [triggers](https://developers.google.com/apps-script/reference/script/script-app#newTrigger(String)) |
    | https://www.googleapis.com/auth/userinfo.email | | ... see your [primary Google Account email address](https://developers.google.com/apps-script/reference/base/session#geteffectiveuser) so the project can create triggers on your [calendar](https://developers.google.com/apps-script/reference/script/trigger-builder#forUserCalendar(String)) |

    **Remember, these are the scopes I use in my add-on. Yours will be different.**

    ### WYSIWYG Card Builder

    Writing the code to create cards for the add-on is [painful, and if I am being honest, confusing](https://developers.google.com/apps-script/add-ons/concepts/card-interfaces). So I was very happy to discover https://gw-card-builder.web.app/. It is an online WYSIWYG card builder. You can visually create your cards and then copy/paste the code into your project.

    I used it to create [all of the card code for my add-on](https://github.com/imthenachoman/Nacho-Auto-Vacation-for-Gmail/blob/main/sidebar.js). I did refactor the code the builder provided but that was for personal reasons -- you don't need to.

    ### Add-on Manifest File

    Every add-on needs specific elements in your project's [manifest file](https://developers.google.com/apps-script/concepts/manifests). What goes in your add-on's manifest file will depend a lot on your add-on. My advice is to carefully read through https://developers.google.com/apps-script/add-ons/concepts/workspace-manifests to see what you need.

    Here is an explanation of what is in [my add-on's manifest file](https://github.com/imthenachoman/Nacho-Auto-Vacation-for-Gmail/blob/main/appsscript.json):

    ``` json
    ...
    "addOns": {
    "common": {
    "name": "Nacho Auto Vacation for Gmail",
    "logoUrl": "https://lh3.googleusercontent.com/pw/AM-JKLWnXrKoV9rliAUmvgumEE_fTK3IAX5rUAjo95LXXe6Xoai7Mo9XQ3OaNKksMJKNnfleCTQ6vTyit87FYzxdvdAe7W-FqgoP4udjgNpfY3Td77JUaS3RPO04LYBs9LlVnTAVqmjsf9kKztWZZojJDw_FQQ=s480-no?authuser=0",
    "homepageTrigger": {
    "enabled": true,
    "runFunction": "card_onHomepage"
    },
    "universalActions": [
    {
    "label": "Homepage",
    "openLink": "https://github.com/imthenachoman/Nacho-Auto-Vacation-for-Gmail"
    },
    {
    "label": "Privacy Policy",
    "openLink": "https://github.com/imthenachoman/Nacho-Auto-Vacation-for-Gmail#privacy-policy"
    }
    ]
    },
    "gmail": {},
    "calendar": {}
    },
    "urlFetchWhitelist": [
    "https://github.com/imthenachoman/"
    ]
    ...
    ```

    | Property | Reason | Reference |
    | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------ |
    | `addOns` | Root element for all add-on configuration | https://developers.google.com/apps-script/manifest/addons#addons |
    | `addOns.common` | Common properties | https://developers.google.com/apps-script/manifest/addons#common |
    | `addOns.common.name` | Name of the add-on | https://developers.google.com/apps-script/manifest/addons#Common.FIELDS.name |
    | `addOns.common.logoUrl` | Add-on logo urlFetchWhitelist | https://developers.google.com/apps-script/manifest/addons#Common.FIELDS.logoUrl |
    | `addOns.common.homepageTrigger` | Homepage properties | https://developers.google.com/apps-script/manifest/addons#Common.FIELDS.homepageTrigger |
    | `addOns.common.homepageTrigger.enabled` | Enable the homepage trigger | https://developers.google.com/apps-script/manifest/homepage-trigger#HomepageTrigger.FIELDS.enabled |
    | `addOns.common.homepageTrigger.runFunction` | Call the function [`card_onHomepage`](https://github.com/imthenachoman/Nacho-Auto-Vacation-for-Gmail/blob/25011da98b9bd271d486f35cc06508688b620a4a/sidebar.js#L147) when when this add-on loads the homepage | https://developers.google.com/apps-script/manifest/homepage-trigger#HomepageTrigger.FIELDS.runFunction |
    | `addOns.common.universalActions` | Show some universal links in th add-On | https://developers.google.com/apps-script/manifest/addons#Common.FIELDS.universalActions |
    | `addOns.gmail` | Show this add-on in Gmail; my add-on does not need to do/show anything special in Gmail | https://developers.google.com/apps-script/manifest/addons#AddOns.FIELDS.gmail |
    | `addOns.calendar` | Show this add-on in Google Calendar; my add-on does not need to do/show anything special in Google Calendar | https://developers.google.com/apps-script/manifest/addons#AddOns.FIELDS.calendar |
    | `urlFetchWhitelist` | All of the URLs my add-on references so links to them are allowed | https://developers.google.com/apps-script/manifest#Manifest.FIELDS.urlFetchWhitelist |

    ### Testing Your Add-On

    Google makes it stupid easy to test your add-on. Just follow the instructions at https://developers.google.com/apps-script/add-ons/how-tos/testing-workspace-addons#install_an_unpublished_add-on.

    You may have to execute your GAS project before you can do a test deployment.

    ## Publishing The Add-on

    This is why you're really here, right?

    Google's guide is at https://developers.google.com/apps-script/add-ons/how-tos/publish-add-on-overview but I'll dig into the steps I took. Plus, there are some things you want to have ready before you start, and the order of steps Google has isn't right. For example, you'll need to [create a GCP project](#create-a-google-cloud-platform-project) before you can create a version even though [Google's guide](https://developers.google.com/apps-script/add-ons/how-tos/publish-add-on-overview) has it the other way around.

    Before you start, make sure you've finished [developing](#developing-the-add-on) and [testing](#testing-your-add-on) your add-on.

    ### Prepare

    #### Homepage, Privacy Policy, and Terms of Service

    Your add-on's marketplace listing will need to link to a homepage, privacy policy, and terms of service. If you're reading this guide you're probably asking yourself what those things are and/or what they should say. I'll level with you -- I have no clue. This was kind of a trial and error process for me.

    I have no legal experience, nor do I want to point anyone in the wrong direction, so I won't dig into this topic. All I will say is I did a lot of Googling and spoke to a few lawyer friends.

    As you go through the OAuth consent screen approval process they will review your privacy policy and provide feedback. This is the various feedback I got when I was going through my approval process:

    > **Limited Use Requirements**
    >
    > If your app uses restricted scopes, we'll thoroughly review your Privacy Policy to check that it follows our [Limited Use requirements](https://support.google.com/cloud/answer/9110914#explain-types).
    >
    > If your Privacy Policy follows the Limited Use requirements, we need to know how your app treats user data. You can tell us this, and show how your app follows Google policies, through a public online disclosure. For example, this could be an in-product disclosure on the application homepage, or a public FAQ. You can read more about this requirement in the FAQ.
    >
    > We suggest adding a disclosure to your app that meets these requirements:
    >
    > - The disclosure must be under 500 characters.
    > - The disclosure must clearly call out that the app complies with the [Google API Services User Data Policy](https://developers.google.com/terms/api-services-user-data-policy#additional_requirements_for_specific_api_scopes), including the Limited Use requirements.
    > - The disclosure must contain a link to the [Google API Services User Data Policy](https://developers.google.com/terms/api-services-user-data-policy#additional_requirements_for_specific_api_scopes) so that it's easily accessible to all users.
    > - The disclosure must be accessible on the project’s homepage URL or one click away from the homepage URL.
    > - The disclosure must be easily visible to all users.
    >
    > Example disclosure: "**(App’s) use and transfer to any other app of information received from Google APIs will adhere to [Google API Services User Data Policy](https://developers.google.com/terms/api-services-user-data-policy#additional_requirements_for_specific_api_scopes), including the Limited Use requirements.**"
    And:

    > **Privacy Policy Requirements**
    >
    > - The URL in your project points to a privacy policy on a publicly accessible domain.
    > - The privacy policy is hosted and accessible in the domain of your website.
    > - The privacy policy is accessible from the app’s home page.
    > - Users can view the privacy policy.
    > - The privacy policy clearly describes the way your application accesses, uses, stores, or shares Google user data.
    > - [The privacy policy is linked to the OAuth Consent Screen on the Google API Console](https://console.developers.google.com/).
    > - You only use Google user data in the ways described in your published privacy policy.
    >
    > **Limited Use Requirements**
    >
    > If your app uses restricted scopes, we'll check that your privacy policy follows our [Limited Use requirements](https://support.google.com/cloud/answer/9110914#explain-types).
    >
    > **NOTE**: For your scenario, you will need to update your home page to include your privacy policy URL link with the Limited Use Disclosure.
    #### Demo Video (Maybe)

    As mentioned [above](#scopes), if your add-on uses [restricted scopes](https://support.google.com/cloud/answer/9110914#restricted-scopes), your add-on will have additional review and requirements. One of these requirements is:

    > Provide a YouTube video demonstrating how you'll use the data from these scopes in your app. Your video must include all OAuth clients that you assigned to this project.
    ![image](https://user-images.githubusercontent.com/83817/260203680-6ce6b9c1-1889-4f0c-90c9-aefdc7f70aea.png)

    I uploaded an unlisted video to YouTube.

    ### Create A Google Cloud Platform Project

    To quote [Google](https://developers.google.com/apps-script/add-ons/how-tos/publish-add-on-overview):

    > When you build your add-on in Apps Script, a default Google Cloud Platform (GCP) project is automatically created for it. However, you can’t use the default GCP project to publish your app. Instead, use the steps below to create a standard GCP project:
    So the first thing we need to do is [create a GCP project](https://developers.google.com/apps-script/add-ons/how-tos/publish-add-on-overview#create_a_standard_google_cloud_platform_project):

    1. Open https://console.cloud.google.com/project
    - Make sure you're logged in using the Google account you intend to use to publish the add-on
    - In most cases this will be the same account you [developed](#developing-the-add-on) and [tested](#testing-your-add-on) your add-on with
    2. Click `CREATE PROJECT` in the top next to `Manage Resources`
    ![image](https://user-images.githubusercontent.com/83817/260203659-5bf308aa-8948-43fe-a622-64cf3f11c2cf.jpeg)
    3. Fill out the `New Project` from
    - Your view may look different than mine
    - I am creating this GCP project under my Google Workspace account
    - `Project name` is the just the name of your GCP project and not necessarily the [name of your add-on](#naming-your-add-on). They don't have to match.
    ![image](https://user-images.githubusercontent.com/83817/260203660-9db7bcb9-34c2-43bb-a15f-88e279b8ecbe.jpeg)
    4. Once it finishes creating the project, click `SELECT PROJECT` in the `Notifications` window
    ![image](https://user-images.githubusercontent.com/83817/260203661-be4a412d-d915-41f2-91ef-3984a33e268f.jpeg)
    5. Make note of your `Project number` under `Project info` -- **you will need this later**
    ![image](https://user-images.githubusercontent.com/83817/260203662-a8e160f4-2e91-4b63-a1c0-d34f2fda1621.jpeg)

    *(More information on Google Apps Script and Google Cloud Platform Projects can be found at https://developers.google.com/apps-script/guides/cloud-platform-projects.)*

    ### Configure Your Add-on's OAuth Consent Screen

    When a user goes to install your add-on, they will see an OAuth consent screen asking them to allow the add-on to have access to their Google account/data. You need to [configure what this OAuth consenst screen](https://developers.google.com/workspace/marketplace/configure-oauth-consent-screen#fill_out_the_oauth_consent_screen) will say.

    1. If you're continuing from [Create A Google Cloud Platform Project](#create-a-google-cloud-platform-project) then you're already at your GCP project's dashboard. Otherwise, go to https://console.cloud.google.com/ and select this add-on's GCP project from the top selector.
    - Make sure you're logged in using the Google account you intend to use to publish the add-on
    - In most cases this will be the same account you [developed](#developing-the-add-on) and [tested](#testing-your-add-on) your add-on with
    ![image](https://user-images.githubusercontent.com/83817/260203663-9f0ad70b-98bc-45c4-ad0e-99942469aa9a.jpeg)
    2. Open the left side-bar and navigate to `APIs & Services` > `OAuth consent screen`
    ![image](https://user-images.githubusercontent.com/83817/260203664-27fadc0c-26d6-4019-ba59-74b27c25499b.jpeg)
    3. This guide assumes you're publishing your add-on to the public space/domain so select `External` for `User Type` and then click `Create`
    ![image](https://user-images.githubusercontent.com/83817/260203665-9d9cbf8c-b922-4961-8012-4bbcd2bbfbc9.jpeg)
    4. Fill in the fields as they apply to your add-on
    ![image](https://user-images.githubusercontent.com/83817/260203666-469b171e-c4c8-4db7-bf36-42383303a77c.png)
    5. Add all of your [scopes](#scopes)
    - This is where you'll if you have restricted scopes
    ![image](https://user-images.githubusercontent.com/83817/260203667-7b25f0e6-bac9-427a-8284-22ec1a9590b4.png)
    6. Add your test users
    ![image](https://user-images.githubusercontent.com/83817/260203668-ecd94ad6-f67b-4aeb-a67b-fa5b86c37a3e.jpeg)
    7. Go back to the dashboard
    ![image](https://user-images.githubusercontent.com/83817/260203669-29d600c2-8d69-4708-925c-2d84ca48c7fe.png)
    8. Click on `PUBLISH APP` under `Publishing status`
    ![image](https://user-images.githubusercontent.com/83817/260203675-190671a2-56e9-4c6c-9c89-0ca1deb67065.jpeg)
    9. Confirm for `Push to production?`
    ![image](https://user-images.githubusercontent.com/83817/260203677-a5d5cf9f-80da-4cc9-a112-28ff3d0b32ed.jpeg)

    ### OAuth Consent Screen Additional Verfification (Maybe)

    As mentioned [above](#scopes), if your add-on uses [restricted scopes](https://support.google.com/cloud/answer/9110914#restricted-scopes), your add-on will have additional review and requirements. You'll know yours needs this if you see this screen after configuring your [OAuth consent screen](#configure-your-add-ons-oauth-consent-screen).

    ![image](https://user-images.githubusercontent.com/83817/260203678-157432b4-26ee-4bb2-83c1-98ddf83f6e18.jpeg)

    1. Click `PREPARE FOR VERIFICATION`
    2. Review the app information and click `SAVE AND CONTINUE`
    3. Answer all of the questions
    ![image](https://user-images.githubusercontent.com/83817/260203681-14e2e158-8a9d-4a72-a6b8-8f77a062790f.png)
    4. Answer some more optional information
    ![image](https://user-images.githubusercontent.com/83817/260203683-85da3f5d-2966-4938-a040-5bd0cd49e182.png)
    5. Check the `My usage of OAuth Scopes complies with the Google API Services: User Data Policy.` box and click `SUBMIT FR VERIFICATION`
    ![image](https://user-images.githubusercontent.com/83817/260203685-5717cdad-8dd6-4782-8ac6-72a262cce087.png)
    6. Sit back and wait

    You will get en email from Google as they review your project. You might have to answer more questions, make updates, provide more evidence, etc. Just go through the motions with them.

    Be patient as it can take a while. I mean no insult but the review team does not seem to be super technical nor do they seem to know/understand all of Google's products/capabilities. I had to explain basic things like how the only way to enable/disable the vacation responder in Gmail was use a restricted scope. They kept asking me if I could remove the restricted scope as though they didn't understand the technical limtiation from Google's side. By the time everything was said and done, I had exchanged 200+ emails with Google.

    ### Associate Your GAS Project To Your GCP Project

    As mentioned [above](#create-a-google-cloud-platform-project), your GAS project will need to use a standard GCP project instead of the default one.

    1. Go to your GAS project and click on the gear icon
    ![image](https://user-images.githubusercontent.com/83817/260203672-fd5bf19b-5be0-41d8-bc12-47c4b266a183.jpeg)
    2. Scroll to the bottom and click the `Change project` button
    ![image]([019.jpeg](https://user-images.githubusercontent.com/83817/260203673-144a1573-0b67-4e7a-9fa4-3f950fd7d69d.jpeg))
    3. Enter your GCP project number that you got from step #5 of [Create A Google Cloud Platform Project](#create-a-google-cloud-platform-project) and click `Set project`

    ### Create A Deployment/Version Of Your GAS Project

    1. Go to your GAS project and click on the gear icon
    2. Go into the code editor
    3. Click on the dropdown arrow next to `Deploy`
    4. Enter a description and click `Deploy`
    5. Make note of the `Deployment ID` -- **you will need this later**

    More information can be found at https://developers.google.com/apps-script/add-ons/how-tos/publish-add-on-overview#create_a_version_of_your_add-on.

    ### Final Steps

    From here on, Google's documentation on publishing an add-on is pretty straight forward. Just follow the guide at https://developers.google.com/workspace/marketplace/how-to-publish from step #4.

    # Appendix

    ## Naming Your Add-on

    Google has [strict rules](https://about.google/brand-resource-center/guidance/apis/) on what you can name your add-on. You want to make sure to pick a name they will approve before you start otherwise you'll have to make a lot of changes like redoing all of your logos.

    So before you go too far down the rabit hole, read through https://about.google/brand-resource-center/guidance/apis/ to make sure your add-on meets all of their branding requirements.

    I originally named my add-on **Gmail Auto Vacation for Gmail** but they didn't like that because it had **Gmail** in it. They approved **Nacho **Auto** Vacation for Gmail™**. Notice the **** in the title becuase Gmail is trademarked by Google.


    ## Website and Domain Name

    In order for you to publish your add-on to the marketplace, your add-on and marketplace listing will need to link to official documents, like a privacy policy, on a website that [Google Search Console](https://search.google.com/search-console/about) shows you as an owner of.

    | Requirement | Details |
    | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | Website hosting | If you have have one, great. If not, I am using [Google Sites](https://workspace.google.com/products/sites/) because it is free and easy. |
    | Domain name | Google requires that you can show you own your website through [Google Search Console]([https://search.google.com/search-console/about](https://search.google.com/search-console/about)).<br /><br />I tried to use free solutions like [GitHub](https://github.com/imthenachoman/Nacho-Auto-Vacation-for-Gmail) for hosting my privacy policy but they wouldn't approve it since you can't claim ownership of a website under a domain name you don't own. I've seen quite a few add-ons in the marketplace using GitHub for their privacy policy and I have no clue how they did it because Google wouldn't let me do it. If anyone knows how they do it, please let me know in the comments below.<br /><br />I got my domain https://www.nachoapps.dev from [Google Domains](https://domains.google/) for $12 USD a year -- not too bad. You can get a domain name from wherever you want but going through Google Domains did make my life easier because then it automatically showed me as an owner on [Google Search Console](https://search.google.com/search-console/about). |

    ## Verifying Your Domain In Google Search Console

    Google requires that the account you use to publish your add-on is listed as an owner of your domain. I did not have to do anything special for this because I bought my domain from Google Domains.

    ![image](https://user-images.githubusercontent.com/83817/260203649-6acb365b-4ffa-4ec1-8b99-3e00bc541a55.jpeg)

    If you didn't use Google Domains, you can manually verify your domain:

    1. Go to https://search.google.com/search-console
    2. Click on the drop-down in the top-left
    ![image](https://user-images.githubusercontent.com/83817/260203656-6ef66312-e74a-4435-9a95-ce22419b6507.jpeg)
    3. Click `Add property`
    ![image](https://user-images.githubusercontent.com/83817/260203657-4eb331e7-6735-46cf-b028-d57f1c19c566.jpeg)
    4. Go through the wizard
    ![image](https://user-images.githubusercontent.com/83817/260203658-2b53fc3c-7037-450a-a9b9-e8111b36766d.jpeg)

    When everything is done, you should be able to go to `Settings` and see you are a verified owner.

    ## Publishing Your Google Site To Your Domain

    I used [Google Sites](https://workspace.google.com/products/sites/) because it is free and easy. Your domain name will need to point to your Google Site. To do this:

    1. Go to https://sites.google.com/
    2. Select your site
    3. Click on the gears in the top right corner
    ![image](https://user-images.githubusercontent.com/83817/260203654-f9bb9d5e-1d93-42d9-816e-d8d77058389d.jpeg)
    4. Click `Custom domains` on the left and `Add` on the right
    ![image](https://user-images.githubusercontent.com/83817/260203655-72da653f-1e7b-40a9-bff7-760c2c2b7ce7.jpeg)
    5. Go through the screens to add your domain
    6. Remember to republish your site to push the updates

    ## References

    - https://developers.google.com/apps-script/add-ons/how-tos/building-workspace-addons
    - https://developers.google.com/apps-script/add-ons/how-tos/publish-add-on-overview
    - https://developers.googleblog.com/2021/03/evolving-google-workspace-add-ons-with.html
    - https://developers.google.com/apps-script/add-ons/guides/query-logs
    - https://about.google/brand-resource-center/guidance/apis/