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.
- 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
- 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
# 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 deployIn 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).
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.
| 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 |
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
- 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
These projects are publicly viewable:
| Environment | Link |
|---|---|
| Development | Open in Apps Script |
| Production | Open in Apps Script |
MIT