The App Maker editor and user apps will be shut down on January 19, 2021. New application creation is disabled. Learn more

Scripting Overview

App Maker makes it possible to create relatively complex apps without coding, but sometimes you need functionality that widgets and the model editor alone can't provide. App Maker's JavaScript script editor can help you fill in the gaps.

There are two types of scripts in App Maker: client scripts that run on users' browsers and server scripts that run on App Maker servers. Here are just a few examples of what you can do with scripts in App Maker:

  • Perform app-specific logic and calculations
  • Connect to external web services
  • Create custom permission checks
  • And more...

Client and server scripts

Though client and server scripts both run JavaScript, they differ in where they're used and even how they function.

Client script quick facts

  • Client scripts run on users' browsers. They can access the DOM, browser local storage, and more.
  • Client scripts can edit widget properties. App Maker exposes widgets as JavaScript objects, so you can change their appearance, events, and other properties programmatically.
  • Client scripts block the browser. To keep apps responsive, complex calculations should be avoided in client scripts.

  • Client APIs are asynchronous. Some client script calls execute out of order. See the work with data models example below for details.

  • Client scripts aren't secure. Advanced users can see and change client scripts with browser tools. Don't rely on them for data security or consistency.

Server script quick facts

  • Server scripts run on Apps Script. They can access databases directly and use Apps Script APIs like calendar, email, and more.
  • Server scripts don't keep state between requests. They run on distributed servers, so each time you call a scripts its global variables are empty.
  • Server scripts are sometimes subject to quotas. Calls to Apps Script services are limited by daily quotas.
  • Server scripts can be secure. Unlike client scripts, you can trust server scripts to control access to sensitive data. Use them for auditing and to enforce data consistency.

Script examples

The easiest way to understand the difference between client and server scripts is by example. The scripts below are from a to-do list app that lets users create multiple to-do lists, each with multiple to-do items.

Client: interact with pages and widgets

This onClick script for DeleteTodoListButton switches to a confirmation page when a user clicks the button:


Client: implement property bindings

This script is a binding expression for DeleteTodoListButton's enabled property. It ensures that the button is only enabled when there aren't any to-do items in a list, so users can only delete empty to-do lists.

@datasource.item != null && @datasource.item.TodoItems.length == 0

Client and server: work with data models


This script creates and selects a new to-do list. It first calls a server script to create a new list record, then reloads the TodoList model, and finally selects the newly-created list.

function onCreateTodoListClick() {
  var datasource = app.datasources.TodoList; {

    // When created, redisplay todo lists.
    datasource.load(function() {

      // When reloaded, select new todo list.

You might notice that the code doesn't match the order of operations above. That's because this script, like many client scripts, executes asynchronously. The script can't just execute createTodoListWithItem() then load(), because, both being asynchronous, there's no guarantee that a new to-do list will be created before the datasource reloads.

Instead, createTodoListWithItem() calls load() with a callback that only executes after a to-do list item is successfully created. Learn more about asynchronous scripts and callbacks in Client Scripts.


This server script is createTodoListWithItem(), called from the client script above. It accesses the app's database to create a new to-do list and an item for that list, then returns the list's Key.

function createTodoListWithItem() {
  // Automatically number todo lists for the user.
  var lock = LockService.getScriptLock();
  var query = app.models.TodoList.newQuery();
  var allTodoLists =;
  var todoList = app.models.TodoList.newRecord();
  var newListNumber = allTodoLists.length + 1; = "My list " + newListNumber;

  // Create first todo item for user convenience.
  var todoItem = app.models.TodoItem.newRecord();
  todoItem.TodoList = todoList;
  return todoList._key;

Server scripts don't save their data automatically, so the script calls saveRecords() to save its changes to the model. Remember to do the same when writing your own scripts that create or edit records.

The script also uses locking to ensure data consistency. Learn more about locking in Server Scripts.

Server: security, auditing, and data consistency

Server scripts help you keep your data consistent and secure. The script above used the lock service to achieve atomicity of query and create operations.

You can also implement custom permissions by using exceptions to disallow certain model events. For example, adding the following to a model's onDelete() event prevents record deletion:

throw "Deletions now allowed";

You can also create audits using the onCreate() handler:

var email = Session.getActiveUser().getEmail();
record.setAudit("Created on " + new Date() + " by user " + email + "\n");

Client and server: fetch data from other URLs


Use an XMLHttpRequest, or App Maker's HtmlArea widget to inject an IFRAME.


Use Apps Script's URL Fetch Service.

Client: integrate custom JavaScript libraries

There are two ways to load external JavaScript libraries, depending on the library:

JSHint for script validation

App Maker supports some JSHint directives. For example, you can use the ignore directive to turn off the static checker for a block of code:

/* jshint unused: true, eqnull: false */
var w = 3;   // Warning: w is defined but never used.
alert(10 == null); // Warning: use '===' to compare with 'null'.

/* jshint ignore:start */
var y = 4;     // No warning.
alert(10 == null); //  No warning.
/* jshint ignore:end */

var a = 5;   // Warning: a is defined but never used.
alert(10 == null); // Warning: use '===' to compare with 'null'.

For more information about JSHint, see the JSHint documentation.