Skip to content

Google Sheets Trigger

Overview

The Google Sheets Trigger watches a Google Sheet and starts a workflow when its rows change. Use it to turn a spreadsheet into a front end for automation — a sales team keeps a sheet, and every new row becomes a CRM record, an email, or an invoice.

BaseCloud polls the sheet and compares it against the last state it saw, so the trigger reports what actually changed rather than simply that something did.

When to use this trigger:

  • Create CRM records from rows a team adds to a shared sheet.
  • Kick off a workflow when a status column changes.
  • Import a list someone maintains outside the CRM.

Reading and writing a sheet

This trigger starts a workflow on change. To read or write sheet data inside a workflow, use the Google Sheets action task.

BaseCloud polls the sheet and compares it against the last state it saw. That comparison is why the very first run behaves differently from every run after it:

flowchart TD
    A[Poll the sheet] --> B[Compare against last seen state]
    B --> C{First run?}
    C -->|Yes| D["initial_connection — a baseline, not new records"]
    C -->|No| E["batch_changes — rows added, modified, deleted"]
    E --> F[Workflow runs]

Guarding against that first run is the single most common thing to get wrong here — see On the first run after connecting.

The Google Sheets Trigger configuration panel, described as monitoring Google Sheets for row updates, new rows and cell changes. A banner marks it as a trigger task that starts the workflow. Fields are a Google Sheets Connection selector, a Spreadsheet URL, a Sheet Name set to Sheet1, and an optional Watch Range whose placeholder reads A1 to AX1000, leave blank for entire sheet

The first run does not fire once per existing row

Connecting to a sheet that already has rows produces one initial_connection event summarising them — not one event per row. It carries totalRows, connectionSummary and a sampleData array of the first three rows. A workflow that assumes every trigger is a single row will mis-handle that first event.

There is a second collapse to know about: when more than 50 rows change in one poll, the individual events are replaced by a single batch_changes event carrying totalChanges, rowsAdded and rowsModified. A bulk paste into the sheet produces one event, not hundreds.

This trigger takes the spreadsheet URL; the Google Sheets action takes the spreadsheet ID. They are not interchangeable — paste the whole URL here, and the long identifier from inside it there.

Leaving Watch Range blank watches the entire sheet. Narrowing it is the cheapest way to stop edits in unrelated columns waking the workflow.

Configuration

Builder fields

The Field column is the label as it appears in the task builder; Key is the name the value is stored under and referenced by.

Field Key Type Default Notes
Google Account app_connection_id app-connection –
Spreadsheet URL spreadsheet_url text –
Sheet Name sheet_name text Sheet1
Watch Range (optional) watch_range text –
Field Required Default Notes
Google account Yes – The connected Google account with access to the spreadsheet.
Spreadsheet ID Yes – From the sheet's URL, between /d/ and /edit.
Sheet name Yes Sheet1 The tab within the spreadsheet.
Trigger type Yes row_updated What kind of change starts the workflow.
Watch range No blank Restrict watching to a range such as A2:F500. Blank watches the whole sheet.

Finding the spreadsheet ID:

https://docs.google.com/spreadsheets/d/1AbCdEfGhIjKlMnOpQrStUvWxYz/edit#gid=0
                                       └──────── spreadsheet ID ────────┘

Set a watch range on a large sheet

Watching an entire large sheet means comparing every cell on every poll. A range that covers only the columns and rows that matter is faster and produces fewer spurious changes — for example A2:F1000 to skip the header row.

Outputs

Field names are camelCase, unlike most tasks. They are exactly as emitted.

Field Type Example Notes
changeType string batch_changes What kind of change this was — batch_changes, initial_connection, and so on. Branch on this first.
rowIndex number 14 The affected row, 1-based, matching what you see in Sheets.
rowData array ["Jane","jane@x.com"] The row's current values.
oldRowData array ["Jane","old@x.com"] The row's previous values, for a modification.
timestamp string 2026-09-07T09:14:02Z When the change was detected.
run boolean true false when no change data was available.
run_text string Google Sheets Change Detected… A readable summary of the change.

On a batch change

Field Type Notes
totalChanges number How many changes were detected in this batch.
rowsAdded number Rows added.
rowsModified number Rows modified.
rowsDeleted number Rows deleted.
batchChanges array The individual row changes. Iterate this with a Loop using action set to array.

On the first run after connecting

Field Type Notes
totalRows number How many rows the sheet holds.
sampleData array A sample of the first rows.
connectionSummary string A readable summary of the connection.

Guard on changeType before creating records

The first run reports initial_connection — a baseline, not a batch of new rows. Test changeType in an If Statement before acting.

Real-World Examples

Turn new spreadsheet rows into CRM clients

Google Sheets Trigger      watch A2:F1000, trigger on row updated
  └─ If Statement          type is not "initial_connection"
      └─ Loop              over batchChanges
          └─ Match to Client   look the client up by email
              └─ Email         send a welcome message

Act on a status column change

Google Sheets Trigger
  └─ If Statement          the status cell equals "Approved"
      └─ BaseCloud Accounting   raise the invoice

Best Practices

  • Always set a watch range. It bounds the comparison and avoids noise from unrelated columns.
  • Skip the header row by starting the range at row 2.
  • Handle initial_connection explicitly. It is a baseline, not a batch of new records.
  • Loop over batchChanges, don't assume one change per run — several edits between polls arrive together.
  • Keep the sheet's shape stable. Inserting or reordering columns changes what each position means and will produce confusing changes.
  • Don't have the workflow write back to the same watched range — the write is itself a change and the trigger will fire again.

Troubleshooting

Symptom Cause and fix
No change data available from trigger. The event carried no change payload. Usually a transient poll issue; check the Google connection is still authorised.
Change data not found in raw_content. The stored change data could not be loaded. Re-save the task and let it re-baseline.
Invalid change data format: … The stored change payload was not readable. Re-save the task to re-baseline.
Trigger fires constantly A workflow is writing back into the watched range, or a formula recalculates on every poll. Narrow the watch range to static columns.
Nothing fires when rows change Wrong sheet name, changes outside the watch range, or the Google account has lost access to the file.
Every existing row looks new This is the initial_connection baseline run. Guard against it.

Frequently Asked Questions

How quickly does it react? The sheet is polled, so a change is picked up on the next poll rather than instantly.

Does it detect a formula's result changing? It compares cell values, so a recalculated formula reads as a change. Keep formula columns out of the watch range unless you want that.

Can I watch several tabs? One task watches one tab. Add a task per tab.

Can I write back to the sheet? Yes — with the Google Sheets action task, but write to a different range than the one being watched.

  • Google Sheets - Read and write sheet data in a workflow
  • Loop - Process each row in batchChanges
  • Match to Client - Turn a row into a CRM record
  • If Statement - Guard against the initial connection run
  • Webhook In - A more immediate alternative when the source can post data