You have a form on your website and you want the data in Google Sheets. You don't want to spin up an Express server, deploy Firebase functions, or manage a database. You just need form submissions in a spreadsheet.
This is one of the most common problems in web development. In this guide, we'll cover every way to solve it — from a 60-second setup with Sheet Monkey, to the free DIY approach with Google Apps Script, to third-party form services and full CRUD APIs. Each method includes working code you can copy and use today.
Why Skip the Backend?
Writing a backend server to handle form submissions means:
- Hosting costs. You need a server running 24/7. Even a cheap VPS is $5–10/month. Serverless functions still have costs at scale.
- Complexity. Authentication, CORS headers, error handling, rate limiting, data validation — there's more code to write than you'd think.
- Maintenance. Servers crash, dependencies have security patches, APIs change. Every backend is a thing you have to keep running.
- Time. Setting up a backend for form handling takes hours. Most of that time is boilerplate you'll never think about again.
For form submissions that go into a Google Sheet, a backend server is almost always overkill. Google Sheets is free, your team already knows how to use it, and it comes with built-in collaboration, formulas, charts, and sharing. The only question is how to get data into it.
Method 1: Sheet Monkey (60-Second Setup, Recommended)
Sheet Monkey gives you a URL that you set as your form's action. When someone submits the form, the data goes directly into your Google Sheet. No backend, no middleware, no polling.
Working example (5 lines of HTML)
<form action="https://api.sheetmonkey.io/form/YOUR_ID" method="POST"> <input type="text" name="Name" placeholder="Name" required /> <input type="email" name="Email" placeholder="Email" required /> <textarea name="Message" placeholder="Message"></textarea> <button type="submit">Send</button> </form>
That's a fully working form that sends data to Google Sheets. No JavaScript, no backend, no build process.
How it works under the hood
- The browser sends a POST request to Sheet Monkey's endpoint.
- Sheet Monkey authenticates with Google on your behalf (credentials are stored securely in Sheet Monkey's cloud, not on your site).
- Sheet Monkey writes the data to your Google Sheet using the Sheets API.
- The user sees a success message or is redirected to your thank-you page.
The entire round-trip takes less than a second.
Features you get for free
Even on Sheet Monkey's free tier (100 submissions/month), you get:
- Automatic timestamps on every submission
- File uploads — just add
<input type="file" name="Resume">and files are stored with links in your sheet - Email notifications — get an email when someone submits
- Autoresponder emails — send confirmation emails to submitters automatically
- Custom redirects — redirect to a thank-you page after submission
- Write-only security — your endpoint can only write to your sheet, never read from it
AJAX submission (no page redirect)
If you want the form to submit without leaving the page:
const form = document.querySelector('form'); form.addEventListener('submit', async (e) => { e.preventDefault(); const response = await fetch(form.action, { method: 'POST', body: new FormData(form), }); if (response.ok) { alert('Form submitted successfully!'); form.reset(); } });
No CORS issues. Sheet Monkey handles cross-origin requests properly.
Pros:
- Setup in under a minute
- No backend code to write or maintain
- File uploads, notifications, autoresponders built in
- Works with any HTML form on any platform
- Write-only security model
- AJAX submissions work without CORS issues
Cons:
- Free tier limited to 100 submissions/month
- Paid plans start at $5/month for unlimited (see pricing)
Method 2: Google Apps Script (Free, But Complex)
Google Apps Script lets you write server-side JavaScript that runs inside Google's infrastructure. You can create a web app that receives form data and writes it to a Google Sheet. It's free but requires coding and has limitations.
Step 1: Create your Google Sheet
Create a new Google Sheet and add column headers in the first row that match your form field names. For example: Name, Email, Message.
Step 2: Open the Apps Script editor
Go to Extensions > Apps Script in your Google Sheet. This opens the script editor.
Step 3: Add the script
Delete any existing code and paste this:
function doPost(e) { var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0]; var row = []; for (var i = 0; i < headers.length; i++) { if (headers[i] === 'Timestamp') { row.push(new Date()); } else { row.push(e.parameter[headers[i]] || ''); } } sheet.appendRow(row); return ContentService .createTextOutput(JSON.stringify({ result: 'success' })) .setMimeType(ContentService.MimeType.JSON); }
Step 4: Deploy as a web app
- Click Deploy > New deployment.
- Select Web app as the type.
- Set "Execute as" to Me and "Who has access" to Anyone.
- Click Deploy and copy the web app URL.
Step 5: Create your HTML form
<form action="YOUR_APPS_SCRIPT_URL" method="POST"> <input type="text" name="Name" placeholder="Your name" required /> <input type="email" name="Email" placeholder="Your email" required /> <textarea name="Message" placeholder="Your message" required></textarea> <button type="submit">Send</button> </form>
The downsides of Apps Script
This method is free and uses Google's own infrastructure, but it has real problems:
- CORS issues. If you submit the form via JavaScript (fetch or XMLHttpRequest), you'll hit CORS errors. The form must submit as a traditional POST, which means a full page redirect.
- Debugging is painful. Apps Script errors don't show up in your browser console. You have to check the Apps Script execution log, which is often unhelpful.
- Maintenance burden. When Google updates the Apps Script runtime or changes API behavior, your script can break without warning.
- No features. No file uploads, no email notifications, no autoresponders, no custom redirects. Just raw data into a sheet.
- Rate limits. Google imposes quotas on Apps Script executions that can silently drop submissions during traffic spikes.
Pros:
- Completely free
- No third-party service required
- Runs on Google's infrastructure
Cons:
- CORS issues with JavaScript submissions
- Painful debugging experience
- Breaks when Google updates APIs
- No file uploads, notifications, or autoresponders
- Rate limits can drop submissions silently
Method 3: Other Services and APIs
There are other services that can accept form data, but most don't send it directly to Google Sheets.
Formspree
Formspree is a form backend that sends submissions to your email. It doesn't have native Google Sheets integration — you'd need Zapier ($20+/month) to bridge the gap. Free tier: 50 submissions/month. See our detailed comparison.
fetch('https://formspree.io/f/YOUR_ID', { method: 'POST', body: new FormData(form), headers: { 'Accept': 'application/json' } });
Web3Forms
Web3Forms is free (250 submissions/month) and sends to email. Like Formspree, no native Google Sheets connection.
Full CRUD APIs (SheetDB, Sheet.best)
Services like SheetDB and Sheet.best turn your Google Sheet into a full REST API — you can GET rows, POST new rows, PUT updates, and DELETE rows. They're designed for apps that need to read data back from the sheet, not just collect form submissions.
// Read all rows const data = await fetch('https://sheetdb.io/api/v1/YOUR_ID').then(r => r.json()); // Add a row await fetch('https://sheetdb.io/api/v1/YOUR_ID', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ Name: 'John', Email: 'john@example.com' }), });
Full CRUD APIs make sense for prototype backends, dynamic content, or internal tools. But for form submissions on a public website, they're overkill — and the read access means your sheet data is exposed via the API. More on this in the security section.
The common problem with non-Sheets services
Formspree, Web3Forms, and similar tools store your data on their servers or send it to your email. None of them write directly to Google Sheets. To get data into a sheet, you need Zapier or a similar tool — which adds cost, complexity, and latency.
Comparison: Which Method Is Best?
| Feature | Sheet Monkey | Apps Script | Formspree + Zapier | SheetDB |
|---|---|---|---|---|
| Price | Free (100/mo) | Free | $20+/month | $7/month |
| Setup | Under 1 minute | 30+ minutes | 15 minutes | 10 minutes |
| Google Sheets native | Yes | Yes | No (requires Zapier) | Yes |
| File uploads | Yes | No | Paid only | No |
| Autoresponder | Yes | No | No | No |
| Custom redirects | Yes | No | Yes | No |
| AJAX support | No CORS issues | CORS issues | Works | Works |
| Maintenance | None | You maintain it | Managed | Managed |
| Write-only security | Yes | Depends on script | N/A | No (full read access) |
Security: Write-Only vs. Read-Write
This is the most important decision when using Google Sheets as a form backend. Your form's action URL is visible in your HTML source — anyone can see it by viewing your page source. That means the endpoint needs to be safe to expose.
Write-only endpoints (Sheet Monkey)
Sheet Monkey endpoints can only add rows to your spreadsheet. They cannot read, modify, or delete data. If someone reverse-engineers your endpoint URL, they can only submit new form entries. They can't see what's already in the sheet.
This is the correct security model for public-facing forms.
Read-write endpoints (SheetDB, Sheet.best)
Full CRUD API endpoints can read every row in your sheet. Anyone with the API URL can see all submitted data — names, emails, messages, everything. For internal tools or prototypes this might be acceptable. For public-facing forms, it's a problem.
Apps Script
Your script controls what data is returned in the response. If your doPost function only writes and returns a success message, it's effectively write-only. But there's no architectural guarantee — it depends on what you put in the code.
Credential storage
- Sheet Monkey: Google credentials stored in Sheet Monkey's secure cloud, never on your site.
- WordPress plugins: Many store Google API credentials in the WordPress database (a common attack target).
- Apps Script: Runs under your Google account. The web app URL is the only credential.
Rate limiting and spam protection
- Sheet Monkey: Built-in rate limiting and spam protection prevent abuse.
- SheetDB/Sheet.best: Varies by plan.
- Apps Script: Google imposes quotas. During traffic spikes, submissions can be silently dropped. You'll need to implement spam protection yourself.
When Google Sheets Is the Right Backend
Great for
- Under 10,000 rows. Google Sheets handles up to ~10 million cells, but performance degrades with large datasets. For form submissions (hundreds to low thousands of rows), it's perfect.
- Form submissions. Contact forms, signups, surveys, feedback forms, order forms, lead capture. Write-only access is ideal.
- Simple data. Flat data that fits naturally in rows and columns.
- Team visibility. When non-technical team members need to see and analyze the data.
- Prototyping. When you're testing an idea and don't want to set up infrastructure.
Not great for
- Real-time applications. Sheets isn't a real-time database. If you need WebSocket connections or sub-second updates, use a real database.
- Complex queries. JOINs, nested queries, and complex aggregations are awkward or impossible in Sheets.
- High throughput. If you're receiving thousands of submissions per hour, Google Sheets API rate limits will be a bottleneck.
- Relational data. If your data has relationships (users have orders, orders have items), a relational database is a better fit.
- Sensitive data. While Sheet Monkey endpoints are write-only, Google Sheets itself isn't designed for sensitive data storage (PII, payment info). Use a proper database with encryption for that.
Adding Features Without a Backend
Once your basic form is working, you can add features without writing any backend code.
File uploads without a server
With Sheet Monkey, file uploads work with just an HTML input:
<input type="file" name="Document" />
The file is stored securely and a link appears in your Google Sheet. No server-side file handling code needed. See our file uploads guide.
Custom redirects
Redirect users to a thank-you page after submission:
<input type="hidden" name="_redirect" value="https://yoursite.com/thank-you" />
Autoresponder emails without a server
Send confirmation emails to form submitters automatically. Configure the template in your Sheet Monkey dashboard using Handlebars syntax:
Hi {{Name}}, thanks for reaching out! We'll get back to you within 24 hours.
No email server, no SendGrid, no Mailchimp. See our autoresponder guide.
UTM tracking without analytics tools
Capture ad campaign data (utm_source, utm_medium, utm_campaign) in hidden form fields and send them to your Google Sheet alongside the submission data:
<input type="hidden" name="utm_source" id="utm_source" /> <input type="hidden" name="utm_medium" id="utm_medium" /> <input type="hidden" name="utm_campaign" id="utm_campaign" /> <script> const params = new URLSearchParams(window.location.search); ['utm_source', 'utm_medium', 'utm_campaign'].forEach(param => { const el = document.getElementById(param); if (el) el.value = params.get(param) || ''; }); </script>
Analyze conversion data directly in Google Sheets with COUNTIF and QUERY formulas. See our UTM tracking guide.
Framework and Platform Guides
Sheet Monkey works with any frontend framework or website platform. Here are framework-specific examples:
React
function ContactForm() { const handleSubmit = async (e) => { e.preventDefault(); const data = new FormData(e.target); await fetch('https://api.sheetmonkey.io/form/YOUR_ID', { method: 'POST', body: data, }); e.target.reset(); }; return ( <form onSubmit={handleSubmit}> <input type="text" name="Name" required /> <input type="email" name="Email" required /> <button type="submit">Send</button> </form> ); }
See the full guide: React forms to Google Sheets.
Vue
<template> <form @submit.prevent="handleSubmit"> <input v-model="name" type="text" name="Name" required /> <input v-model="email" type="email" name="Email" required /> <button type="submit">Send</button> </form> </template> <script> export default { data() { return { name: '', email: '' }; }, methods: { async handleSubmit(e) { await fetch('https://api.sheetmonkey.io/form/YOUR_ID', { method: 'POST', body: new FormData(e.target), }); this.name = ''; this.email = ''; }, }, }; </script>
See the full guide: Vue forms to Google Sheets.
Next.js
Sheet Monkey works with Next.js static exports and server-rendered pages. Just use a standard form action or the fetch approach above. No API routes needed.
Platform guides
Sheet Monkey works with every major website platform:
- Webflow — Set the form action in the designer
- Carrd — Custom form type with action URL
- Squarespace — Code block with custom form
- WordPress — CF7 plugin or custom form action
- GitHub Pages — Standard HTML form
Frequently Asked Questions
Can I use this with any website builder?
Yes. If your website builder supports HTML forms with a custom action attribute, it works with Sheet Monkey. This includes Webflow, Carrd, Squarespace, WordPress, Wix (with custom code), and any static site.
Is my data secure?
Sheet Monkey endpoints are write-only. They can add rows to your Google Sheet but can never read data from it. Your existing spreadsheet data is always protected. See our security documentation for more details.
How many submissions can I send?
Sheet Monkey's free tier includes 100 submissions per month. Unlimited plans start at $5/month. See our pricing page for details.
Can I submit the form without a page redirect?
Yes. Use JavaScript's fetch API to submit the form data via AJAX. Sheet Monkey handles CORS properly, so fetch submissions work from any domain. See the AJAX example above.
Does this work with Google Workspace (business) accounts?
Yes. Sheet Monkey works with both personal Google accounts and Google Workspace accounts.
When should I use a full CRUD API instead?
If your app needs to read data back from Google Sheets (not just write to it), use a full CRUD service like SheetDB. Common use cases: prototype backends, dynamic page content from a spreadsheet, or internal admin tools. For form submissions on public websites, write-only endpoints are safer and simpler.
Get Started
No backend required. Submit your first form to Google Sheets free with Sheet Monkey — 100 submissions/month, setup in under a minute.