# How to Send Google Sheets Updates to Your Phone

> Use a Google Apps Script edit trigger to send a short Ping to your phone when a task's Status cell changes to Ready.

- Published: 2026-10-12
- Author: PingRoom
- Category: Developers
- Topics: Google Sheets push notifications, Google Sheets cell change notification, Apps Script phone notification
- Canonical: https://pingroom.io/blog/google-sheets-push-notifications
- Cover image: https://pingroom.io/blog/google-sheets-push-notifications.webp
- Cover description: A PingRoom avatar works at a laptop while Pingo stands beside a face-down phone on the desk.

To send Google Sheets push notifications to a phone, connect an **installable Apps Script edit trigger** to a PingRoom incoming webhook. This example sends one short update to a Room when someone changes a task's Status cell to **Ready**.

It is a webhook recipe you configure, not a native Google Sheets integration. If email is enough, Google's [conditional notifications](https://support.google.com/docs/answer/14099459?hl=en) may already fit; they are available to certain work or school accounts.

## Give one change a clear meaning

Imagine a small workshop preparing collection orders. Its team agrees that **Ready** means an order can be collected. Create a tab named **Tasks** with these exact headers:

| Task            | Status      |
| --------------- | ----------- |
| Sample order 42 | In progress |

Column A holds a short, non-sensitive label. Column B holds the status. A person changes **B2** to **Ready**, and the destination Room receives:

> **Task ready**
>
> Ready: Sample order 42

This is an illustrative workflow. The script reports the spreadsheet edit; it cannot verify that the physical order is ready. Avoid putting customer details into labels that may appear on a lock screen.

## Prepare the Room and script

The destination Room's owner needs active **PingRoom Pro** for incoming webhooks. Members need PingRoom with notifications allowed to receive native phone alerts.

Follow the [incoming webhook setup](/blog/webhook-to-push-notification): open the Room's **Settings → Connections → Incoming webhooks**, add a connection named **Workshop sheet**, choose **Custom message**, and copy its URL.

In the spreadsheet, choose **Extensions → Apps Script**. This creates a [bound script](https://developers.google.com/apps-script/guides/bound) for that file. Open **Project Settings → Script Properties** and add:

| Property               | Value                             |
| ---------------------- | --------------------------------- |
| `PINGROOM_WEBHOOK_URL` | The complete incoming webhook URL |

Google's [Properties service](https://developers.google.com/apps-script/guides/properties) keeps this configuration out of sheet cells and pasted source. It is still accessible to script code. Bound scripts share the spreadsheet's access list, so use this recipe only with editors you trust with the credential. Never include the URL in a public example, screenshot, or log; rotate it in PingRoom if exposed.

## Add the edit handler

Paste this function into the script editor and save. Keep its name as `notifyReady`; the next step installs the authorized trigger.

```javascript
function notifyReady(e) {
  if (!e || !e.range) return;
  const cell = e.range;
  const sheet = cell.getSheet();
  if (
    sheet.getName() !== "Tasks" ||
    cell.getRow() < 2 ||
    cell.getColumn() !== 2 ||
    cell.getNumRows() !== 1 ||
    cell.getNumColumns() !== 1 ||
    e.value !== "Ready" ||
    e.oldValue === "Ready"
  )
    return;

  const headers = sheet.getRange(1, 1, 1, 2).getDisplayValues()[0];
  if (headers[0] !== "Task" || headers[1] !== "Status") {
    throw new Error("Expected Task and Status in columns A and B.");
  }
  const task = Array.from(
    sheet.getRange(cell.getRow(), 1).getDisplayValue().trim(),
  )
    .slice(0, 80)
    .join("");
  if (!task) return;

  const url = PropertiesService.getScriptProperties().getProperty(
    "PINGROOM_WEBHOOK_URL",
  );
  if (
    !url ||
    !/^https:\/\/api\.pingroom\.io\/api\/webhooks\/[^/?#\s]+\/[^/?#\s]+$/.test(
      url,
    )
  ) {
    throw new Error("Set a valid PingRoom webhook URL in Script Properties.");
  }

  let response;
  try {
    response = UrlFetchApp.fetch(url, {
      method: "post",
      contentType: "application/json",
      payload: JSON.stringify({
        action: null,
        title: "Task ready",
        message: "Ready: " + task,
      }),
      followRedirects: false,
      muteHttpExceptions: true,
    });
  } catch {
    throw new Error("Request failed. Check the webhook configuration.");
  }
  let accepted = false;
  try {
    accepted = JSON.parse(response.getContentText()).success === true;
  } catch {
    // A non-JSON response cannot confirm acceptance.
  }
  const status = response.getResponseCode();
  if (status !== 200 || !accepted) {
    throw new Error("PingRoom did not accept the Ping (HTTP " + status + ").");
  }
}
```

The [edit event](https://developers.google.com/apps-script/guides/triggers/events) supplies the edited range and, for a single cell, the new and previous values. The handler checks those before sending. It ignores multi-cell pastes, other tabs, header edits, other columns, and changes to anything except the exact text **Ready**.

It sends only the task label, capped at 80 characters, using the documented [PingRoom payload](/documents/webhooks). It does not upload the rest of the sheet. Google's [URL Fetch service](https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app) performs the HTTPS request; errors intentionally omit the credential and response body.

## Install one authorized trigger

In Apps Script, select **Triggers → Add Trigger**, then choose:

| Setting      | Value            |
| ------------ | ---------------- |
| Function     | `notifyReady`    |
| Deployment   | `Head`           |
| Event source | From spreadsheet |
| Event type   | On edit          |

Save and complete Google's authorization prompt. An [installable trigger](https://developers.google.com/apps-script/guides/triggers/installable) can call services requiring authorization and runs as the account that created it. Choose one responsible account and install one trigger; multiple owners installing the same handler can produce duplicate Pings.

![A PingRoom avatar checks a phone in the kitchen while Pingo stands on a nearby wooden shelf.](/blog/google-sheets-push-notifications-1.webp)

_AI-generated editorial illustration. Pingo is PingRoom's fictional mascot; the PingRoom avatars and task depict an example._

## Try the small example first

Change **B2** from **In progress** to **Ready**. Check the script's **Executions** list, the Room history, and the recipient phone. Clicking **Run** in the script editor supplies no edit event, so this handler does nothing there.

This recipe handles manual status edits. Formula recalculation, another script, or an API writing a value needs a different event source. It also provides no durable retry queue or exactly-once guarantee. An ambiguous request failure may occur after acceptance; check Room history before manually repeating it. Google [runtime and service quotas](https://developers.google.com/apps-script/guides/services/quotas), PingRoom cooldowns, and device notification settings still apply.

To pause the automation, delete its trigger in Apps Script. Start with a harmless task and a small [PingRoom Room](/app/rooms), then use the same agreed status consistently.
