Static websites often struggle with the simplest need: a contact form. Portfolio sites, landing pages, and small business pages typically avoid adding a backend just to store a name, email, and message. Meanwhile, popular hosted form services start charging once you want Google Sheet integration or custom branding. A lightweight Google Apps Script web app changes that by turning Google Sheets into a free, real-time contact form database.
How a zero-cost form backend works
The workflow is straightforward. When a visitor submits a form, the frontend sends a POST request to a Google Apps Script web app instead of a traditional server. The script processes the input, writes the data to a Google Sheet, and sends an email alert to the site owner. No database setup, no SMTP configuration, and no recurring hosting bills.
- HTML form → Google Apps Script doPost endpoint
- Data validation and spam filtering inside the script
- Google Sheet acts as the database
- MailApp.sendEmail delivers instant notifications
- Optional autoresponse for website visitors
Deploy the script once, and it runs indefinitely without manual intervention.
Setting up the form handler script
The core of the solution is a doPost function that acts as the API endpoint. It wraps the main logic in error handling so any failure returns a clean JSON response instead of exposing internal errors.
function doPost(e) {
try {
return handlePost(e);
} catch (err) {
console.error(err);
return jsonResponse('error', 'Internal server error.');
}
}Inside handlePost, the script follows a strict sequence:
- Parses incoming data whether it arrives as JSON or form-urlencoded
- Checks a hidden honeypot field for bot activity
- Validates required fields are present and not empty
- Rejects submissions with malformed email addresses
- Filters submissions containing common spam keywords
- Enforces basic rate limiting to block rapid repeats
- Appends a new row to the designated Google Sheet
- Sends a notification email to the site owner
- Optionally dispatches an auto-reply to the visitor
The honeypot technique is especially effective: bots fill every visible field, while humans ignore hidden ones. If the _gotcha field contains a value, the script returns a fake success message and skips writing to the sheet entirely.
Turning Google Sheets into a live database
For contact forms, a spreadsheet is often a better database than a full-fledged SQL instance. It is immediately searchable, exportable to CSV, and familiar to clients who need to review leads. The script creates a dedicated sheet on first run and ensures the correct columns exist.
function ensureSheet(sheetName) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
let sheet = ss.getSheetByName(sheetName);
if (!sheet) {
sheet = ss.insertSheet(sheetName);
sheet.appendRow(['Timestamp', 'Name', 'Email', 'Message', 'Source URL']);
sheet.setFrozenRows(1);
sheet.getRange('D:D').setWrap(true);
}
}New submissions are appended with a single call:
function appendRow(sheetName, row) {
SpreadsheetApp.getActiveSpreadsheet()
.getSheetByName(sheetName)
.appendRow(row);
}Column wrapping keeps long messages readable without truncation.
Sending email alerts without SMTP
Google Apps Script includes MailApp.sendEmail, which removes the need for third-party email services. The script constructs a concise notification containing the visitor’s name, email, and message.
MailApp.sendEmail({
to: cfg.recipientEmail,
subject: 'New Contact Form Submission',
body: `${name} <${email}> sent:\n\n${message}`
});For many small websites, this level of delivery is sufficient. If higher deliverability is needed later, switching to a transactional email provider is always an option.
Connecting the frontend form
The frontend only needs a minimal JavaScript handler that calls the deployed script URL. The example uses fetch with JSON payload including the honeypot field.
const res = await fetch(SCRIPT_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: form.name.value,
email: form.email.value,
message: form.message.value,
_gotcha: form._gotcha.value
})
});
const json = await res.json();Set the Google Apps Script deployment access to “Anyone” and paste the generated URL into your form code. The script handles the rest automatically.
When to use this approach — and when not to
This pattern excels for low-traffic use cases:
- Portfolio and agency contact forms
- Landing page lead capture
- Small business inquiry forms
- Internal request or waitlist signups
- Low-volume lead generation without file uploads
It is not designed for:
- File uploads or large attachments
- Payment processing or e-commerce orders
- High-frequency transactional workloads
- Situations requiring strict GDPR compliance or data deletion workflows
For teams needing a polished setup UI and multi-form management, a paid version of the same script exists, but the open-source version remains fully functional for most needs.
A complete, MIT-licensed implementation with templates, spam filters, rate limiting, and autoresponse logic is available for immediate use. The project balances simplicity with practical features, proving that robust form handling does not require a server or subscription fees.
AI summary
Statik web siteleri için aylık ödeme gerektirmeyen ücretsiz bir iletişim formu arka ucu oluşturmanın yolu: Google Apps Script ve Google E-Tablolar ile nasıl yapılır?