Ayush Paul
Back to Blog

How to Create Custom Google Forms CRM Integration

avatarAyush PaulOctober 24, 2025 (3w ago)8 min read

If you have ever wanted to create a stunning custom contact form but didn't want to deal with backend servers, databases, or complex integrations, this guide is for you.

I'll show you how to build a professional contact form that:

  • Submits to Google Forms (free google sheet storage)
  • Creates tasks in your CRM (ClickUp, in this case)
  • Looks completely custom - no ugly Google Forms UI
  • Works with just frontend code - no backend required

Why This Approach?

Most developers either use Google Forms directly (which looks basic) or build a full backend with database. But there's a middle ground:

Benefits:

  • Free storage - Google Sheets handles all your form data
  • No backend costs - Everything runs in the browser
  • Instant CRM integration - Every submission becomes an actionable task
  • Complete design control - Build any UI you want
  • Easy maintenance - No server to manage

Step 1: Create Your Google Form

First, create a normal Google Form with all the fields you need:

  1. Go to Google Forms
  2. Create a new form
  3. Add fields: Name, Email, Phone, Message, etc.
  4. Important: Set it to not require sign-in

For example, my form has:

  • Full Name (Short answer)
  • Email (Short answer)
  • Phone Number (Short answer)
  • Requirement/Message (Paragraph)

Step 2: Get the Prefilled Link

Here's the magic trick. Google Forms has a hidden feature called "Get pre-filled link":

  1. Open your form
  2. Click the three dots menu (⋮) in the top right
  3. Select "Get pre-filled link"
  4. Fill in dummy values for each field
  5. Click "Get Link"

You'll get a URL like:

https://docs.google.com/forms/d/e/FORM_ID/viewform?entry.123456=John&entry.789012=test@email.com

Notice the entry.XXXXXX parameters? Those are your field IDs.

Step 3: Convert to Form Action URL

Change the URL from viewform to formResponse:

Before:

https://docs.google.com/forms/d/e/YOUR_FORM_ID/viewform?entry.123=test

After:

https://docs.google.com/forms/d/e/YOUR_FORM_ID/formResponse

This is your form submission endpoint.

Step 4: Map Your Field IDs

From the prefilled link, note down each field's entry ID:

// My form field mappings:
// entry.1112309323 = Full Name
// entry.1832877796 = Email
// entry.533660756 = Phone Number
// entry.1198180553 = Message/Requirement

Step 5: Build Your Custom Form

Now create your React component with a beautiful UI:

const ContactForm = () => {
  const [formData, setFormData] = useState({
    firstName: "",
    lastName: "",
    email: "",
    phone: "",
    message: "",
  });
 
  return (
    <form
      method="POST"
      action="https://docs.google.com/forms/d/e/YOUR_FORM_ID/formResponse"
      onSubmit={handleSubmit}
    >
      {/* Hidden combined name field */}
      <input
        type="hidden"
        name="entry.1112309323"
        value={`${formData.firstName} ${formData.lastName}`}
      />
 
      {/* Email field */}
      <input
        type="email"
        name="entry.1832877796"
        value={formData.email}
        onChange={(e) =>
          setFormData((prev) => ({ ...prev, email: e.target.value }))
        }
        required
      />
 
      {/* Phone field */}
      <input
        type="tel"
        name="entry.533660756"
        value={formData.phone}
        onChange={(e) =>
          setFormData((prev) => ({ ...prev, phone: e.target.value }))
        }
        required
      />
 
      {/* Message field */}
      <textarea
        name="entry.1198180553"
        value={formData.message}
        onChange={(e) =>
          setFormData((prev) => ({ ...prev, message: e.target.value }))
        }
        required
      />
 
      <button type="submit">Send Message</button>
    </form>
  );
};

Step 6: Prevent the Redirect to Google Forms

When you submit a form to Google Forms, it automatically redirects users to a Google Forms success page. This breaks the user experience on your custom site.

The solution? A hidden iframe that captures the redirect:

// Add a hidden iframe to your component
<iframe name="hidden_iframe" style={{ display: "none" }}></iframe>
 
// Target the iframe in your form
<form
  method="POST"
  target="hidden_iframe"
  action="https://docs.google.com/forms/d/e/YOUR_FORM_ID/formResponse"
  onSubmit={handleSubmit}
>

How it works:

  • The target="hidden_iframe" attribute tells the browser to load the response inside the iframe
  • Instead of your page redirecting to Google Forms, the success page loads in the hidden iframe
  • Your user stays on your beautiful custom form
  • You can show your own success message

This is a clever workaround that keeps users on your site while still successfully submitting to Google Forms in the background.

Step 7: Add CRM Integration

Now for the powerful part - creating tasks in your CRM automatically. I'm using ClickUp, but you can adapt this for any CRM with an API.

First, get your ClickUp API key:

  1. Go to ClickUp Settings → Apps
  2. Generate an API token
  3. Find your List ID (from the URL when viewing a list)
const submitToClickUp = async (formData) => {
  const fullName = `${formData.firstName} ${formData.lastName}`;
  const fullPhone = `${dialingCodes[formData.countryCode]}${formData.phone}`;
 
  const clickUpData = {
    name: `New Lead: ${fullName}`,
    description: `
      Name: ${fullName}
      Email: ${formData.email}
      Phone: ${fullPhone}
      
      Requirement:
      ${formData.message}
      
      Submitted: ${new Date().toLocaleString()}
    `,
    assignees: [YOUR_USER_ID],
    due_date: Date.now() + 24 * 60 * 60 * 1000, // 24 hours from now
  };
 
  const response = await fetch(
    "https://api.clickup.com/api/v2/list/YOUR_LIST_ID/task",
    {
      method: "POST",
      headers: {
        Authorization: "YOUR_API_KEY",
        "Content-Type": "application/json",
      },
      body: JSON.stringify(clickUpData),
    }
  );
 
  return response.ok;
};

Step 8: Submit to Both Simultaneously

Use Promise.allSettled to submit to both Google Forms and ClickUp at the same time:

const handleSubmit = async (e) => {
  e.preventDefault();
  setIsSubmitting(true);
 
  const form = e.target;
  const data = new FormData(form);
 
  try {
    const [googleFormsResult, clickUpResult] = await Promise.allSettled([
      // Google Forms submission
      fetch(form.action, {
        method: "POST",
        mode: "no-cors",
        body: data,
      }),
      // ClickUp submission
      submitToClickUp(formData),
    ]);
 
    // Show success message
    setIsSuccess(true);
 
    // Reset form after 3 seconds
    setTimeout(() => {
      setFormData({
        firstName: "",
        lastName: "",
        email: "",
        phone: "",
        message: "",
      });
      setIsSuccess(false);
    }, 3000);
  } catch (error) {
    console.error("Error:", error);
  }
};

The Complete Flow

  1. User fills out your beautiful custom form
  2. On submit, data goes to both:
    • Google Forms → stored in Google Sheets (your backup/database)
    • ClickUp API → creates an actionable task with all details
  3. Google's success page loads in the hidden iframe (invisible to user)
  4. You show your own custom success message
  5. You get a notification in ClickUp
  6. Data is safely stored in Google Sheets

Pro Tips

Add Phone Number Validation:

const validatePhone = (phone) => {
  const phoneRegex = /^[0-9]{7,15}$/;
  return phoneRegex.test(phone);
};

Add Country Code Selector:

const dialingCodes = {
  US: "+1",
  IN: "+91",
  UK: "+44",
  CA: "+1",
};

Show Loading States:

{
  isSubmitting ? (
    <div className="animate-spin">⏳</div>
  ) : isSuccess ? (
    <div>✅ Message Sent!</div>
  ) : (
    <div>Send Message</div>
  );
}

Advantages of This Approach

  • Zero backend costs - No servers, no databases to pay for
  • Instant setup - Can be done in 30 minutes
  • Reliable - Google's infrastructure handles storage
  • Flexible - Easy to add more CRM integrations
  • Transparent - All submissions visible in Google Sheets
  • No vendor lock-in - Your data is in Google Sheets, easy to export

Limitations to Know

  • API keys are exposed in frontend (use environment variables in production)
  • Google Forms has rate limits (but they're quite high)
  • No server-side validation (add client-side validation carefully)
  • Because of mode: "no-cors", you can't programmatically confirm Google Forms submission status

Taking It Further

You can extend this to:

  • Send email notifications using EmailJS
  • Integrate with Slack, Discord, or Telegram
  • Connect to Notion databases
  • Trigger Zapier workflows
  • Add to multiple CRMs simultaneously

Real-World Impact

I've used this exact setup for client projects. Every form submission:

  • Gets logged in Google Sheets (searchable database)
  • Creates a ClickUp task (assigned to sales team)
  • Due date set for 24-hour follow-up

No backend. No database. Just smart frontend integration.

The best part? Non-technical team members can access responses directly in Google Sheets, and developers can still use the CRM API for automation.


This approach has saved me countless hours of backend development and hosting costs. Try it out for your next project - you might never go back to traditional form backends.

Questions or improvements? Let me know!

Contact

Get in Touch

Got an idea you want to bring to life? Just shoot me a dm directly on linkedin or drop me an email and I'll respond as soon as possible

Ayush Paul © 2025