Installable Triggers

Like simple triggers, installable triggers let Apps Script run a function automatically when a certain event, such as opening a document, occurs. Installable triggers, however, offer more flexibility than simple triggers: they can call services that require authorization, they offer several additional types of events including time-driven (clock) triggers, and they can be controlled programmatically. For both simple and installable triggers, Apps Script passes the triggered function an event object that contains information about the context in which the event occurred.


Even though installable triggers offer more flexibility than simple triggers, they are still subject to several restrictions:

  • They do not run if a file is opened in read-only (view or comment) mode.
  • Installable triggers always run under the account of the person who created them. For example, if you create an installable open trigger, it will run when your colleague opens the document (if your colleague has edit access), but it will run as your account. This means that if you create a trigger to send an email when a document is opened, the email will always be sent from your account, not necessarily the account that opened the document. However, you could create an installable trigger for each account, which would result in one email sent from each account.
  • A given account cannot see triggers installed from a second account, even though the first account can still activate those triggers.

Time-driven triggers

A time-driven trigger (also called a clock trigger) is similar to a cron job in Unix. Time-driven triggers let scripts execute at a particular time or on a recurring interval, as frequently as every minute or as infrequently as once per month. (Note that an add-on can use a time-driven trigger once per hour at most.) The time may be slightly randomized — for example, if you create a recurring 9 a.m. trigger, Apps Script chooses a time between 9 a.m. and 10 a.m., then keeps that timing consistent from day to day so that 24 hours elapse before the trigger fires again.

Google Apps triggers

Installable triggers for Google Apps are conceptually similar to simple triggers for Google Apps like onOpen(), but they can respond to additional events, and they behave differently.

For example, the installable open trigger for Google Sheets activates whenever the spreadsheet is opened by any user who has edit access, just like the simple onOpen() trigger. However, the installable version can call services that require authorization. The installable version runs with the authorization of the user who created the trigger, even if another user with edit access opens the spreadsheet.

There are several installable triggers for Google Apps:

  • An installable open trigger runs when a user opens a spreadsheet, document, or form that he or she has permission to edit.
  • An installable edit trigger runs when a user modifies a value in a spreadsheet.
  • An installable change trigger runs when a user modifies the structure of a spreadsheet itself — for example, by adding a new sheet or removing a column.
  • An installable form-submit trigger runs when a user responds to a form. There are two versions of the form-submit trigger, one for Google Forms itself and one for Sheets if the form submits to a spreadsheet.

Note that, unlike with simple triggers, the script for an installable trigger does not need to be bound to a Google App. For example, a standalone script can programmatically create an installable trigger for an arbitrary Google Sheets file by calling TriggerBuilder.forSpreadsheet(key) and passing in the spreadsheet's ID.

Managing triggers manually

To manually create an installable trigger through a dialog in the script editor, follow these steps:

  1. From the script editor, choose Resources > Current project's triggers.
  2. Click the link that says: No triggers set up. Click here to add one now.
  3. Under Run, select the name of function you want to trigger.
  4. Under Events, select either Time-driven or the Google App that the script is bound to (for example, From spreadsheet).
  5. Select and configure the type of trigger you want to create (for example, an Hour timer that runs Every hour or an On open trigger).
  6. Optionally, click Notifications to configure how and when you will be contacted by email if your triggered function fails.
  7. Click Save.

Managing triggers programmatically

You can also create and delete triggers programmatically with the Script service. Start by calling ScriptApp.newTrigger(functionName), which returns a TriggerBuilder.

The following example shows how to create two time-driven triggers—one that fires every 6 hours, and one that fires every Monday at 9 a.m. (in the time zone that your script is set to).

function createTimeDrivenTriggers() {
  // Trigger every 6 hours.

  // Trigger every Monday at 09:00.

This next example shows how to create an installable open trigger for a spreadsheet. Note that, unlike for a simple onOpen() trigger, the script for the installable trigger does not need to be bound to the spreadsheet. To create this trigger from a standalone script, simply replace SpreadsheetApp.getActive() with a call to SpreadsheetApp.openById(id).

function createSpreadsheetEditTrigger() {
  var ss = SpreadsheetApp.getActive();

To programmatically modify an existing installable trigger, you must delete it and create a new one. If you have previously stored the ID of a trigger, you can delete it by passing the ID as an argument to the function below.

function deleteTrigger(triggerId) {
  // Loop over all triggers.
  var allTriggers = ScriptApp.getProjectTriggers();
  for (var i = 0; i < allTriggers.length; i++) {
    // If the current trigger is the correct one, delete it.
    if (allTriggers[i].getUniqueId() == triggerId) {

Errors in triggers

When an installable trigger fires but the function throws an exception or otherwise fails to run successfully, you don't see an error message on your screen. After all, when a time-driven trigger runs or another user activates your form-submit trigger, you might not even be at your computer.

Instead, Apps Script sends you an email like the following:

From: apps-scripts-notifications@google.com
Subject: Summary of failures for Google Apps Script
Your script has recently failed to finish successfully.
A summary of the failure(s) is shown below.

The email includes a link to disable or reconfigure the trigger. If the script is bound to a Google Sheets, Docs, or Forms file, the email also includes a link to that file. These links let you disable the trigger or edit the script to fix the bug.

To review all of the triggers that are associated with your Google account and disable the triggers you no longer need, follow these steps:

  1. Open the script editor by opening any script or visiting script.google.com.
  2. Click Resources > All your triggers. If you just created a new script, the script editor will prompt you to give the script a name first.
  3. A dialog will list every simple or installable trigger that is associated with your account. From this dialog, it is not possible to determine which script uses a given trigger, but if you recognize the function name for an installable trigger and know that you don't need the trigger anymore, you can delete the trigger by clicking the X icon to the left of the function name. Simple triggers like onOpen() cannot be disabled from this dialog; instead, you must edit the appropriate script and remove or rename the onOpen() function.

Installable triggers in add-ons

Add-ons can programmatically create and manage these installable triggers:

  • Sheets add-ons can use the change, edit, open, and form-submit installable triggers.
  • Docs add-ons can use the open installable trigger.
  • Forms add-ons can use the open and form-submit installable triggers.
  • Any add-on can use time-driven installable triggers.

Installable triggers for add-ons must be created programmatically; they cannot be manually controlled through the Resources > Current project's triggers dialog in the script editor.


Normally, if a developer updates an add-on to use new services that require additional authorization, users are prompted to re-authorize the add-on the next time they use it.

However, add-ons that use triggers encounter special authorization challenges. Imagine an add-on that uses a trigger to monitor form submissions: a form creator might authorize the add-on the first time they use it, then leave it to run for months or years without ever reopening the spreadsheet. If the developer were to update the add-on to use new services that require additional authorization, the form creator would never see the re-authorization dialog because they never reopened the spreadsheet, and the add-on would stop working.

Consequently, unlike triggers in regular Apps Script projects, triggers in add-ons continue to fire even if they need re-authorization. However, the script will still fail if it hits a line of code that requires authorization the script does not have. To avoid this situation, developers can use the method ScriptApp.getAuthorizationInfo() to gate access to parts of code that have changed between published versions of the add-on.

Below is an example of the recommended structure. It responds to a form-submit event within a Google Sheets add-on and, if re-authorization is required, sends the user of the add-on an alert email using templated HTML.


function respondToFormSubmit(e) {
  var addonTitle = 'My Add-on Title';
  var props = PropertiesService.getDocumentProperties();
  var authInfo = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL);

  // Check if the actions of the trigger requires authorization that has not
  // been granted yet; if so, warn the user via email. This check is required
  // when using triggers with add-ons to maintain functional triggers.
  if (authInfo.getAuthorizationStatus() ==
      ScriptApp.AuthorizationStatus.REQUIRED) {
    // Re-authorization is required. In this case, the user needs to be alerted
    // that they need to re-authorize; the normal trigger action is not
    // conducted, since it requires authorization first. Send at most one
    // "Authorization Required" email per day to avoid spamming users.
    var lastAuthEmailDate = props.getProperty('lastAuthEmailDate');
    var today = new Date().toDateString();
    if (lastAuthEmailDate != today) {
      if (MailApp.getRemainingDailyQuota() > 0) {
        var html = HtmlService.createTemplateFromFile('AuthorizationEmail');
        html.url = authInfo.getAuthorizationUrl();
        html.addonTitle = addonTitle;
        var message = html.evaluate();
            'Authorization Required',
            message.getContent(), {
                name: addonTitle,
                htmlBody: message.getContent()
      props.setProperty('lastAuthEmailDate', today);
  } else {
    // Authorization has been granted, so continue to respond to the trigger.
    // Main trigger logic here.


<p>The Google Sheets add-on <i><?= addonTitle ?></i> is set to run automatically
whenever a form is submitted. The add-on was recently updated and it needs you
to re-authorize it to run on your behalf.</p>

<p>The add-on's automatic functions are temporarily disabled until you
re-authorize it. To do so, open Google Sheets and run the add-on from the
Add-ons menu. Alternatively, you can click this link to authorize it:</p>

<p><a href="<?= url ?>">Re-authorize the add-on.</a></p>

<p>This notification email will be sent to you at most once per day until the
add-on is re-authorized.</p>


Several limitations apply to installable triggers in add-ons:

  • Each add-on can only have one trigger of each type, per user, per document. For instance, in a given spreadsheet, a given user can only have one edit trigger, although the user could also have a form-submit trigger or a time-driven trigger in the same spreadsheet.
  • Add-ons can only create triggers for the document or spreadsheet in which the add-on is used. That is, an add-on that is used in Google Doc A cannot create a trigger to monitor when Google Doc B is opened.
  • Time-driven triggers cannot run more frequently than once per hour.
  • Add-ons do not automatically send the user an email when code run by an installable trigger throws an exception. It is up to the developer to check for and handle failure cases gracefully.
  • Add-on triggers will stop firing in any of the following situations:
    • If the add-on is uninstalled by the user
    • If the add-on is disabled in a document (if it is re-enabled, the trigger will become operational again)
    • If the developer unpublishes the add-on or submits a broken version to the add-on store
  • Add-on trigger handler functions will execute until they reach code that uses an unauthorized service, at which point they will stop. This is true only if the add-on is published; the same trigger in a regular Apps Script project or an unpublished add-on will not execute at all if any part of the script needs authorization.

Send feedback about...

Apps Script