So today, I was creating an input section on a new website and I really wanted to automatically submit the responses to a Google Form. In the end, I wanted to do a basic HTML form with an action to Google, and luckily after a little testing I figured it out.
And yes. I do know this probably isn't the safest way to do things, but it was the most efficient and easiest for a simple POC I am making.
From the start, I tried to directly post to a Google Form with fields I assumed would work.
POST /forms/d/e/<formID>? HTTP/1.1
Host: docs.google.com
Content-Type: application/json
{"name": "Kenton", "email": "test@test.com"}
However, I was quickly met with a 404 :( Nothing too scary though, lets see if adding view form would work.
POST /forms/d/e/<formID>/viewform HTTP/1.1
Host: docs.google.com
Content-Type: application/json
{"name": "Kenton", "email": "test@test.com"}
Presumably, this fails. It sends a 405 HTTP code, meaning that the method wasn't allowed. This was caused by sending a POST request to a GET endpoint.
Stumped, I decided to go to Google. But, instead of just Googling things, lets learn how to get the correct endpoint when you aren't exactly sure.
As an example, here is a test form that I setup. It simply captures a name and email.
Now that we have our form, let's open up the preview. After we have the preview open, open the Chrome Developer Tools and go to the network panel. Make sure you toggle "Preserve Log" from the top bar. This will let us see network traffic even after we've been redirected.
Great! Now, lets type in some fake input (make sure you remember what you typed in, it will become useful later) and submit it. Once you do so, you will see your network panel blow up with requests. It should look similar to below:
While it may seem daunting at first, fear not. The only thing you need to look at is at the very top of the list where it says "formResponse"
Once you click in there, scroll to the very bottom of the Headers section until you find the Form Data section. Now, you will notice some odd things. Mainly, the field names aren't exactly what one would first assume considering what I named "Name" is now entry.3403608
(expect that number to be different than yours). This is why submitting recognizable information in the previous section was important. This allows us to easily recognize which field goes where.
Now, to double check that Google isn't playing tricks, we should do the submission process again, however I've discovered it doesn't change in between requests. Phew.
Cool. Now, we discovered the correct endpoint, https://docs.google.com/forms/d/e/<formID>/formResponse
. Simple enough. Now, we just need to adjust our HTML input names to reflect the correct Form Data fields. To do this, simply add a name=<ID>
into your code. An example is below.
Boom! You now have a fully working form that submits directly to Google Forms.
And again. The way this is setup has minimal security and spam protection, but it has about the same as a normal form due to the rate limiting and smartness of Google. If you would like to add a bit more security, you can enable "Collect email addresses" and/or "Limit to 1 response" however it will require the user to submit the form on Google Forms after they submit on your site.
As an example, I setup Limit to 1 Response and got this warning once I clicked "Submit" on my locally hosted form:
So, if you don't mind losing a little spam protection to create a basic form for your users, this will work. And, if you do want a little bit more spam protection, you can enable Limit to 1 Response or have it collect email addresses automatically (though an "email" input will not auto fill a required email field, just fyi). For my needs, a non-limited and non-capturing form was plenty, and if I notice spam starts to happen I can seamlessly turn on single submissions.
Soon, PRAUXY.app will include a Secure Google Forms middleman that will allow you to limit to one response without a secondary submission, but for now, that does not exist :)
Let me know if you use this and I'd love to hear feedback if you have any!