Why Google Apps Script Is Underrated
Every person with a Google account already has access to Apps Script. It runs on Google's servers. It's completely free. And it can automate virtually everything in your Google Workspace — without any subscription, no server setup, no external tools.
| Capability | What You Can Automate |
|---|---|
| Gmail | Auto-label, auto-reply, extract data from emails |
| Google Sheets | Auto-calculations, sending emails from Sheet data, building dashboards |
| Google Calendar | Create events, send reminders, sync with other systems |
| Google Drive | Organise files, create folders, convert formats |
| Google Docs | Generate documents from templates |
| Google Forms | Process submissions, trigger workflows |

Getting Started
- Open any Google Sheet, Doc, or Form
- Click Extensions → Apps Script
- A code editor opens — this is where you write your scripts
- Click the floppy disk icon to save, then the play button to run
Or go directly to script.google.com to create standalone scripts.
Automation 1: Auto-Label Emails in Gmail
Sort incoming emails automatically by sender domain, keywords, or any criteria.
function autoLabelEmails() {
// Run this on a trigger: every 5 minutes
const label = GmailApp.getUserLabelByName('Clients') || GmailApp.createLabel('Clients')
const threads = GmailApp.search('is:unread from:(@yourclient.com)', 0, 10)
threads.forEach(thread => {
thread.addLabel(label)
// Optional: mark as read after labelling
// thread.markRead()
})
},
// Set a time-based trigger to run every 5 minutes:
// Extensions → Apps Script → Triggers → Add trigger
// Function: autoLabelEmails
// Select event source: Time-driven → Minutes timer → Every 5 minutes
Automation 2: Send Emails from a Google Sheet
You have a spreadsheet of contacts. Send each one a personalised email.
function sendPersonalisedEmails() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Contacts')
const data = sheet.getDataRange().getValues()
// Skip header row
for (let i = 1; i < data.length; i++) {
const [name, email, company, status] = data[i]
// Skip if already sent
if (status === 'Sent') continue
// Build email body
const subject = `Following up — ${company}`
const body = `Hi ${name},
I wanted to follow up on our conversation about ${company}'s automation needs.
Have you had a chance to think about it?
Best,
Your Name`
// Send email
GmailApp.sendEmail(email, subject, body)
// Mark as sent in the spreadsheet
sheet.getRange(i + 1, 4).setValue('Sent')
sheet.getRange(i + 1, 5).setValue(new Date())
// Rate limiting: wait 1 second between emails
Utilities.sleep(1000)
}
Logger.log('Done! Check the sheet for sent statuses.')
},
Automation 3: Webhook Receiver in Apps Script
Apps Script can receive webhooks — making it a free alternative to many paid webhook processors.
// This script acts as a webhook endpoint
// Deploy it as a Web App (Publish → Deploy as web app → Anyone can access)
function doPost(e) {
const data = JSON.parse(e.postData.contents)
// Log to a Sheet
const sheet = SpreadsheetApp.openById('YOUR_SHEET_ID').getSheetByName('Webhooks')
sheet.appendRow([
new Date(),
data.event || 'unknown',
JSON.stringify(data),
])
// Trigger actions based on event type
if (data.event === 'payment.success') {
handlePaymentSuccess(data)
}
return ContentService
.createTextOutput(JSON.stringify({ success: true }))
.setMimeType(ContentService.MimeType.JSON)
},
function handlePaymentSuccess(data) {
// Send confirmation email, update CRM, etc.
GmailApp.sendEmail(
data.customer.email,
'Payment Confirmed — Thank You!',
`Hi ${data.customer.name}, your payment of ${data.amount} has been confirmed.`
)
},
Automation 4: Generate Reports Automatically
function generateWeeklyReport() {
const ss = SpreadsheetApp.getActiveSpreadsheet()
const dataSheet = ss.getSheetByName('Data')
const reportSheet = ss.getSheetByName('Weekly Report') || ss.insertSheet('Weekly Report')
const lastWeek = new Date()
lastWeek.setDate(lastWeek.getDate() - 7)
// Get data from last 7 days
const allData = dataSheet.getDataRange().getValues()
const weekData = allData.filter(row => new Date(row[0]) >= lastWeek)
// Calculate metrics
const totalRevenue = weekData.reduce((sum, row) => sum + (row[2] || 0), 0)
const totalOrders = weekData.length
const avgOrder = totalOrders > 0 ? totalRevenue / totalOrders : 0
// Write to report sheet
reportSheet.clearContents()
reportSheet.getRange('A1').setValue('Weekly Report: ' + new Date().toDateString())
reportSheet.getRange('A3:B6').setValues([
['Total Revenue', totalRevenue],
['Total Orders', totalOrders],
['Average Order', avgOrder.toFixed(2)],
['Generated', new Date()],
])
// Email the report
const recipient = 'you@example.com'
const subject = `Weekly Report — ${new Date().toDateString()}`
const body = `Weekly Summary:
Revenue: $${totalRevenue.toFixed(2)}
Orders: ${totalOrders}
Average Order: $${avgOrder.toFixed(2)}`
GmailApp.sendEmail(recipient, subject, body)
Logger.log('Weekly report sent!')
},
Triggers: Running Scripts Automatically
Without triggers, scripts only run when you manually click "Run." Triggers make them automatic.
| Trigger Type | When It Runs | Use Case |
|---|---|---|
| Time-driven: Every minute | Every minute | Real-time monitoring |
| Time-driven: Every 5 minutes | Every 5 minutes | Email checking, webhook processing |
| Time-driven: Hourly | Every hour | Reporting, data sync |
| Time-driven: Daily (9am) | Every day at 9am | Morning reports |
| Time-driven: Weekly (Monday) | Every Monday | Weekly reports |
| On form submit | When a Google Form is submitted | Form processing |
| On edit | When a cell changes in a Sheet | Live data validation |
| On open | When a Sheet is opened | Dashboard refresh |
To add a trigger:
- In Apps Script editor, click the clock icon (Triggers)
- Click "Add Trigger"
- Choose your function, event source, and schedule

