How to send website form submissions to Google Sheets
The most direct way to get form submissions into a spreadsheet is a few lines of Apps Script, deployed as a web app, that adds a row each time your site posts to it. No middleman service is needed. The setup takes ten minutes; the decisions about columns and sharing are what keep the sheet useful a year later.
How it works
Google Apps Script lets a spreadsheet run code in your own Google account. A script with a doPost(e) function, deployed as a web app, gets its own https://script.google.com/macros/s/…/exec address. When your website sends a POST request to that address with the submission as JSON, the script reads e.postData.contents, parses it and calls appendRow to add a line to the sheet. Nothing passes through a third service, and the script runs with your permissions.
Set it up with Anticode
- Create a new Google Sheet, name it clearly ("Website enquiries"), and add a header row: Submitted, Site, Form, Details.
- In Anticode, open Connectors in the dashboard and choose Google Sheets. It shows a short script with a Copy button.
- In your sheet, open Extensions › Apps Script, delete the sample code and paste the script.
- Choose Deploy › New deployment, select Web app, set it to execute as you and to let anyone access it, then deploy. Google will ask you to authorise the script for your account.
- Copy the web app URL that ends in
/execand paste it into the Web app URL field in Anticode. Save and turn it on. - Press Send a test. A row should appear within a few seconds. If it does, submit your live form once to confirm.
Each row holds the time, the site, the form and every field. Anticode's script puts the fields together in the last column as JSON, so a contact form and a booking form can share one sheet without their columns clashing.
Choose columns that stay useful
One JSON column is safe but awkward to sort. If one form feeds the sheet and you want a column per field, edit the script's appendRow line to pull out the fields you care about, for example sheet.appendRow([d.submittedAt, d.form, d.data.name, d.data.email, d.data.message]). Use the field names you see in your test row's JSON, and keep the header row in the same order.
- Keep the timestamp first. It's the one column you'll always sort by.
- Add a status column by hand (New, Replied, Booked) to the right of the script's columns. The script only writes the columns it's given, so your own notes stay put.
- One sheet per purpose. Enquiries and newsletter sign-ups have different retention needs; mixing them makes deleting old data harder.
- Don't rename the first tab casually. The default script writes to the first sheet in the file. If you change the script to use a named sheet, keep that name fixed.
After editing the script, open Deploy › Manage deployments, edit the existing deployment and choose a new version. That keeps the same URL; a brand-new deployment gets a different one, which you'd have to paste into Anticode again.
Keep the sheet from becoming a privacy problem
A spreadsheet of names, emails and phone numbers is personal data, and Sheets makes it very easy to share too widely. Share the file only with named people who need it, never with "anyone with the link". Delete rows you no longer need on a schedule you've written into your privacy policy. Remember the sheet is now one more place the data lives, so list Google Sheets among the services that receive submissions; see how to write a privacy policy for a small website.
The web app URL works like a password: anyone who has it can add rows. Anticode stores it sealed and write-only, so it isn't shown again in the builder or on your site. Don't paste it into public places.
When it doesn't work
- The test fails straight away. Check the URL ends in
/exec, not/dev, and that the deployment lets anyone access it. - Rows stopped arriving after an edit. You probably created a new deployment instead of a new version of the old one, so the URL changed.
- Authorisation errors. Run the deployment again and approve the permissions prompt from the account that owns the sheet.
- A row is missing. Each submission is sent once, without retries. If Google was briefly unavailable, that row won't be added, but the submission is still saved in your Anticode dashboard.
Limits
The connector adds rows; it doesn't update or delete them, and it doesn't read anything back from the sheet. Treat the dashboard as the full record and the sheet as a convenient copy. For heavier workflows, such as routing enquiries to different people or enriching them, a webhook to an automation tool gives you more control.
Questions people ask
Do I need Zapier or Make for this?
No. The Apps Script web app receives submissions directly. Automation tools are useful when you want several steps after each submission.
Can several forms write to one sheet?
Yes. Each row records which form it came from, so you can filter by the Form column.
Is the data safe in Google Sheets?
It's as safe as your Google account and your sharing settings. Turn on two-step verification for the account and share the file with as few people as possible.
Sources
- Google Apps Script: Web Apps, checked
- Google Apps Script reference: Class Sheet, checked