apps-script-slack-notifier
March 14, 2026 · View on GitHub
Detects new rows added to a Google Spreadsheet and sends Slack notifications via Bot Token using chat.postMessage — built from the apps-script-fleet template.
How It Works
- Time-driven trigger — A Google Apps Script time trigger runs
checkNewRowson a schedule (e.g., every 5 minutes) - New row detection — Reads all rows from the spreadsheet and extracts rows added after the last processed row index (
LAST_PROCESSED_ROW) - Slack notification — Calls
https://slack.com/api/chat.postMessageviaUrlFetchApp.fetchwith the new row content - State update — Saves the last processed row index to
PropertiesServiceto prevent duplicate notifications on the next run
Setup
1. Create a Slack App
- Go to api.slack.com/apps and create a new app
- Under OAuth & Permissions → Bot Token Scopes, add
chat:write - Install the app to your workspace and copy the Bot User OAuth Token (
xoxb-...) - Find the Channel ID of the target channel (right-click the channel → "View channel details" → copy the ID)
- Invite the Slack app to that channel:
/invite @your-app-name
2. Deploy to Google Apps Script
# Authenticate clasp (first time only)
pnpm exec clasp login
# Create .clasp-dev.json with your script ID
echo '{"scriptId":"YOUR_SCRIPT_ID","rootDir":"dist"}' > .clasp-dev.json
# Check, build, and deploy
pnpm run deploy
3. Set Script Properties
In the Apps Script editor: Project Settings (gear icon) → Script Properties → add:
| Property | Description |
|---|---|
SLACK_BOT_TOKEN | Slack Bot User OAuth Token (xoxb-...) |
SLACK_CHANNEL_ID | Target channel ID (C01234567 format) |
LAST_PROCESSED_ROW is set automatically on the first run of checkNewRows (defaults to 1 to skip the header row).
4. Set Up Trigger
Add optional Script Properties to configure the schedule:
| Property | Values | Default |
|---|---|---|
TRIGGER_INTERVAL | 1min, 5min, 10min, hourly, daily | 5min |
TRIGGER_HOUR | 0–23 (only used with daily) | 9 |
Run setupTrigger in the Apps Script editor (▶). First run requires script.scriptapp scope authorization.
Development Commands
| Command | Description |
|---|---|
pnpm run check | lint + typecheck + test (all checks) |
pnpm run test | Jest with coverage |
pnpm run test -- --watch | Jest watch mode |
pnpm run build | Bundle TypeScript and output to dist/ |
pnpm run deploy | check → build → clasp push to dev |
pnpm run deploy:prod | check → build → clasp push to production |
Project Structure
src/
├── index.ts # GAS entry points (checkNewRows, setupTrigger)
├── sheet-reader.ts # Spreadsheet row extraction logic
└── slack-message.ts # Slack message payload builder
test/
├── sheet-reader.test.ts
└── slack-message.test.ts
Notes
- Functions in
src/index.tsmust not have theexportkeyword — the GAS runtime does not support ES module syntax src/index.tsis excluded from test coverage because GAS globals (SpreadsheetApp, etc.) cannot run in Node.js- Coverage threshold: 80% for all metrics (configurable in
jest.config.json) LAST_PROCESSED_ROWdefaults to1on first run to skip the header row
Apps Script Projects
These projects are publicly viewable:
| Environment | Link |
|---|---|
| Development | Open in Apps Script |
| Production | Open in Apps Script |
License
MIT