Lead Capture Kitfor n8n
Get the kit

Reference

Node reference

Checked against n8n 2.47.3 node definitions. Workflow settings use execution order v1 and the Asia/Manila time zone.

#Main workflow nodes

# Node Type What it does
1 Website Form Webhook Webhook v2.1 POST /webhook/lead-capture. Responds through the Respond to Webhook node. Accepts JSON or form bodies; UTM tags in the query string are merged in.
2 When Executed by Another Workflow Execute Workflow Trigger v1.3 Input data mode: Accept all data. Receives leads from the Demo Form or any parent workflow and feeds the same path.
3 Config Edit Fields (Set) v3.4 The only node you edit. Every setting in one place. Passes the trigger data through.
4 Normalize & Validate Code v2 Maps field aliases, cleans text, lower-cases email, writes phones as E.164 (+639…), runs spam checks, checks required fields, guards against formula injection and pre-builds the reply for rejected leads.
5 Valid Lead? If v2.2 accepted = true continues. Otherwise skips to the reply (spam 200, invalid 422).
6 Read Existing Leads Google Sheets v4.5, Get row(s) Reads the Leads tab. Always Output Data is on, so an empty Sheet works. Retries 3 times; its error output goes to the save-failed path.
7 Dedupe Check Code v2 Matches by email (case-insensitive), then by phone. Builds lead_id (LC-YYYYMMDD-XXXX), timestamps in the business time zone, status, submission_count, notes and should_ack.
8 Duplicate? If v2.2 True goes to Update, false to Append.
9 Update Lead Row Google Sheets v4.5, Update Matches on lead_id and writes only last_seen_at, status, message, submission_count, trigger and notes. Retries 3 times.
10 Append Lead Row Google Sheets v4.5, Append Writes all 19 columns as RAW, so +63… stays text. Retries 3 times.
11 Build Response & Alerts Code v2 Builds the JSON reply, the HTML thank-you email and the alert text for each channel (Telegram HTML, Slack mrkdwn, Discord markdown with @everyone defused).
12 Build Save-Failed Response Code v2 Only when Sheets failed after retries: a 503 reply with a friendly message.
13 Webhook Request? If v2.2 trigger = webhook goes to the reply. Calls from other workflows skip it.
14 Respond to Website Respond to Webhook v1.4 Body from $json.response, status from $json.http_status (200, 422 or 503).
15 Save Failed? If v2.2 True stops the run with an error.
16 Stop: Lead Not Saved Stop and Error v1 Fails the run on purpose so the error handler logs and alerts it.
17 Send Acknowledgement? If v2.2 Uses should_ack: send_ack is on, the lead has an email, and it's not a repeat unless ack_on_duplicate is on.
18 Gmail: Acknowledge Lead Gmail v2.1, Send HTML email with the lead's first name, message and reference ID. Errors go to the Error Log.
19 Route Alerts Switch v3.2 Sends to every channel that's switched on (all matching outputs).
20 Telegram: Alert Team Telegram v1.2 HTML parse mode, link previews off.
21 Slack: Alert Team Slack v2.3 Posts to slack_channel_id.
22 Discord: Alert Team (HTTP) HTTP Request v4.2 POST to a Discord webhook URL, with mentions disabled.
23 Log Notification Failure Google Sheets v4.5, Append Writes failed email and alert attempts to Error Log, with an execution link.

#Error handler and Demo Form

Workflow Nodes
Lead Capture → Error Handler Error Trigger v1 → Error Config → Log Error to Sheet, plus Alert on Error? → Telegram: Error Alert. Publish it, then select it in the main workflow's Error Workflow setting.
Lead Capture → Demo Form Demo Lead Form (Form Trigger v2.3, path lead-capture-demo, Ignore Bots on) → Save Lead (run main workflow) (Execute Workflow v1.3, source Database, wait on) → Thank-You Page or Error Page (Form v2.3, Form Ending).

The Demo Form asks for Full Name, Email, Phone / Mobile, Company / Business and How can we help?, plus hidden source, utm_source, utm_medium and utm_campaign fields filled from the link, for example ?utm_source=facebook.

#Config fields

Field Type Default Meaning
business_name string Your Business Shown in the thank-you email and alerts
sheet_id string placeholder Google Sheet ID from its address
leads_tab string Leads Tab that stores leads
error_tab string Error Log Tab for failed email and alert attempts
timezone string Asia/Manila Time zone for received_at and last_seen_at
n8n_base_url string https://n8n.example.com Your n8n address, for execution links
default_country_code string 63 Country code for local numbers
default_source string website source when a request sends none
form_source_label string n8n-demo-form source for the hosted form
form_thank_you_text string Thanks! We received your message and will reply soon. formSubmittedText in the reply
send_ack boolean true Send the thank-you email
ack_on_duplicate boolean false Also email repeat leads
ack_from_name string Your Business Sender name on the email
ack_subject string Thanks for contacting [business] Subject; [business] is replaced
ack_response_time string will get back to you within 1 business day The promise in the email
ack_signature string — The Your Business team Last line of the email
alert_telegram boolean true Send Telegram alerts
alert_slack boolean false Send Slack alerts
alert_discord boolean false Send Discord alerts
alert_on_duplicate boolean true Alert for repeat leads too
telegram_chat_id string placeholder Chat or group ID (groups start with -100)
slack_channel_id string placeholder Slack channel ID (C…)
discord_webhook_url string empty Discord webhook URL; keep it private
dedupe_by_phone boolean true Treat the same phone as the same lead
keep_status_on_duplicate string contacted,qualified,won Statuses kept when a lead returns; others become returning
honeypot_field string website Hidden field that must stay empty
min_fill_seconds number 3 Minimum seconds between opening and submitting the form
max_links_in_message number 2 More links than this counts as spam
spam_keywords string casino, crypto investment, forex signals, seo services, backlinks, … Comma list; any match is spam
blocked_email_domains string mailinator.com, guerrillamail.com, 10minutemail.com, tempmail.com, yopmail.com Throw-away email domains

#Data each step adds

Field Example Notes
accepted true Not spam and no validation errors
is_spam, spam_reasons true, ["honeypot"] Reasons: honeypot, too_fast, too_many_links, keyword:<word>, blocked_domain:<domain>
errors ["email looks invalid"] name is required, email or phone is required, email looks invalid, phone looks invalid, name is too long
trigger webhook, form or subworkflow webhook only when the workflow's own webhook node ran. Only webhook reaches Respond to Website.
name, company, message Trimmed. Cells starting with =, +, - or @ get a leading ' so Sheets won't run them as formulas.
email, phone maria.santos@example.com, +639170000101 Email lower-cased; phone in E.164

Dedupe Check adds lead_id, received_at, last_seen_at, status, submission_count, notes, is_duplicate, matched_by, existing_row_number and should_ack. Use them in any node you add later:

Text
{{ $('Dedupe Check').first().json.lead_id }}

#Sheet columns

Leads row 1, in this order:

Text
lead_id, received_at, last_seen_at, status, name, email, phone, company, message, source, utm_source, utm_medium, utm_campaign, utm_term, utm_content, page_url, submission_count, trigger, notes
Column New lead Repeat lead
lead_id Written Used to find the row
received_at First contact Kept
last_seen_at, message, trigger Written Updated
status new returning, or kept if already contacted, qualified or won
name, email, phone, company Written Kept (first values win)
source, utm_*, page_url Written Kept (first-touch attribution)
submission_count 1 +1
notes Written “Re-submitted …” appended

Error Log row 1: logged_at, workflow, execution_id, execution_url, failed_node, error_message, lead_id.

Status values: new → contacted → qualified → won or lost. returning means the person sent the form again.

#Error handling

Failure What happens
Google Sheets read, append or update fails 3 retries, 2 seconds apart → 503 reply → Stop: Lead Not Saved → the error handler logs it to Error Log and alerts Telegram
Gmail send fails 3 retries → a row in Error Log. The lead is already saved.
Telegram, Slack or Discord fails 3 retries → a row in Error Log
Writing to the Error Log fails Ignored, so it never hides the original result
Any other unexpected error n8n fails the run → the error handler, if it's selected in settings

Lead Capture Kit for n8n: website enquiries saved to Google Sheets, de-duplicated, thanked and sent to your team chat.

Checked against n8n 2.47.3. n8n, Google Sheets, Gmail, Telegram, Slack and Discord are trademarks of their owners; this kit is not affiliated with them. Sample data is fictional.