Overview
A few months back I remember seeing Dr. Nic's Custom Google Forms Post (and source) and thinking that was genius. The takeaway:
If a service doesn't give you the programmer enough control over their content, write a web scraper and build an API from the raw html.
All services should make it top priority to give developers complete control over the system right away. I don't mean "make it so we can do a million things", rather, make it so we can easily access the core data in a scalable fashion. If you do that for us, we'll make you big. Google doesn't care about that though, they're already big :).
Anyway, check out the google form (before) and the styled one using the api (after):
Online Form Services
There are quite a few web form services out there that I've tried:
-
Google Forms (live examples)
- 100% Free
- Minimal feature set (6 form field types only)
- Easy to use
- Lots of (ugly) templates
- Can only view form responses by going to the Google Spreadsheet. You can tell Google Docs to send you an email whenever someone fills out a form, but you have to go to the actual spreadsheet to view the responses (waste of time).
-
Wufoo (live examples)
- 3 forms free (100 entries per month, which is nothing).
- Pretty expensive otherwise
- Tons of form field types
- Very nice interface, very easy to use.
- Form API
-
PandaForm
- 100% free
- Almost the same feature set as Wufoo, but it's FREE.
- No limit
- No API
All of them are great if you just need to get up a form to collect information and the user experience doesn't really matter.
But once user experience matters, good luck. Wufoo and Google both allow you to style the forms with CSS, but unless you're a ninja, you can't remove the copyright info and "powered by X" stuff that they all come with. To top that off, you only have 2 options for viewing the form:
- On their website (definitely not an option if you want a seamless UX).
- In an iframe. Needless to say, iframes are inherently limited. Good luck applying cascading styles to your form and using javascript to enhance the experience (or for client side validations!). You're stuck with the defaults...
I'd go with Google Forms if you want just a basic setup. It's free, and you don't have to worry about being charged. And while PandaForm looks very cool, we know Google Forms will be around for a while.
Build an API around Google Forms
I spent a late night once a while back seeing how Google Forms were structured. After spending a few weeks with the Surveyor Ruby Gem and seeing how they built forms with haml, I decided you could probably do that with Google Forms. Combine that with Dr. Nic's idea, and you've got a very customizable web form setup.
1. Install Googletastic
One of my clients wanted a completely custom interface to Google Apps to manage all of their documents/manuals/brochures, forms, assets, communication, etc. So I built Googletastic. Here's a Sinatra/Googletastic demo I setup randomly to show of it's features. Doesn't do much justice, but you can fork the source anyway.
Googletastic uses Nokogiri to parse XML from the Google Data API. After spending hours on this, I discovered HTTParty. Would've made my life easier, could've used JSON :). But it's done, and it works.
Install the gem:
2. Create a Google Form
Create a simple Google Form, you can copy one of these templates.
3. Convert the Google Form to JSON!
# setup credentials |
Here's how that works:
- Grab the list of spreadsheets from your Google Spreadsheets.
- Login to your Google Apps account using Mechanize.
- For each spreadsheet, find the
formkeyby parsing random html and javascript after a few redirects (since there's no way to get a formkey from Google other than by manually going to the url or doing this). - Download the form at the url
http://spreadsheets.google.com/viewform?hl=en&formkey=#{form_key}#gid=0 - Parse the html into the data structure used to build the form.
An paragraph text node from a google form looks like this:
So googletastic's just saying, for each <div class='ss-item'>, find the title, help text, description, default values, whether or not it's required, and the id of the entry. We know that id's look like entry_(\d+) and form field names, which are passed as params, look like entry.(\d+).(single|group). From that information, we have the entire form structure.
You could do the same thing to wufoo and pandaform no problem.
4. Build a HAML template around the Google Form API
Here's the first template I made using this new-found api:
That looks crazy but it's actually really simple: for each form field, build a renderer depending on the field type.
Then you just style the elements and you're golden.
5. Add Validations (and other Javascript)
Now that you have the form and can render it independently of Google, you are free to set up custom validations.
In jQuery, using the jQuery Validate Plugin, you can do something like this:
Some notes:
- If you're using these forms on a completely static site and don't have server-side access (Github Pages for example), then you can't do server-side validations obviously. This means that if users don't have javascript enabled (which is a tiny fraction nowadays), they could fill out forms incorrectly because they'd bypass javascript validations.
- So, I recommend validating all required fields in jQuery. Otherwise, if they submit the form and something's wrong, Google will redirect them to the ugly Google Form page for them to correct invalid fields. Let's avoid that :). However, if you have server-side access, you could capture the response, extract the json, and render that using your HAML template. I'm doing that on a site now.
6. Use Google Forms in Your App
To sum up, here's all you need to use Google Forms in this completely custom way:
require 'rubygems' |
Then just build an ERB/HAML view of it, add some validations, style it, and it looks like you've built a survey system from scratch.
Here's what the final result looks like. And this is the original form.