In October 2017, Google released its Gmail “Add-on” platform, allowing developers to create add-ons for Gmail that work on both desktop and mobile (well Android right now, iOS coming later). I’m currently working on a Gmail Add-on for GMass that will let you see the campaign history for a contact when you’re viewing an email from that contact.
You can read the Google documentation on how to write an add-on, which I’ve basically memorized at this point. But if you’re like me, you’re going to run into some stumbling blocks while writing your Gmail Add-on, and you won’t have a place to turn, because this development platform is so new that these issues aren’t documented.
What exactly is an “Add-on” anyway?
If you’re confused, thinking that Add-ons have been around forever and all this hoopla is nothing new, you are partially right. The term “add-on” has been used in other contexts for far longer, like Firefox’s Add-ons, which are the Firefox equivalent of Chrome extensions. Many people use the term “add-on” to describe what is otherwise just a Chrome extension that extends Gmail. Google choosing the term “add-on” probably wasn’t the best idea, but since they did, let’s clear up the confusion. Chrome extensions are pieces of software that are installed in Chrome and can enhance the functionality of any website, Gmail being one of them. They are listed in the Chrome Web Store. Chrome extensions only work on desktop and not on mobile. If you are a Firefox user, the equivalent of Chrome extensions are Firefox add-ons. The new Gmail “Add-on” is a Gmail specific piece of software that enhances Gmail, and it has the benefit of working on both desktop and mobile, via the native Gmail app on Android (iOS support supposedly coming soon). It is possible to write a Chrome extension that does the equivalent of what your Gmail Add-on does, except for working on mobile. It is not possible to write a Gmail Add-on that does everything your Chrome extension does, unless what your Chrome extension does is limited to being present in the Gmail sidebar and only being active when an email is being read. Chrome extensions only work on the desktop. Gmail Add-ons work on desktop and mobile. Chrome extensions offer greater flexibility than Gmail Add-ons, in terms of look, feel, and the code that can be executed. Gmail Add-ons are more controlled, limiting you to certain fonts, layouts, and user interface controls.
No need to reload
As you’re writing your Add-on and testing it, you’ll be making changes to the HEAD deployment of your Google Apps Script project. To save your changes, you just hit the SAVE button in the Google Script editor, and then in another window, where you have Gmail loaded with your Add-on running, you do NOT need to RELOAD. Just open up another email, wait for your Add-on to present itself, and it will reflect your updated code. If you notice that your Add-on appears a bit too fast, then it might be cached, in which case you should reload Gmail.
Baffling error messages
While debugging, the error messages are just plain wrong occasionally. One of the things you’ll learn to do is to write navigation flows, so your user can navigate smoothly between cards. If you make a slight mistake in how you do this, you’ll be told that the updateCard method doesn’t exist.
Of course it exists. You just didn’t build your card quite right. I don’t know why exactly this doesn’t work, but note the commented lines. If you uncomment the “var” lines, and comment out the line at the top, it does work, without the runtime error.
The Universal Actions are hiding
Where in the world are your Universal Actions? I wanted to add a Help menu item to my cards, so since its context-independent, I figured I’d use a Universal Action. You then go to run your Add-on, but it doesn’t show. It’s there; it’s just not obvious where. Click the three dots in the upper right. Since Google doesn’t give you a screenshot showing where the Universal Actions go, I will:
Want the user’s email address?
You’ll probably want the email address of the logged-in user, because that’s an essential part of the process of determining who this person is and what account on your web app to log this user into. I spent hours trying to figure this out. Google uses a default scope of https://www.googleapis.com/auth/userinfo.email as part of your project, but the question is — once you have access to retrieve the email address, how do you write the Google Apps Script code to retrieve the email address? Googling it will lead you to Session.getActiveUser().getEmail. This will work fine during testing, because the Google Apps Script project owner will likely be the same as the Gmail account from which you’re testing. Once you test from a different Gmail account, you’ll be stumped as to why it’s returning an empty string. There are forum posts about this, and the solution appears to be using getEffectiveUser instead of getActiveUser. Why that works and the other doesn’t is beyond me, but if anyone else has any insight into this issue, I’d love to see a comment below.
What’s in a name?
The UI style guide states this specific rule:
Don’t include the words "Google" or "Gmail" in your add-on name.
However if you look at the G Suite Marketplace Gmail Add-on Store, you’ll note that pretty much everyone is breaking this rule. You want to get the name of your Add-on just right. The name that your user will see in the header of your Add-on the name specified in your manifest file. This name can be different from the name you use in the Gmail Add-on Store though. However, those aren’t the only names your user will see as they interact with and authorize your Add-on. They will also see the name associated with your OAuth client project for the Add-on authorization. They will also then see the name associated with your OAuth client project for authorization into your web app, assuming your Add-on works in conjunction with a web-app which most do, in order to be useful at all. And then there’s the name that only you, the developer, will see: the name of your Google Apps Script project.
Can’t install Add-on in test accounts
When building your Gmail Add-on, it’s easiest if the Google account that owns the Google Apps Script project is also the Gmail account that you are using for testing. As the documentation says, you can run a development Add-on in another Gmail account by specifying its Deployment ID, but if your project is owned by an @gmail.com account, and you try to load the Add-on into a G Suite account (like @wordzen.com), the Add-on won’t load, and you’ll be told it’s an invalid Add-on. Don’t worry. Your Add-on still exists, but for some reason Google won’t let you load developer add-ons owned by a Gmail.com account from a G Suite account.
There are a bunch of steps to actually publish your Gmail Add-on publicly to the G Suite Marketplace. After preparing all the text and image assets Google asks you for, you might find that the little checkbox at the bottom where you can tell Google that your project is indeed a Gmail Add-on is disabled and grayed out.
Now you could fire up Chrome’s Developer Tools and try to re-enable that checkbox yourself (I didn’t try this), but I suspect Google is smarter than to let that fly. I went to publish and it was grayed out. I was publishing from an @gmail.com account — the same @gmail.com account that I used to create all my other OAuth client projects for my other live products, and the same @gmail.com account I use to manage my Chrome Web Store extensions. On a hunch, I logged out, and logged in with my @wordzen.com account, and voila! — the checkbox was enabled. I guess Google is only allowing G Suite users to publish Gmail Add-ons publicly. Now that doesn’t mean your G Suite account has to own the Google Apps Script project. In my case, my @gmail.com account still owns the project, but my G Suite account has EDIT permissions on the project, and according to the publishing guidelines, that allows my G Suite account to publish the project.
More publishing problems
After you get that checkbox enabled, you now might find that the SAVE button is disabled.
Good lord. Why is it disabled? Because Google hasn’t yet granted you permission to publish a public Add-on. For now, Google requires that you fill out this permission-request form, be granted permission, and then you can submit your Add-on for review. I’m still waiting for permission to be granted. As soon as it is I’ll write another post about how much time that process took, and what it entailed.
In most cases, you’ll want your Add-on to authorize with your own web app. That means your user will have two sets of authorizations when first setting up the Add-on. They will go through the authorization process so that your Add-on gets permission to run the scopes you’ve selected. That means your Add-on code will be able to access the user’s email address, and the Gmail Message Id that’s currently opened and all that jazz. Then, your user will go through the process of logging in or creating an account with your web app, because chances are, any useful Add-on will need to tie information about the email message they’re viewing to information from your web app. That double authorization might be confusing, and might make your user think there’s a bug in your software, so be sure to use a custom authorization prompt following this process, rather than the default. If you use the default prompt, your user is sure to think something is wrong, being asked to authenticate twice. Additionally, the docs state this:
The above widget must use the
OnClose.RELOAD_ADD_ONsetting in its
OpenLinkobject to ensure the add-on reloads after authorization is received.
but I found it not necessary. In fact, it’s not even in the example. I found that the Add-on frame reloads automatically after the authorization popup is closed, regardless of whether authorization was successful or not.
I hope this article clarified the process of creating and publishing a Gmail Add-on, but you may run into stumbling blocks that I didn’t. If that’s the case, head over to the Stack Overflow section of Gmail Add-ons.
Ajay is the founder of GMass and has been developing email sending software for 20 years.