Blog

Manuel Tardivo

Your first n8n workflow in 30 minutes: form → Google Sheet → Slack

n8n tutorial: webhook lead, Google Sheet row, Slack ping. No invented ROI: what to click, and how to verify the flow actually runs.

Cover image for the article “Your first n8n workflow in 30 minutes: form → Google Sheet → Slack”

Problem you solve: someone submits a form on your site and you want a row in a spreadsheet and a Slack ping without manual copy-paste.

What you ship in ~30 minutes: an n8n workflow (self-hosted or cloud) that handles a POST, appends to Google Sheets, and posts to Slack.

How you know it works: you send a fake JSON with curl and see a new row plus a Slack message.

Make and Zapier can do the same with less wiring; n8n is used here because it is easy to reproduce for free (self-hosted) and the same flow maps 1:1 to the other tools (same credentials, different UI).

Prerequisites

  • An n8n instance (n8n.io cloud or self-hosted).
  • A Google Cloud project with Google Sheets API enabled and an OAuth client (type per n8n’s Google credential docs).
  • Slack: an app with an Incoming Webhook to a test channel (or a bot with OAuth if you prefer).

Official n8n docs: Google Sheets, Slack, Webhook.

Step 1 — Inbound webhook

  1. Create a new workflow.
  2. Add a Webhook node, method POST, path e.g. lead-ingest.
  3. Activate the workflow and copy the Production URL (use Production if external forms will call it).
  4. Optional: set Response Mode to Using Respond to Webhook and add a Respond to Webhook node at the end returning { "ok": true }.

Example minimal payload:

{
  "email": "lead@example.com",
  "name": "Jane Doe",
  "message": "I need a quote"
}

Step 2 — Google Sheet

  1. Create a sheet with headers in row 1: timestamp, email, name, message.
  2. Add Google Sheets → Append row.
  3. Connect OAuth credentials and pick the document + sheet tab.
  4. Map fields from the Webhook output, e.g. {{ $json.body.email }} (exact expressions depend on whether you normalize with a Set node first).

Tip: add a Set node right after the Webhook with fixed keys email, name, message so a client schema change does not break the sheet mapping.

Step 3 — Slack

  1. Slack node → Post Message with OAuth or HTTP Request to the Incoming Webhook URL with JSON {"text": "..."}.
  2. Message body like: New lead: {{ $json.email }} — {{ $json.message }}.

Step 4 — Verify with curl

curl -sS -X POST 'https://<your-n8n>/webhook/lead-ingest' \
  -H 'Content-Type: application/json' \
  -d '{"email":"test@example.com","name":"Test","message":"Hello"}'

Check: new row in the sheet, message in Slack. If it fails, open the execution in n8n and read the failing node (401 Google = credentials; 403 Slack = revoked webhook).

Zapier and Make (same problem, different UI)

  • Zapier: “Webhooks by Zapier” (Catch Hook) → Google Sheets “Create Spreadsheet Row” → Slack “Send Channel Message”.
  • Make: Webhook module → Google Sheets “Add a row” → Slack “Create a message”.

Logic is identical. Idempotent rows are not automatic—if you must not duplicate the same lead, add deduplication (e.g. email + day in a Code node or a small lookup table).

Limits to remember

  • Provider rate limits (Slack, Google).
  • Webhook hardening: in production add Authorization: Bearer <token> and gate with an IF node before writing to the sheet.
  • Self-hosted n8n: you own upgrades and backups of the credentials database.

Summary

  1. Webhook POST → 2. (optional) Set to normalize JSON → 3. Append row → 4. Slack.
  2. Verify with curl.
  3. Rebuild the same graph in Make/Zapier if you prefer a managed SaaS.

You do not need a made-up “ROI percentage” to know this is valuable: if you currently copy leads manually and this flow removes that work, the problem is solved in a measurable way (manual time per lead → ~0 after deploy).

Portrait of Manuel Tardivo

Co-founder & CEO, Snowinch

Manuel Tardivo

On LinkedIn