DEV Community

Cover image for Submitting a Next.js Form to Google Sheets
Masaud Ahmod
Masaud Ahmod

Posted on

Submitting a Next.js Form to Google Sheets

Collecting user feedback or leads on a landing page is a must-have feature for modern applications. While setting up a full backend can be heavy for a simple landing page, you can use Google Sheets as a free and reliable database.

In this guide, we’ll build a Contact Form in Next.js (with TypeScript) that stores form submissions directly into a Google Sheet using Google Apps Script.

This method is:
✅ Free
✅ Serverless (no backend required)
✅ Scalable for MVPs & landing pages


🚀 Step 1: Set Up Google Sheet & Apps Script

  1. Create a Google Sheet
  • Go to Google Sheets and create a new sheet.

  • Add headers in the first row: Name, Email, Message, Timestamp.

  1. Open Script Editor
  • In Google Sheets, click: ExtensionsApp Script
  1. Paste Script
function doPost(e) {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var data = JSON.parse(e.postData.contents);

  sheet.appendRow([
    data.name,
    data.email,
    data.message,
    new Date()
  ]);

  return ContentService
    .createTextOutput(JSON.stringify({ status: "success" }))
    .setMimeType(ContentService.MimeType.JSON);
}

Enter fullscreen mode Exit fullscreen mode
  1. Deploy as Web App

⚛️ Step 2: Create Next.js Contact Form Component

Here’s the React component with loading state:

"use client";
import { useState } from "react";

export default function ContactForm() {
  const [form, setForm] = useState({ name: "", email: "", message: "" });
  const [loading, setLoading] = useState(false);

  const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
    setForm({ ...form, [e.target.name]: e.target.value });
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setLoading(true);

    try {
      const res = await fetch("YOUR_GOOGLE_SCRIPT_URL", {
        method: "POST",
        body: JSON.stringify(form),
      });

      const result = await res.json();
      if (result.status === "success") {
        alert("✅ Form submitted successfully!");
        setForm({ name: "", email: "", message: "" });
      } else {
        alert("❌ Something went wrong!");
      }
    } catch (error) {
      console.error(error);
      alert("⚠️ Error submitting form!");
    } finally {
      setLoading(false);
    }
  };

  return (
    <form onSubmit={handleSubmit} className="space-y-4 max-w-md mx-auto">
      <input
        type="text"
        name="name"
        placeholder="Your Name"
        value={form.name}
        onChange={handleChange}
        className="w-full border p-2 rounded"
        required
      />
      <input
        type="email"
        name="email"
        placeholder="Your Email"
        value={form.email}
        onChange={handleChange}
        className="w-full border p-2 rounded"
        required
      />
      <textarea
        name="message"
        placeholder="Your Message"
        value={form.message}
        onChange={handleChange}
        className="w-full border p-2 rounded"
      />
      <button
        type="submit"
        disabled={loading}
        className={`px-4 py-2 rounded text-white ${
          loading ? "bg-gray-400 cursor-not-allowed" : "bg-blue-600"
        }`}
      >
        {loading ? "Submitting..." : "Submit"}
      </button>
    </form>
  );
}

Enter fullscreen mode Exit fullscreen mode

📊 Step 3: Test the Integration

  • Deploy your Next.js project (npm run dev or vercel deploy).

  • Submit the form.

  • Check your Google Sheet → new row should appear with the form data. 🎉


🌟 Why Use This Approach?

  • Fast Setup: No backend required.

  • Cost-effective: 100% free with Google.

  • Easy migration: Later you can replace Google Sheets with a real backend (Node.js, Express, MongoDB).

Top comments (1)

Collapse
 
hashbyt profile image
Hashbyt

Leveraging Google Apps Script with Next.js streamlines serverless form submission, making it easy to collect user data without managing traditional backend infrastructure.