DEV Community

Mahesh Langote
Mahesh Langote

Posted on

How to Integrate Google Forms with Your Custom-Coded Contact Form

How to Integrate Google Forms with Your Custom Website Contact Form (Free, No Backend)

A complete step-by-step guide for beginners.

Are you tired of paying monthly fees for form submission services? Want to collect form data directly into Google Sheets for free? This guide shows you exactly how to integrate Google Forms with your custom website contact form, no matter what technology you're using (React, HTML, PHP, or any other framework).

What You'll Learn

  • How to create a Google Form and link it to Google Sheets
  • How to find the special field IDs needed for integration
  • How to code your custom form to submit data to Google Forms
  • Real working code examples you can copy and use

Time Required: 15–20 minutes
Cost: 100% FREE
Technical Level: Beginner-friendly (we'll explain everything!)

Why Use Google Forms Integration?

Before we dive in, let's understand why this method is so popular:

  • Completely Free — No monthly subscription fees
  • Automatic Google Sheets Integration — All submissions appear instantly in a spreadsheet
  • No Backend Required — Works with static websites
  • Easy Data Management — Export to Excel, analyze, and share easily
  • Email Notifications — Get notified when someone submits the form
  • Reliable — Powered by Google's infrastructure

Part 1: Creating Your Google Form

Step 1: Create a New Google Form

  1. Go to Google Forms
  2. Click on the "+ Blank" button to create a new form
  3. Give your form a meaningful title (e.g., "Website Contact Form")

Step 2: Add Your Form Fields

Now, let's add the fields that match your contact form. For our example, we need:

  • Full Name
  • Email Address
  • Phone Number
  • Message

For each field:

  1. Click "+ Add question" (the plus icon on the right)
  2. Enter the question/label (e.g., "Full Name")
  3. Select the question type:
    • Short answer for Name, Email, Phone
    • Paragraph for Message
  4. Toggle "Required" ON for all fields
  5. Click Done

Pro Tip: Add Email Validation

  1. Click the three dots (⋮) on the Email question
  2. Select "Response validation"
  3. Choose "Text""Email"
  4. This ensures only valid email addresses are accepted

Step 3: Link Form to Google Sheets

This is where the magic happens! Every form submission will automatically appear in a spreadsheet.

  1. Click the "Responses" tab at the top
  2. Click the Google Sheets icon (green spreadsheet icon)
  3. Select "Create a new spreadsheet"
  4. Give it a name (e.g., "Contact Form Responses")
  5. Click Create

Your Google Sheet will open automatically. You'll see column headers matching your form fields. Every submission will appear as a new row with a timestamp!

Part 2: Finding Your Form Field IDs

This is the most important step! We need to find special ID numbers that Google assigns to each form field.

Step 4: Get the Form's Pre-filled Link (optional)

  1. Go back to your Google Form
  2. Click the three dots (⋮) in the top-right corner
  3. Select "Get pre-filled link"
  4. Fill in some dummy data in each field (e.g., "Test Name", "test@email.com", "1234567890", "Test message")
  5. Click "Get link" at the bottom
  6. Click "Copy link"
  7. Open a text editor (Notepad, VS Code, or any text editor)
  8. Paste the copied URL

The URL will look something like this:

https://docs.google.com/forms/d/e/1FD_u0oGFWMDp0C9PBa1EKmQ/formResponse
Enter fullscreen mode Exit fullscreen mode

Look for the entry.XXXXXXXX numbers — these are your field IDs!

Understanding the Field IDs

Let me break down what each part means:

entry.2022495458     This is the Full Name field ID
entry.1831963579     This is the Email Address field ID
entry.330449643      This is the Phone Number field ID
entry.1694943240     This is the Message field ID
Enter fullscreen mode Exit fullscreen mode

Create a Mapping Table

Pro Tip: Create a mapping table for easy reference:

Form Field Entry ID
Full Name entry.2022495458
Email Address entry.1831963579
Phone Number entry.330449643
Message entry.1694943240

Step 6: Get the Form Submission URL

Look at the URL again. Find the long ID in the middle (between /d/e/ and /viewform):

1FAIpQLSckkgNbSSRu6GBHQ1C7WMWvDHgDp0C9PBa1EKmQ
Enter fullscreen mode Exit fullscreen mode

Your submission URL will be:

https://docs.google.com/forms/d/e/[YOUR_FORM_ID]/formResponse
Enter fullscreen mode Exit fullscreen mode

Replace [YOUR_FORM_ID] with the ID you just copied. Example:

https://docs.google.com/forms/d/e/1FAIpQQ1C7OlFD_u0oGFWMWvDHgDp0C9PBa1EKmQ/formResponse
Enter fullscreen mode Exit fullscreen mode

Part 3: Coding Your Custom Form

Now comes the fun part — connecting your custom form to Google Forms!

Step 7: Understanding the Code Structure

Here's what our code needs to do:

  1. Capture form data when the user clicks Submit
  2. Create a FormData object with the Google Form field IDs
  3. Send the data to Google Forms using the Fetch API
  4. Show success/error messages to the user

Step 8: Complete React Example

Here's a fully functional React contact form component:

import React, { useState } from 'react';

const ContactForm = () => {
  // State to store form data
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    phone: '',
    message: ''
  });

  // State for loading and status messages
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [submitStatus, setSubmitStatus] = useState('');

  // Handle input changes
  const handleChange = (e) => {
    setFormData({
      ...formData,
      [e.target.name]: e.target.value
    });
  };

  // Handle form submission
  const handleSubmit = async (e) => {
    e.preventDefault();
    setIsSubmitting(true);
    setSubmitStatus('');

    // Basic validation
    if (!formData.name.trim() || !formData.email.trim() ||
        !formData.phone.trim() || !formData.message.trim()) {
      setSubmitStatus('error');
      setIsSubmitting(false);
      return;
    }

    try {
      // YOUR Google Form submission URL
      const formURL = 'https://docs.google.com/forms/d/e/YOUR_FORM_ID_HERE/formResponse';

      // Create FormData with YOUR field IDs
      const formDataToSubmit = new FormData();
      formDataToSubmit.append('entry.YOUR_NAME_FIELD_ID', formData.name.trim());
      formDataToSubmit.append('entry.YOUR_EMAIL_FIELD_ID', formData.email.trim());
      formDataToSubmit.append('entry.YOUR_PHONE_FIELD_ID', formData.phone.trim());
      formDataToSubmit.append('entry.YOUR_MESSAGE_FIELD_ID', formData.message.trim());

      // Submit to Google Form
      await fetch(formURL, {
        method: 'POST',
        mode: 'no-cors', // Important for Google Forms
        body: formDataToSubmit
      });

      // Show success message
      setSubmitStatus('success');

      // Clear the form
      setFormData({
        name: '',
        email: '',
        phone: '',
        message: ''
      });

      // Auto-clear success message after 5 seconds
      setTimeout(() => setSubmitStatus(''), 5000);
    } catch (error) {
      console.error('Error submitting form:', error);
      setSubmitStatus('error');
      setTimeout(() => setSubmitStatus(''), 5000);
    } finally {
      setIsSubmitting(false);
    }
  };

  return (
    <div className="max-w-2xl mx-auto p-6">
      <h2 className="text-3xl font-bold mb-6">Contact Us</h2>

      {/* Success Message */}
      {submitStatus === 'success' && (
        <div className="mb-6 p-4 bg-green-100 text-green-700 rounded-lg">
          ✅ Message sent successfully! We'll get back to you soon.
        </div>
      )}

      {/* Error Message */}
      {submitStatus === 'error' && (
        <div className="mb-6 p-4 bg-red-100 text-red-700 rounded-lg">
          ❌ Please fill in all fields correctly and try again.
        </div>
      )}

      <form onSubmit={handleSubmit} className="space-y-6">
        {/* Name Field */}
        <div>
          <label className="block font-medium mb-2">
            Full Name *
          </label>
          <input
            type="text"
            name="name"
            value={formData.name}
            onChange={handleChange}
            required
            className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500"
            placeholder="Enter your full name"
          />
        </div>

        {/* Email Field */}
        <div>
          <label className="block font-medium mb-2">
            Email Address *
          </label>
          <input
            type="email"
            name="email"
            value={formData.email}
            onChange={handleChange}
            required
            className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500"
            placeholder="Enter your email address"
          />
        </div>

        {/* Phone Field */}
        <div>
          <label className="block font-medium mb-2">
            Phone Number *
          </label>
          <input
            type="tel"
            name="phone"
            value={formData.phone}
            onChange={handleChange}
            required
            className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500"
            placeholder="Enter your phone number"
          />
        </div>

        {/* Message Field */}
        <div>
          <label className="block font-medium mb-2">
            Message *
          </label>
          <textarea
            name="message"
            value={formData.message}
            onChange={handleChange}
            required
            rows={6}
            className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500"
            placeholder="Tell us how we can help you..."
          />
        </div>

        {/* Submit Button */}
        <button
          type="submit"
          disabled={isSubmitting}
          className="w-full py-3 px-6 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:bg-gray-400"
        >
          {isSubmitting ? 'Sending...' : 'Send Message'}
        </button>
      </form>
    </div>
  );
};

export default ContactForm;
Enter fullscreen mode Exit fullscreen mode

Step 9: Customize the Code with Your Field IDs

Important: You MUST replace these placeholders with YOUR actual values:

  • Replace YOUR_FORM_ID_HERE with your Google Form ID
  • Replace YOUR_NAME_FIELD_ID with your actual name field entry ID
  • Replace YOUR_EMAIL_FIELD_ID with your actual email field entry ID
  • Replace YOUR_PHONE_FIELD_ID with your actual phone field entry ID
  • Replace YOUR_MESSAGE_FIELD_ID with your actual message field entry ID

Example with Real IDs

const formURL = 'https://docs.google.com/forms/d/e/1FAIpQLSckkgNbSSRu6GBHQ1C7OlFD_u0oGFWMWvDHgDp0C9PBa1EKmQ/formResponse';

formDataToSubmit.append('entry.2022495458', formData.name.trim());
formDataToSubmit.append('entry.1831963579', formData.email.trim());
formDataToSubmit.append('entry.330449643', formData.phone.trim());
formDataToSubmit.append('entry.1694943240', formData.message.trim());
Enter fullscreen mode Exit fullscreen mode

Part 4: Alternative Implementations

For Plain HTML + JavaScript

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Contact Form</title>
    <style>
        .form-container {
            max-width: 600px;
            margin: 50px auto;
            padding: 20px;
        }
        .form-group {
            margin-bottom: 20px;
        }
        label {
            display: block;
            margin-bottom: 5px;
            font-weight: bold;
        }
        input, textarea {
            width: 100%;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 5px;
        }
        button {
            background-color: #007bff;
            color: white;
            padding: 12px 30px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
        }
        button:disabled {
            background-color: #ccc;
        }
        .success {
            background-color: #d4edda;
            color: #155724;
            padding: 15px;
            border-radius: 5px;
            margin-bottom: 20px;
        }
        .error {
            background-color: #f8d7da;
            color: #721c24;
            padding: 15px;
            border-radius: 5px;
            margin-bottom: 20px;
        }
    </style>
</head>
<body>
    <div class="form-container">
        <h2>Contact Us</h2>
        <div id="message" style="display: none;"></div>
        <form id="contactForm">
            <div class="form-group">
                <label>Full Name *</label>
                <input type="text" id="name" required>
            </div>
            <div class="form-group">
                <label>Email Address *</label>
                <input type="email" id="email" required>
            </div>
            <div class="form-group">
                <label>Phone Number *</label>
                <input type="tel" id="phone" required>
            </div>
            <div class="form-group">
                <label>Message *</label>
                <textarea id="message-text" rows="6" required></textarea>
            </div>
            <button type="submit" id="submitBtn">Send Message</button>
        </form>
    </div>

    <script>
        const form = document.getElementById('contactForm');
        const submitBtn = document.getElementById('submitBtn');
        const messageDiv = document.getElementById('message');

        form.addEventListener('submit', async (e) => {
            e.preventDefault();
            submitBtn.disabled = true;
            submitBtn.textContent = 'Sending...';
            messageDiv.style.display = 'none';

            // Get form values
            const name = document.getElementById('name').value.trim();
            const email = document.getElementById('email').value.trim();
            const phone = document.getElementById('phone').value.trim();
            const messageText = document.getElementById('message-text').value.trim();

            // YOUR Google Form URL
            const formURL = 'https://docs.google.com/forms/d/e/YOUR_FORM_ID_HERE/formResponse';

            // Create FormData with YOUR field IDs
            const formData = new FormData();
            formData.append('entry.YOUR_NAME_FIELD_ID', name);
            formData.append('entry.YOUR_EMAIL_FIELD_ID', email);
            formData.append('entry.YOUR_PHONE_FIELD_ID', phone);
            formData.append('entry.YOUR_MESSAGE_FIELD_ID', messageText);

            try {
                await fetch(formURL, {
                    method: 'POST',
                    mode: 'no-cors',
                    body: formData
                });

                // Show success message
                messageDiv.className = 'success';
                messageDiv.textContent = "✅ Message sent successfully! We'll get back to you soon.";
                messageDiv.style.display = 'block';

                // Clear form
                form.reset();

                // Hide message after 5 seconds
                setTimeout(() => {
                    messageDiv.style.display = 'none';
                }, 5000);
            } catch (error) {
                // Show error message
                messageDiv.className = 'error';
                messageDiv.textContent = '❌ Something went wrong. Please try again.';
                messageDiv.style.display = 'block';
            } finally {
                submitBtn.disabled = false;
                submitBtn.textContent = 'Send Message';
            }
        });
    </script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

For jQuery

$('#contactForm').on('submit', function(e) {
    e.preventDefault();
    $('#submitBtn').prop('disabled', true).text('Sending...');

    var formURL = 'https://docs.google.com/forms/d/e/YOUR_FORM_ID_HERE/formResponse';
    var formData = new FormData();
    formData.append('entry.YOUR_NAME_FIELD_ID', $('#name').val().trim());
    formData.append('entry.YOUR_EMAIL_FIELD_ID', $('#email').val().trim());
    formData.append('entry.YOUR_PHONE_FIELD_ID', $('#phone').val().trim());
    formData.append('entry.YOUR_MESSAGE_FIELD_ID', $('#message').val().trim());

    $.ajax({
        url: formURL,
        type: 'POST',
        data: formData,
        processData: false,
        contentType: false,
        success: function() {
            alert('✅ Message sent successfully!');
            $('#contactForm')[0].reset();
        },
        error: function() {
            alert('✅ Message sent successfully!'); // Still success with no-cors
            $('#contactForm')[0].reset();
        },
        complete: function() {
            $('#submitBtn').prop('disabled', false).text('Send Message');
        }
    });
});
Enter fullscreen mode Exit fullscreen mode

Part 5: Testing Your Integration

Step 10: Test the Form

  1. Fill out your custom form on your website
  2. Click the Submit button
  3. Check your Google Sheet — you should see a new row with the submission!
  4. Check the timestamp — it should show the current date and time

Common Testing Issues and Solutions

Issue 1: "No data appearing in Google Sheet"

Solutions:

  • Double-check your field IDs are correct
  • Make sure you're using /formResponse not /viewform in the URL
  • Verify the Google Form is not restricted to your organization

Issue 2: "CORS error in console"

Solution: This is normal! Using mode: 'no-cors' prevents you from reading the response, but the submission still works. The CORS error in the console doesn't mean it failed.

Issue 3: "Form submits but fields are empty in Sheet"

Solutions:

  • Your field IDs might be wrong
  • Generate a new pre-filled link and extract IDs again

Security Best Practices

Important Security Considerations

  • Never expose sensitive data — Don't collect passwords or payment info through Google Forms
  • Validate user input — Always validate email format, phone numbers, etc.
  • Rate limiting — Consider adding rate limiting to prevent spam
  • HTTPS only — Always use your form on HTTPS websites
  • Privacy policy — Add a link to your privacy policy near the form

Example Input Validation

// Email validation
const isValidEmail = (email) => {
    const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return regex.test(email);
};

// Phone validation (adjust for your country)
const isValidPhone = (phone) => {
    const regex = /^[\d\s\-\+\(\)]+$/;
    return regex.test(phone) && phone.replace(/\D/g, '').length >= 10;
};

// Add to your handleSubmit function
if (!isValidEmail(formData.email)) {
    alert('Please enter a valid email address');
    return;
}

if (!isValidPhone(formData.phone)) {
    alert('Please enter a valid phone number');
    return;
}
Enter fullscreen mode Exit fullscreen mode

Troubleshooting Guide

Problem: Submissions not appearing in Google Sheet

Solutions:

  • Verify the form URL ends with /formResponse
  • Check that field IDs match exactly (including the "entry." prefix)
  • Make sure the Google Form is published and accepting responses
  • Check if there are any errors in the browser console

Problem: Getting CORS errors

Solution: This is expected! Using mode: 'no-cors' means you can't read the response, but the submission still works. The CORS error in the console doesn't mean it failed.

Problem: Form submits multiple times

Solution: Make sure you're properly disabling the submit button:

setIsSubmitting(true); // At the start
setIsSubmitting(false); // In the finally block
Enter fullscreen mode Exit fullscreen mode

Problem: Special characters not showing correctly

Solution: Use .trim() on all inputs and ensure proper encoding:

formDataToSubmit.append('entry.123456', formData.name.trim());
Enter fullscreen mode Exit fullscreen mode

Best Practices for Production

User Experience Tips

  • Clear feedback — Always show loading states and success/error messages
  • Fast response — Show success immediately (don't wait for confirmation)
  • Form validation — Validate before submission to reduce errors
  • Accessible forms — Use proper labels and ARIA attributes
  • Mobile-friendly — Test on mobile devices

Performance Optimization

// Debounce form submissions to prevent double-clicks
const debounce = (func, wait) => {
    let timeout;
    return function executedFunction(...args) {
        const later = () => {
            clearTimeout(timeout);
            func(...args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
};

// Use it
const debouncedSubmit = debounce(handleSubmit, 1000);
Enter fullscreen mode Exit fullscreen mode

Monitoring and Analytics

Track form submissions with Google Analytics:

// After successful submission
if (window.gtag) {
    window.gtag('event', 'form_submission', {
        'event_category': 'Contact',
        'event_label': 'Contact Form'
    });
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Congratulations! 🎉 You now know how to:

  • Create a Google Form and connect it to Google Sheets
  • Extract field IDs from your form
  • Write code to submit data from custom forms to Google Forms
  • Handle success and error states
  • Implement the solution in multiple frameworks
  • Troubleshoot common issues

Key Takeaways

  • Google Forms integration is completely free
  • All data is automatically stored in Google Sheets
  • You can use this with any website technology
  • The mode: 'no-cors' setting is required for Google Forms
  • Always validate user input before submission

Frequently Asked Questions

Q: Is this method completely free?
A: Yes! Google Forms and Google Sheets are free to use.

Q: How many submissions can I receive?
A: Google Sheets can handle up to 5 million cells, which is plenty for most use cases.

Q: Can I customize the confirmation email?
A: Yes, but you'll need to use Google Apps Script or a third-party add-on.

Q: Will this work on WordPress?
A: Absolutely! You can add this JavaScript code to any WordPress site.

Q: Can I export the data?
A: Yes, from Google Sheets you can export to Excel, CSV, or PDF.

Q: Is my data secure?
A: Data is stored in your Google Drive with Google's security measures. However, don't collect highly sensitive information through this method.

Q: Can I edit submissions after they're received?
A: Yes, you can edit any data directly in the Google Sheet.

Q: What if I need to add more fields later?
A: Just add new questions to your Google Form, get the new field IDs, and update your code.

Need Help?

If you run into any issues implementing this:

  • Double-check all field IDs are correct
  • Verify your form URL ends with /formResponse
  • Test in an incognito window to rule out browser extensions
  • Check the browser console for specific error messages

Still stuck? Leave a comment below with:

  • Your error message (if any)
  • What you've tried so far
  • Screenshots of your setup

I respond to all comments and will help you troubleshoot!


Tags: #webdev #googleforms #react #javascript

Last updated: November 2024

Did this guide help you? Give it a ⭐ and share your success story in the comments below!

Top comments (0)