Every lead capture form should do three things automatically: save the lead somewhere, notify the right person, and send a welcome email. Most people build this once, badly, and then rebuild it every time they start a new project.
I rebuilt it four times before I finally wrote it down properly as an n8n workflow. This is that workflow — free JSON at the end.
What this workflow does
- Receives a webhook POST from your form (Tally, Typeform, Webflow, or a plain HTML form)
- Saves the lead to Airtable (or Google Sheets — I'll show both)
- Posts a Slack message to your #leads channel
- Sends a personalized welcome email via Gmail or SMTP
No paid n8n nodes. No external services beyond what you're probably already using.
Prerequisites
- n8n running (self-hosted free, or n8n Cloud — the workflow works on both)
- An Airtable account (free tier works)
- Slack workspace with a #leads channel
- A form that can send a POST webhook (Tally is free and does this natively)
Step 1: Set up your Airtable base
Create a base called Leads with these fields:
| Field | Type |
|---|---|
| Name | Single line text |
| Source | Single line text |
| Created | Date |
| Status | Single select (New / Contacted / Qualified) |
Copy your Airtable base ID from the URL: https://airtable.com/appXXXXXXXXXXXXXX/... — that appXXX... part is your base ID.
Step 2: Build the n8n workflow
Open n8n and create a new workflow. Add these nodes in order:
Node 1 — Webhook (trigger)
- Authentication: None (or Header Auth if you want security)
- HTTP Method: POST
- Path:
/new-lead - Response Mode: Immediately
This gives you a URL like https://your-n8n.com/webhook/new-lead — that's what your form will POST to.
Node 2 — Set (normalize the data)
Map incoming form fields to consistent variable names. Form providers use different field names — Tally uses fields[0].value, Typeform uses answers[0].text. The Set node creates a clean intermediate shape:
name → {{ $json.body.name ?? $json.body["Name"] ?? "Unknown" }}
email → {{ $json.body.email ?? $json.body["Email"] }}
source → {{ $json.body.source ?? "web" }}
Node 3 — Airtable (save the lead)
- Operation: Create Record
- Base ID: your base ID from Step 1
- Table: Leads
- Fields: map name, email, source, Created (use
{{ new Date().toISOString() }})
Node 4 — Slack (notify your team)
- Channel: #leads
- Message:
🎯 New lead: {{ $('Set').item.json.name }} ({{ $('Set').item.json.email }}) via {{ $('Set').item.json.source }}
Node 5 — Gmail / Send Email (welcome email)
- To:
{{ $('Set').item.json.email }} - Subject:
Thanks for reaching out, {{ $('Set').item.json.name }}! - Body: Write a short, warm reply. Don't make it look automated.
Node 6 — Respond to Webhook
- Return:
{ "status": "ok" }
Connect them 1 → 2 → 3, and from Node 2 also connect to 4 and 5 in parallel (right-click Node 2 → Add Output). Node 6 connects after Node 1 (immediate response) so the form doesn't time out waiting for your CRM writes.
Step 3: Connect your form
In Tally (free):
- Add a new block → Redirect / Webhook
- Paste your n8n webhook URL
- Test submit — you should see the execution appear in n8n immediately
In a plain HTML form:
<form id="lead-form">
<input name="name" placeholder="Your name" required>
<input name="email" type="email" placeholder="Email" required>
<button type="submit">Get started</button>
</form>
<script>
document.getElementById('lead-form').addEventListener('submit', async (e) => {
e.preventDefault();
const data = Object.fromEntries(new FormData(e.target));
await fetch('https://your-n8n.com/webhook/new-lead', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
// show success message
});
</script>
Step 4: Google Sheets instead of Airtable (optional)
Replace Node 3 with a Google Sheets node:
- Operation: Append Row
- Spreadsheet ID: your sheet ID from the URL
- Sheet: Sheet1
- Columns: Name, Email, Source, Created At
Same downstream nodes; everything else stays identical.
The free workflow JSON
Drop a comment below and I'll share the full workflow JSON — import it directly into n8n with File → Import from JSON. It includes all 6 nodes pre-configured with placeholder credentials (swap in yours and it runs).
I've also packaged this workflow alongside two others (Stripe payment fulfillment + form-to-Sheets) into a starter pack if you want all three ready to go:
👉 n8n Workflow Starter Pack — $29 — includes documented JSON + a walkthrough for each workflow.
What to do if the webhook stops receiving data
Two common failures:
-
Form sends application/x-www-form-urlencoded instead of JSON — add a Code node after the Webhook and parse
$input.item.binarymanually, or switch your form to JSON mode. -
n8n is behind a firewall / localhost — use ngrok to expose it temporarily while testing:
ngrok http 5678.
That's the full build. If you're already running this and hit a specific snag, post it in the comments — I check back.
Top comments (1)
Here's the free workflow JSON as promised — paste this into n8n via File → Import from JSON:
Swap in your Airtable Base ID, Slack channel, and Gmail credentials and it runs. If you hit any snags importing, drop a reply and I'll help debug.