Author: By Raj
Part of our Google Sheets Automation Expert guides. Need this built for your team? Hire a Google Apps Script developer.
Estimated reading time: 10 minutes
Build an Approval Workflow in Google Sheets with Apps Script
Approval workflows in Google Sheets combine status columns, data validation, email notifications, and optional web apps for managers who prefer not to edit the grid directly.
Typical flow: employee sets Status to Submitted → script emails approver with row link → approver sets Approved/Rejected → audit log appends timestamp and actor via Session.getActiveUser().getEmail().
Lock rows after approval with sheet.protect().setWarningOnly(false) or move approved rows to an Archive tab. Cross-link /blog/google-sheets-data-validation-apps-script for status lists.
State machine design
Define allowed transitions in an object: Draft→Submitted only, Submitted→Approved|Rejected. Reject scripts that jump Draft→Approved.
Store transition rules in Config sheet so ops can adjust without developer for text labels.
Notifier functions
MailApp.sendEmail with subject including request ID from column A. Include SpreadsheetApp.getActive().getUrl() + '#gid=' + sheet.getSheetId() + '&range=' + row.
Throttle emails if bulk import sets many rows to Submitted, send digest.
Audit log tab
Append [timestamp, user, row, oldStatus, newStatus] on each valid transition via appendRow.
Protect Audit tab from editors except admins.
Optional approver web app
HtmlService buttons call google.script.run.approveRow(id) for executives on mobile. Deploy execute-as user accessing sheet, domain-restricted.
See /blog/apps-script-crud-app-sheets for UI patterns.
Example code
function handleStatusChange(e) {
const sh = e.range.getSheet();
const row = e.range.getRow();
const status = e.range.getValue();
const id = sh.getRange(row, 1).getValue();
if (status === 'Submitted') {
MailApp.sendEmail('approver@company.com', 'Approval needed #' + id, 'Review row ' + row);
sh.getSheetByName('Audit').appendRow([new Date(), Session.getActiveUser().getEmail(), id, status]);
}
}| Approach | Best for | Tradeoff |
|---|---|---|
| Apps Script native | Google Workspace-centric workflows | 6-min limit, quotas |
| Zapier / Make | No-code, many connectors | Per-task cost, vendor lock-in |
| Python + Cloud | Heavy data / ML | Hosting cost, separate auth |
| Google Sheets automation expert | Production custom logic | Build cost, you own code |
FAQ
How do I capture who approved?
Can one approver pool work?
Yes. Send mail to a group alias or round-robin via a Queue sheet listing on-call approver emails updated weekly.
What about multi-step approvals?
Use columns Approver1Status and Approver2Status or a small state machine table, escalate after 48h with time-driven checks.
Does Google have native Approvals?
Workspace Approvals exists for some flows; Apps Script customizes logic tied to Sheets formulas and external systems.
How to prevent edit after approved?
Protect the row range except finance role, or move to Archive sheet read-only for requesters.
Need this done for you? I handle this as part of my consulting work, fixed-price quote within 24 hours.
Book a call with Raj →Get the full Build an Approval Workflow in Google Sheets with Apps Script script template
I'll email you a production-ready, commented version you can deploy in 10 minutes.
Continue reading
Google Sheets Automation
Google Sheets CRM Automation: Triggers, Pipelines, and Follow-Ups
Google Sheets Automation
Google Sheets Dashboard Automation with Apps Script
Google Sheets Automation
Auto-Generate Reports from Google Sheets with Apps Script
From another topic
How to Automate Google Sheets with Apps Script (Beginner Guide) →Need help with this? I handle this as part of my Google Sheets Automation Expert service.
CRM, dashboards, invoices, inventory, and report automation in Sheets.
See how it works →