![](https://corporate-assets.lucid.co/co/7c6fd082-22f3-4acf-ac27-a373bf635b6d.png?v=1712437569187)
The 6 deadly sins of Google Apps Script Add-on development
Tim Winchester
Reading time: about 15 min
Topics:
#1: Coding your Google Apps Script add-on in the built-in script editor
It’s always a chore doing the prep work necessary to be effective in a new environment when all you really want to do is jump in with both feet and start experimenting with APIs, and starting a new Google Apps Script add-on is no exception. That’s what makes the built-in script editor so tempting: you don’t have to set anything up or read any documentation. You can just click “Tools > Script editor” and then jump in and start coding immediately. However, like most temptations, it comes with a heavy cost later on. The built-in script editor offers minimal source control options, bare-bones search functionality, and a text editor that will get the job done but lacks quality-of-life features like automatic closing parenthesis insertion and simultaneous multiple line indentation. It’s certainly enough to get small projects working, but once you are dealing with more than a handful of files, you will eventually reach your breaking point, and that’s when the second temptation will kick in.![The built-in editor for Google Apps Script add-ons](https://corporate-assets.lucid.co/co/3861d306-5034-4970-adf0-248ca47ce1e4.png?height=227&width=617)
#2: Hardcoding app-specific strings and API calls
Unless your Google Apps Script add-on’s purpose is extremely specific to Sheets (for example), you will eventually want to port it to Docs. Or even if it will never be ported to another G Suite app, you may want to release translations of it in Spanish, French, German, and Chinese. If you’ve hardcoded every string relating to spreadsheets, you’ll have to hunt them all down to hand them over to your translator and then manually put them back in. If you’ve hardcoded every API call to SpreadsheetApp.getThing().getOtherThing().getWidth(), then you’ll have to replace it with DocumentApp.getDifferentThing().getWidth() all throughout your codebase. Or if you update the UI for one of multiple add-ons that are basically the same, you will have to move those changes over very carefully to make sure you don’t break anything in the other add-ons—which you probably weren’t thinking about very hard when making the updated UI.![Comparison of old UI and new UI of the Lucidchart Google Apps Script add-ons](https://corporate-assets.lucid.co/co/7d4f8b36-db89-44ce-b952-68c07426782e.png?height=1054&width=1202)
![Diagram of IntegratedApp's relationship to DocumentApp, SpreadsheetApp, and SlidesApp within the Lucidchart Google Apps Script add-on](https://corporate-assets.lucid.co/co/a0d3276c-9ada-45aa-93b2-2c6567a32ff6.png?height=393&width=1024)
#3: Only testing in AuthMode.LIMITED
This one is easy to forget because most of your work in a Google Apps Script add-on will be based on the functionality that is only available after the add-on has been enabled, which naturally means that most of the time you’ll be in AuthMode.LIMITED. Unfortunately, most of your new users will not be.![Diagram of authorization mode determined by the Google Apps Script add-on lifecycle](https://corporate-assets.lucid.co/co/cecc18f6-9db0-4d35-962b-f2271586f613.png?height=1174&width=2368)
BadIntegratedApp = { getPageWidth: SlidesApp.getActivePresentation().getPageWidth .bind(SlidesApp.getActivePresentation()) };
GoodIntegratedApp = { getPageWidth: function() { return SlidesApp.getActivePresentation().getPageWidth(); } };
#4: Not separating your HTML/JS/CSS
Google Apps Script add-ons only support two file types: .gs and .html. The .gs files are written in Google Apps Script (which is pretty close to Javascript with the name filed off) and run on the backend. These aren’t usually the source of this problem. As you might guess, the .html files are written in HTML and make up your add-on’s front-end. Seeing that you’re coding directly in HTML may bring you back to the days of using HomeSite to write DHTML and lead you to bundle related HTML, CSS, and JS together in one file. After all, you don’t have the option to include .js and .css files, right? Technically yes—but practically, there’s a way around this limitation. Although you can’t include .js and .css files directly, there’s nothing stopping you from creating .html files that function as if they are .js and .css files. Wrap your JS in a <script> tag, and voilà! You’ve got valid HTML. Wrap your CSS in a <style> tag, and you’ve got valid HTML. You can even use .js.html and .css.html in your filenames to make it perfectly clear that while this is an “HTML” file, it’s really a JS file. Then in your actual .html file, you can include your JS and CSS by using printing scriptlets like the following:<?!=HtmlService.createHtmlOutputFromFile('loginForm.js').getContent()?> <?!=HtmlService.createHtmlOutputFromFile('sidebar.css').getContent()?>
#5: Failing to understand environment restrictions at design time
Writing an add-on for G Suite is very similar to normal web development, but there are some things you could do on a normal web page that are just not possible in an add-on. It’s important that you understand these limitations before beginning development, and it’s just as important to convey them to your UI/UX designer before they start making mocks. It’s easy to think (for example) that you can put a contextually-captioned button in the title bar of your sidebar add-on, but it turns out that you can’t. If your mocks depended on that functionality being available, it’s back to the drawing board. While I cannot give an exhaustive list here of cans and cannots, I will explain a few, and I will note that the dialog guide and the add-on style guide will probably be useful to your designer. Firstly, you cannot violate the borders of the iframe sandbox, and all sandboxing is done in iframe mode. Try as you might, you will not be able to throw a div into the middle of the page to make a beautiful image selection modal dialog. You have to instead use the dialog options that the UI API provides. Secondly, paying close attention to the UI API will reveal that all calls to it come from your .gs files (which run on Google Apps Script servers), which means that a modal dialog created by your sidebar is actually created by your .gs backend script messaging Google’s frontend UI service in the browser. So if you pass in a JSON object full of functions that can affect the sidebar as a creation parameter of the modal, you will find that they will not be able to affect the sidebar through closure. This is because in order to pass that JSON object to the modal, you serialize it and send it to Google’s servers in a request, and then it gets deserialized on its way back to Google’s UI service, which uses the deserialized JSON to create the modal. The serialization/deserialization destroys any notion of closure on the JSON’s functions. You can use printing scriptlets to pass information from the sidebar to the dialog at its time of creation, but after that data flow between the two is limited to dialog events the backend will be listening for and backend functions explicitly invoked from the dialog using google.script.run.![Diagram showing where serialization destroys closure when sending a JSON object between the sidebar and a dialog of a Google Apps Script add-on](https://corporate-assets.lucid.co/co/47ea031a-b972-4a08-b467-cb03cb9ccaad.png?height=1061&width=1710)
#6: Delaying marketing materials until after submission for review
As engineers, it’s easy to dismiss marketing as “fluffy ‘people stuff’” and assume that your marketing department can spin up anything you need on short notice. Or, if you’re going it alone, it’s easy to think, “once I have the add-on working, I’ll submit it to get the functionality approved, and I’ll write up my promotional text while I wait for approval.” However, as you will find at 11:30pm on your submission deadline date, you can’t actually submit your add-on for approval without creating its webstore entry, which means submitting marketing materials. You can throw in dummy blank thumbnails and Lorem Ipsum text to make the forms submit, but you will have to get your add-on reapproved once you’ve put real images and text in, and all the while, your add-on will be not be in the webstore (if you’re lucky), or it will be in the webstore with nonsense text and blank images (if you aren’t so lucky). Save yourself the headache and get your media assets prepared long before your deadline.![Google Apps Script add-on webstore entry form](https://corporate-assets.lucid.co/co/5bd4009e-a104-4a2a-a704-d33dec27a52e.png?height=519&width=789)
Conclusion
You may have noticed that the common theme running through my recommendations is “prepare in advance.” This was not an accident. Easily the biggest difficulties in software development come from not thinking things through until a serious problem has reared its head, and add-on development is no exception. But if you are patient and do the unglamorous legwork first, you will find that writing Google Apps Script add-ons is actually quite enjoyable, and a well-prepared engineer has nothing to fear from them. As for me, surviving the mistakes and near-mistakes I encountered over the course of developing my Google Apps Script add-on was a rollercoaster, but completely worth it. I was able to be a launch partner for the announcement of Google Slides add-ons, and since then, our add-on has racked up almost 20,000 individual installs.About Lucid
Lucid Software is a pioneer and leader in visual collaboration dedicated to helping teams build the future. With its products—Lucidchart, Lucidspark, and Lucidscale—teams are supported from ideation to execution and are empowered to align around a shared vision, clarify complexity, and collaborate visually, no matter where they are. Lucid is proud to serve top businesses around the world, including customers such as Google, GE, and NBC Universal, and 99% of the Fortune 500. Lucid partners with industry leaders, including Google, Atlassian, and Microsoft. Since its founding, Lucid has received numerous awards for its products, business, and workplace culture. For more information, visit lucid.co.