Send Form Submissions to Google Sheets
Collect leads in a spreadsheet without standing up a database, a server, or a paid form plan.
Quick Answer
Point your form's action (or your form builder's webhook setting) at a free Requex URL, connect Google in Settings → Connectors, and map one column per field — {{body.email}}, {{body.message}}. Submissions append as rows. A static site can collect leads this way with no backend at all.
Every static site eventually hits the same wall: the marketing page is a handful of files on a CDN, and then someone wants a contact form. Suddenly the options are a server you did not want to run, a form service with a monthly fee and a submission cap, or an Apps Script endpoint that works until Google changes something.
A webhook plus a spreadsheet is the version with the fewest moving parts. The form posts to a URL, the URL writes a row, and the sheet is a perfectly good CRM for the first few hundred leads.
Option A: a plain HTML form
Point the form at your Requex URL and post JSON with a few lines of script:
<form id="contact">
<input name="email" type="email" required />
<textarea name="message" required></textarea>
<button>Send</button>
</form>
<script>
document.getElementById('contact').addEventListener('submit', async (e) => {
e.preventDefault()
const data = Object.fromEntries(new FormData(e.target))
await fetch('https://api.requex.me/hook/YOUR_ID', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
e.target.reset()
// show your own thank-you state here
})
</script>A native (non-JS) form post works too — the body arrives URL-encoded rather than as JSON, and the templates read the same either way.
Option B: a form builder
Typeform, Tally, Jotform, and Formspree all send webhooks. Paste the Requex URL into their webhook setting, submit a test entry, and read the payload in Requex to see how they nest the answers — each one does it differently. Typeform, for instance, wraps everything in form_response.answers as an array, so map by index: {{body.form_response.answers.0.email}}.
Map the columns
Received at → {{timestamp}}
Email → {{body.email}}
Name → {{body.name}}
Message → {{body.message}}
Page → {{headers.referer}}
Source → {{query.utm_source}}Those last two are the ones people forget and later wish they had. referer tells you which page the form was on, and pulling utm_source off the query string means every lead arrives already attributed to the campaign that produced it — no join required later.
Keeping the spam out
A public URL that writes to a spreadsheet will eventually be found by a bot. Three defences, cheapest first:
- A honeypot field. Add a text input hidden with CSS, named something a bot will fill in like
website. Map it to a column. Any row with a value there is spam, and you can filter or delete on sight. - A shared secret. In Settings → Auth, require a header or query key and have your form send it. Fine for a form builder; less so for a public HTML form, where the value is visible in the page source.
- Turnstile or reCAPTCHA. Verify the token server-side if you have somewhere to do it, or at minimum log it so you can spot a flood.
Also set a max request size in Settings → General. It costs nothing and stops someone posting a megabyte of junk into a cell.
When to graduate off the spreadsheet
A sheet is a great CRM right up until two people edit it at once, or you want automated follow-up, or you cross a few thousand rows and filtering gets slow. At that point keep the webhook and add a second destination rather than migrating — the request log in Requex is still the record of what actually arrived.
Related
Start Testing Webhooks Now
Generate your unique URL and test webhooks instantly. Free, no signup.
Open Webhook Tester →