A Step-by-Step Example of using an HTML Form to send a "Contact Us" Message via Email without a Backend Server using a Google Script - No PHP, Python, Ruby, Java, Node.js etc.
We needed a way of sending an email from a "static" HTML page when you don't (want to) have a server.
- No "Backend" to Deploy/Maintain/Pay for
- Fully Customisabe - every aspect is customisable!
- Email sent via Google Mail which is Whitelisted Everywhere (high deliverability success)
- Collect/Store any form data in a Spreadsheet for easy viewing
(perfect if you need to share it with non-technical people)
Instead of using a server to send your email,
which is easy but requires maintenance,
use Google to send mail on your behalf
and use Google Spreadsheets to keep track of the data!
You could use a "free" service like http://formspree.io/ to process your form submissions if you don't care where you are sending your data and want to manage the data submitted
in your email inbox (messy ... yuck!)
Or... you can invest a few minutes and keep data private/manageable. Take your pick.
Sample: https://docs.google.com/spreadsheets/d/1Bn4m6iA_Xch1zzhNvo_6CoQWqOAgwwkOWJKC-phHx2Q/
In Google Sheets, Click "File" > "Make a copy..."
This should give you something like this:
Note: Feel free to change the name of the Copy to anything you want, it will not affect the outcome.
Open the Script editor... by clicking "Tools" > "Script editor..."
Here's a snapshot of the script you need (at this point in the exercise): google-script-just-email.js
In the editor window you should expect to see:
Change the value of the TO_ADDRESS
to which ever email you want to receive
the contact form message.
It's not immediately obvious but you have to click on "Manage Versions..."
Then create your new version:
Select the latest project version to deploy.
Anyone, even anonymous
option for the 'Who has access to the app' dropdown or form responses will not be added to the spreadsheet!
Copy the web app URL to your clip board / note pad. Then Click "OK".
Using the template in index.html
in this repo,
create your own html file with the basic form. (save the file)
- Each of your form elements must have a
name
attribute equal to that of your column name in the Google sheet - The form
id
must begform
, i.e.<form id = "gform">
- If you want to alter this later, you will need to create your
own version of
form-submission-handler.js
and amend the expectedid
- If you want to alter this later, you will need to create your
own version of
Remember to change the Form
action
URL to the one you copied in the previous step:
Fill in some sample data in the HTML Form:
Submit the form. You should see a confirmation that it was sent:
Open the inbox for the email address you set in Step 3 (above)
Done. That's it. You just created an HTML form that sends email!
We are going to keep this Super Lean by using PURE CSS
for our Style (fix the "ugly" HTML Form in step 8).
And submit
the form using JQuery "AJAX" to keep the person
on your page/site (avoid "ugly" response page)
To prevent the page from changing to the JSON
response/result
we need to submit the form using AJAX.
Update your index.html
to include the following JavaScript file at the end of your file
(*before the closing </body>
tag)
<script data-cfasync="false" type="text/javascript"
src="https://cdn.rawgit.com/dwyl/html-form-send-email-via-google-script-without-server/master/form-submission-handler.js"></script>
This will now display a "Thank You" message when the form is submitted:
Keeps the person on the same page. No refresh.
Taylor your message by editing the thankyou_message
div:
For this
example we are using Pure CSS: http://purecss.io/start/
because its light weight (4.0KB minified and gzipped)
and solves our current "problem": Making it Look Good.
Without spending too much time on this, we can make the form look a lot nicer:
By default, the sent email's body contains the key-value pairs from the form, with the key as an <h4>
and the value as a <div>
. This is a fairly basic, and foolproof view for the data.
You should get something that looks roughly like:
Bear in mind that this is a work in progress and does potentially open you up to getting more than you bargained for in the email. Because the email content is now looping over all the data sent in the form, if a robot or malicious user decides to
POST
more than you've asked for, you'll likely get it in your inbox. Use with caution for now. We're investigating improvements.
You can modify this though, via the script editor. The line:
result += "<h4 style='text-transform: capitalize; margin-bottom: 0'>" + key + "</h4><div>" + obj[key] + "</div>";
has all you need. You can adjust the markup to suit you. We chose an <h4>
because it was the best size for the email, and added the small amount of CSS to it to fix the capitalisation (the keys are all lower case in the JS object) and a bit of default spacing. While inline styles like this are generally bad practice on normal web pages, for email HTML they're about the only reliable way to do CSS!
We went with a <div>
for the value part, because it could be anything - single-line, multiline (a <p>
for example wouldn't cut it).
While we're here, there's also a replyTo
option for the sendEmail()
method which is commented out by default:
MailApp.sendEmail({
to: TO_ADDRESS,
subject: "Contact form submitted",
// replyTo: String(mailData.email), // This is optional and reliant on your form actually collecting a field named `email`
htmlBody: formatMailBody(mailData)
});
You can uncomment that if you want to add a reply-to field to your email. The example in the script will set the reply-to as the email submitted in the form.
Google's documentation provides more information about MailApp.sendEmail (for example cc
/bcc
etc.) if you're interested:
https://developers.google.com/apps-script/reference/mail/mail-app
Sending the form data directly to your email inbox is a good first step, but we can do better.
This will record the data received from the POST
as a row in the spreadsheet.
See: google-apps-script.js for the full code you can copy-paste.
Follow Steps 4, 5 & 6 to save a new version and re-publish the script.
Because we are loading external .js files, our web browser will not allow us to simply open the index.html from a local directory for testing out the form.
Open your terminal and run this command to install the node modules and start the live server:
npm install live-server --save-dev && node_modules/.bin/live-server --port=8000
It will take a minute to install,
but once that's done your live-server
will start up.
That starts a node.js HTTP server on port 8000 and opens the form you just created in your default browser. If you wish to update the form styles in style.css or the client-side Javascript in form-submission-handler.js, please be sure to edit index.html to load those resources locally rather than via GitHub.
Note: This is a light taste of Node.js for absolute beginners. You do not need node.js to "deploy" this form, you can run it on an any web server that serves HTML/CSS/JavaScript. If you have never used Node.js before, see: http://nodeguide.com/beginner.html but for the purposes of this exercise (submitting a form without a server) you don't need node.js or
live-server
it's just a nice thing to have when you are creating your form because it automatically re-loads the page when you make changes in your text editor!
If you want us to take this tutorial further, please let us know!
In response to Henry Beary's request we made the form handler generic which means you can now add any fields you want to the form.
remember to include the fields inside the form that has the id gform
and ensure that the name
of the form element matches the new column heading in your spreadsheet.
e.g:
<fieldset class="pure-group">
<label for="color">Favourite Color: </label>
<input id="color" name="color" placeholder="green" />
</fieldset>
This will allow you to capture the person's favourite color: e.g:
Let us know if you have any questions!
In order to avoid getting spammed and fill up google apps usage quota, we will be implementing a simple SPAM prevention technique that's known as Honeypot where it essentially creates a hidden text field that if filled up is assumed as a spam bot and prevents the form from submit.
<form action="https://script.google.com/macros/s/..." method="post">
<!--input id must be honeypot or else it wont work-->
<label class="sr-only">Keep this field blank</label>
<input id="honeypot" type="text" name="honeypot" value="" />
<!--the rest of your form-->
</form>
#honeypot {
display: none; /*makes the field not visible to humans*/
}
/* form-submission-handler.js */
/* remove the comment from this if statement */
if (validateHuman(data.honeypot)) { //if form is filled, form will not be submitted
return false;
}
- Google Apps Scripts Basics: https://developers.google.com/apps-script/articles
- Logger (like console.log): https://developers.google.com/apps-script/reference/base/logger
- Simple Mail Merge using Google Spreadsheets: https://developers.google.com/apps-script/articles/mail_merge
- Original Tutorial: AJAX post to google spreadsheet: http://stackoverflow.com/questions/10000020/ajax-post-to-google-spreadsheet which points to: