Stop retyping contact form leads
Your contact form emails somebody, and that somebody retypes the details into a spreadsheet when they get a minute. Some weeks they do not get a minute. Below is the version I actually build: a webhook, a guard that decides what is real, and an audit trail for everything it throws out.
The questionHow do I get contact form enquiries into my CRM automatically without filling it with spam?
How the working version is put together
Post the form straight at a webhook
The trigger is a POST webhook on its own path, and your form posts directly to it. No inbox parsing, no five-minute polling gap, no mail rule quietly filing enquiries into a folder nobody opens. I set the response mode to acknowledge immediately, so whoever hit submit sees a confirmation while the rest of the run is still happening.
Flatten every payload into one shape
Form builders disagree about what a submission looks like. Some nest everything under a body object, some post the fields flat, some rename message to comments. The second node reads all of those variants and writes one fixed record I control: name, email, company, phone, message, source page, honeypot and timestamp. Nothing downstream has to know which form tool you use, which is why swapping the form later costs you one node rather than a rebuild.
Decide what is real before it lands
A code node scores the submission and writes down why. It checks the email address is structurally usable, rejects a filled honeypot field, rejects disposable domains like mailinator, rejects messages under fifteen characters, rejects anything carrying three or more links, rejects known cold-pitch phrases such as link building and guest post, and rejects all-caps shouting. Every rejection carries its reason in plain English, because I would rather you argue with the guard than quietly stop trusting the sheet.
Keep the rejects, never delete them
An IF node routes on that verdict. Clean enquiries carry on. Anything that failed goes to an Exceptions tab with the reason sitting next to it, and nothing is discarded. That tab is the only tuning dial I trust: read it after a fortnight and you will know whether the guard fits your traffic, or whether it ate a real customer with an unusual email address.
Add the context you would look up by hand
Before the row is written, a set node derives what a person would otherwise go and find: the email domain, whether it is a personal mailbox or a company one, a best-guess account name, a likely website, a stable enquiry id and a status of new. None of it is clever, and I add it because a lead you can sort beats a lead you have to open one at a time.
Write the row, then acknowledge
The clean enquiry appends to a Leads tab in Google Sheets, and a Gmail node sends a short reply quoting back what they wrote. That acknowledgement matters more than it sounds. Somebody who fills in a form and hears nothing for a day assumes it vanished, and I have watched people submit the same enquiry three times over a weekend because of it.
Filter website form enquiries into Google Sheets and send acknowledgements with Gmail
I have published this as a free n8n template, so you can read every node before you decide whether you want help with it. It is in review on the n8n template library.
What the manual version really costs
Two minutes an enquiry, measured on my own operations rather than lifted from a vendor study. Read the notification email, open the sheet, copy the name and the email and the company across, note which page they came from, then remember to reply.
At three enquiries a week you will never notice it. At thirty a week the retyping becomes a queue, and a queue is where enquiries go cold. The cost that shows up in the bank is the one I never see in a report: the person who filled in your form on Friday afternoon, heard nothing until Tuesday, and hired whoever replied within the hour.
The parts that break
Payload shape is the first one. I have had a form tool change its JSON between plan tiers, so submissions arrived nested one level deeper and every field landed empty in the sheet. Nothing errored. The rows just stopped containing anything, which is the worst kind of failure because it reads as a slow week.
The webhook itself is the second. As written it is an open door: anyone who finds the URL can post rows straight into your CRM, so a shared secret or a signature check goes on before it goes live. I would add a duplicate check on email address inside twenty four hours as well, because people double-submit when a page is slow, plus a retry on the sheet append.
Spam moves, too. The phrase list catches this year's SEO pitch and will not catch next year's, so I treat the guard as something you edit rather than something you install. Ten minutes in the Exceptions tab every couple of months is the whole maintenance story.
What it costs to run
Close to nothing in direct spend. I put no model call anywhere in this build, so the running cost is your automation platform plus the Google account you already pay for. On self-hosted n8n it disappears into the server bill you are already paying, and I have never watched this build move a monthly total by an amount anyone noticed.
The real cost is that somebody now has to read the Exceptions tab. I would budget ten minutes a month for that, and treat any quote assuming zero human attention afterwards as a quote for a system you will switch off by Christmas.
Why take this from me
Because the same shape runs in my own operation. Orders arriving from two storefronts, enquiries, supplier invoices: all of it passes a normalise step and then a guard before anything writes to a database, and the work below links to the running systems rather than to screenshots. I published this particular workflow as a free n8n template so you can read every node before deciding whether you want help with it.
You can reasonably object that everything I have described here runs inside my own business, and that I have no client roster standing behind it. I agree, and I would rather say so on this page than let you work it out afterwards. There are no reviews on this site, because nobody has hired me for this work yet.
When I would tell you not to build it
Under about five enquiries a week, do not. Copying five rows by hand costs you ten minutes, and this costs you an evening plus one more thing that can break on a Sunday. The maths only turns, in my experience, when the retyping has become a queue, or when enquiries start slipping because nobody was at a desk.
Check what your existing tools already do before you go any further. Webflow, Squarespace, HubSpot and Pipedrive all ship some form-to-CRM path in the box, and if you are on one of them you may already own the boring three quarters of this. I would count paying me to rebuild something that is sitting unused inside a subscription you renew every month as the worst value in this category.
There is one more case, which is that nobody has agreed who answers the enquiries. A faster pipe into a CRM that no one reads gets you leads going cold in a tidier format, and I have seen that project delivered successfully and abandoned inside a month.
What lands on your desk
- The webhook, the guard and the CRM write running in your own n8n and your own Google account, under your credentials
- A junk filter tuned to your traffic, with the domain and phrase lists in plain arrays you can edit without me
- An Exceptions tab recording every rejection with its reason, so nothing is deleted and nothing is unexplained
- A shared secret or signature check on the webhook, so knowing the URL is not the same as permission to write
- An automatic acknowledgement to the enquirer, or that node removed if you would rather reply yourself
- A written walkthrough, so whoever touches it next is not dependent on me
Open the proof
Published case studies of systems that are running. Each links to the thing itself.
The multi-brand operation this pattern runs in ↗Booboo on GitHub (MIT, read the code) ↗The estate-agent version of this flow, as an instant-download kit ↗
Questions this page answers
- What decides a submission is spam?
- I score every submission in a code node before it reaches the sheet. It checks for a filled honeypot and disposable domains, plus short or link-heavy messages and cold-pitch phrases. Every rejection carries its reason, and that reason gets written down each time it fires.
- What happens to rejected submissions?
- Nothing is deleted. Every rejection lands in an Exceptions tab next to its reason, and that tab is the only tuning dial I trust after a fortnight of real traffic.
- Does this cost anything beyond the automation platform?
- I don't put a model call anywhere in this build, so it costs barely anything beyond your automation platform and the Google account you already have.
- Under what volume should I skip this?
- Under about five enquiries a week, skip it. Copying five rows by hand costs ten minutes; this costs an evening plus one more thing that can break on a Sunday.
- Is this available as a free template?
- It is, currently in review on the n8n template library, so you can see every node before deciding whether you want help with it.
Want this built and handed over working?
One line is enough to start. You get an honest answer on fit, and a number rather than a discovery call.
Start a brief