Resources
What & Link | Type |
---|---|
Apps Script Homepage | Homepage |
Gettings Started with CLASP (Command Line Apps Script Platform) | Guide |
My post - Using TypeScript with Google Apps Script | Guide |
Using clasp
Reference material:
Quick reference:
- One time setup
- Install
yarn global add @google/clasp
npm install @google/clasp
- Grant credentials
clasp login
- Install
- Project setup
cd {projectDir}
- If...
- ... starting from scratch
clasp create {scriptTitle}
- ... project started already in web UI
clasp clone {scriptId}
- ... starting from scratch
- While working
- Download:
clasp pull
- Upload:
clasp push
- Open in browser:
clasp open
- Download:
Ignoring files
You can create and use a .claspignore
file to ignore files from being uploaded, just like how .gitignore
works.
By default, if no file is provided, it will only look for matching source code files (.js
, .ts
, .gs
, .html
), and blocks anything in .git
or node_modules
.
Using type definitions
You can find the types in @types/google-apps-script
and @types/google-adwords-scripts
.
If you are using straight TS, you can just install and then use as normal.
If you are using JS and want typed intellisense, you can install and then use the triple slash directive trick, or setup a tsconfig file.
If you don't want to have a
package.json
file, you could globally install types, and then pull in via symlink withnpm link @types/google-apps-script
. Just make sure you don't have clasp auto-upload!
...Or, you could also be lazy and use a triple slash directive with a global install location, like
/// <reference path="C:/laragon/bin/nodejs/node-v12/node_modules/@types/google-apps-script/index.d.ts" />
Common Coding Challenges
How to respond to GET / POST
In order to respond to incoming requests, you simply declare a top level function that matches the magic function name the docs indicate:
HTTP Method | Matching function |
---|---|
GET |
doGet(e) |
POST |
doPost(e) |
For those looking for what e
, or event looks like and its properties, this table in the docs has you covered. Or, if you are using types, the explicit type of e
is GoogleAppsScript.Events.DoGet
or GoogleAppsScript.Events.DoPost
, depending on the matching function.
Reminder: For accessing a JSON POST body, you can use
JSON.parse(e.postData.contents)
How to serve a redirect from a request
You basically can't serve a redirect, at least not directly via standard status and location headers.
Instead, the only workaround is to return an HTML document (via HtmlService
), and in it, add JavaScript that redirects by using window.open(REDIRECT_URL, 'top');
Details:
- https://consulity.com/content/GASRedirectSawa.aspx
- https://dev.to/schoraria911/build-a-url-shortening-service-using-google-apps-script-3ple
How to make web requests (GET, POST, etc.)
Because GAS does not run in the browser, you don't have access to window.fetch()
or even XMLHttpRequest
; both of those are web APIs. You do however have a GAS provided service and set of methods - "Url Fetch".
NOTE: GAS's method
fetch()
is not the same as the web APIfetch()
that most people are used to. To start with, GASfetch()
, like pretty much everything in GAS, is synchronous, not async!
How to persist values across runs
As you start building more complex scripts, a common requirement that you run into is the need to "persist" a value across script runs, which is something that you cannot do with plain JavaScript / GAS variables.
There are tons of options on how you can save and retrieve a value when executing Google Apps Script code, but I'll break them down into categories.
- External Services (Non-Google)
- Since Apps Scripts can make network requests, there is nothing preventing you from wiring up your script to a non-GAS backend somewhere else.
- GAS also has built-in support for remote database connections, via
JDBC
. You can find docs for that here.
- GAS also has built-in support for remote database connections, via
- Here are some examples of non-Google external services you could wire up in order to persist data
- MySQL Database (via JDBC)
- External API (PHP, NodeJS, etc.)
- POST endpoint for form collection
- Another cloud DB: AWS, Azure, etc.
- Since Apps Scripts can make network requests, there is nothing preventing you from wiring up your script to a non-GAS backend somewhere else.
- Native Services (Google)
- Since you are using GAS, there is a good chance you have a preference for staying in the Google ecosystem.
- As an added bonus, most of these options are free and easier to setup
- Native options include:
- The "Properties Service"
- Simple string key-value store, stored with the script
- Google Sheets (very common approach)
- Good for small pieces of data, especially when allowing user configuring
- starter guide
- Google Drive
- Good for file storage, blobs, etc.
- docs
- some samples
- Google Cloud SQL (via JDBC)
- Google Big Query (docs)
- ... probably at least one more I'm missing, given how often Google changes their product lineup.
- The "Properties Service"
- Since you are using GAS, there is a good chance you have a preference for staying in the Google ecosystem.
How to log and debug in Google Apps Script
Debugging and logging in GAS can be a little complicated, especially if you mix in deployed versions, connections to Google Cloud Platform (GCP), and exception handling.
The debugging section of the GAS troubleshooting page is a good starting point for learning about all the debugging and logging methods available to you.
General Logging Rules
As a general rule of thumb, if...
- You are executing code manually, via the online IDE
Run
menu- You can use
Logger.*
for output to the IDE's log output - You can use the
Debug
menu options to debug functions - You can use
console.*
for BOTH IDE logging and Stackdriver logging
- You can use
- You are executing code via triggers (time based,
doGet
, etc.)- You can only use Stackdriver logging (
console.*
) and exception recording- This is because the IDE logs (via
Logger.*
) are not persisted
- This is because the IDE logs (via
- You can only use Stackdriver logging (
Read more: Google Apps Script - Logging Guide
Where to find Logs and Exceptions
Again, depends on your use case:
- Online IDE Logs:
Menu -> View -> Logs
- Stackdriver logs and executions - any of the below options:
- Basic Logging:
Menu -> View -> Executions
https://script.google.com/home/projects/{projectId}/executions
https://script.google.com/home/executions
- Shows "your" executions, not all executions
- Also known as the "Apps Script Dashboard"
- Advanced Logging (** requires special setup to enable, see below)
GCP Home -> Project -> Logging -> Logs
(doc)https://console.cloud.google.com/logs/viewer
- Basic Logging:
Advanced Stackdriver Logging
To enable more advanced Stackdriver logging (filtering, advanced views, etc.), you have to change the GCP project that your script is attached to from a "Default GCP Project", to a "Standard GCP Project".
This is the warning text from the docs about this:
You can view a simplified version of Stackdriver logs in the Apps Script dashboard. However, to make the most of Stackdriver logging and error reporting you must have access to the GCP project of the script. This is only possible if your script project is using a standard GCP project.
There are other reasons why a standard project might be preferred anyways, and you can find those reasons as well as instructions for converting to standard in this doc page.
Alternative Logging Methods
There are many other alternative ways you could log output somewhere:
- Save to a Google Spreadsheet (just append a new row each time)
- Integrate with a third party logger (Sentry, Rollbar, etc.)
- Email yourself a report, text yourself, etc.
- Save to Google Drive
- ... and many other options
How to Deal With Configurable Secrets and Passwords
There are many different approaches for how to deal with configurable secrets and passwords in GAS, and the best option really depends on your specific use-case. Here are some to consider:
For user-configurable secrets (where you are publishing your script, and want users to be able to modify their password / secret)
- Using the Properties Service
- Since there is no longer a visual editor for these properties, you would need to do something like:
- Code your own simple editor
- Or
- Prompt users to run a one-time script that sets the value based on their input
- Or
- Something else...
- Code your own simple editor
- Since there is no longer a visual editor for these properties, you would need to do something like:
- Spreadsheet Scripts: Store value directly in sheet
- For example, the user could store their secret value in a named range of
SecretKey
, and then you could use:const userSecretRange = SpreadsheetApp.getActiveSpreadsheet().getRangeByName('SecretKey'); const userSecret = userSecretRange ? userSecretRange.getValue() : undefined;
- For example, the user could store their secret value in a named range of
For secrets that are hardcoded into your script, there are still some related approaches:
- If you are checking auth input against an expected value, you could use:
- Private/Public Key Pairs
- The published script would use a public key, requests to the script would have to be signed with the private key, and your script would check that these match.
- Standard (strong) Hashing
- Instead of storing the expected value directly as a plain-text string, you would store the SHA256 hash, as a base64 encoded string. Requests to the script would provide the plain-text password, which would then be hashed and checked against the stored hash.
- Private/Public Key Pairs
Deprecated Visual Properties Editor
Apps Script used to have a really easy way to allow for configurable hidden script properties, where you could quickly edit a hidden key-value store that was accessible from the script code, but stored with the user. The scoped key-value backing system still exists, but they removed the visual editor:
This a giant bummer, because this used to be a great way to be able to share the source code of a script that requires authentication, and just tell people they need to plug their key into that tab.