Saturday, July 30, 2011

Google Docs Forms: Automatic Email Notifications

Forms with Google Docs

In June I wrote a tutorial detailing how I use Google Docs for my own Contact Me form. The form allows readers to submit questions to which I may reply privately in my own time. I think this adds to reader experience and I've answered several submitted questions already. I've even made posts as a result of one or two. The mentioned tutorial showed you how to be notified of a form submission by email, but this was just very basic stuff. I've since come up with a much better way that I'm ready to share.

Detailed Email Notifications 

Google Docs automatic notifications only include a very basic level of information simply telling you someone has submitted a form. You must then visit the document to see what information was sent and it's stored in a fairly unattractive spreadsheet. Although this works as a bare minimum measure it's hardly an ideal way to interact with readers. I actually had to build responses to include the submitted form manually. I knew there was a better way. So, I took some time to dig through Google Apps Script documentation and built a script to improve the process.

I've created a script which automatically processes form submissions into both text and HTML friendly versions, then sends it off to all Spreadsheet Collaborators email. Each form entry is labeled by column label, then placed on its own line. Everything a reader submits I automatically receive in a pleasingly formatted email on my Google account. This saves a great deal of time and makes writing a response much easier. Note: The following tutorial assumes you've already created a Form using Google Docs. If you have not please review the previous tutorial.


Adding the Script to your Form

 Begin by logging into your Google Docs account, then click on the Form you'd like to receive automatic updates for. Next choose the Tools->Script Editor option then click on Create a new project. You'll now have an empty script project with a function named myFunction. You should change myFunction to something meaningful, for example sendEmail. Now, copy and paste the code provided below into the function placing it between the { and } characters.
var formSheet = SpreadsheetApp.getActiveSheet();
var firstRow = 2; //Skip a row for column labels
var lastForm = formSheet.getLastRow();
var lastCol = formSheet.getLastColumn();
var flagCol = null;
var subject = formSheet.getName() + " Form";
var mailTo = "";
var collaborators = SpreadsheetApp.getActiveSpreadsheet().getCollaborators();
for(var i=0; i < collaborators.length; i++){
    mailTo += collaborators + ",";
  }
  var labels = formSheet.getRange(1, 1, 1, lastCol).getValues()[0]; //get column Labels

  for(var i=0; i < labels.length; i++){ //Find which column contains the Sent Flag
    if(labels[i] == "Email Notice Sent"){
      flagCol = i;
      break;
    }
  }  
  if(flagCol === null){//Sent Flag Col not found, create it
    formSheet.insertColumnsAfter(lastCol++, 1);
    formSheet.getRange(1, 1, 1, lastCol).getCell(1, lastCol).setValue("Email Notice Sent");
    SpreadsheetApp.flush();
    flagCol = lastCol;
  }

  for(var i = lastForm; i >= firstRow; i--) { //Loop through forms, last first
    var form = formSheet.getRange(i, 1, 1, lastCol);
    var formVals = form.getValues()[0];  
 
    var message = "";
    var html = "";
 
    if(formVals[0] != "" && formVals[flagCol] != true){ //Skip empty and email sent rows
      for(var col=0; col < lastCol; col++) { //Build the message
        if(col != flagCol){
          message += labels[col] + ": " + formVals[col] + "\n\n";
          html += "<div style='margin-bottom: 10px;'>" + labels[col] + ": ";
     
          htmlVal = formVals[col].toString().replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/[\r\n]/g, "<br>");
          if(typeof(formVals[col]) == "string" && formVals[col].length > 100){
            html += "<p>" + htmlVal + "</p></div>";
          }
          else {
            html += htmlVal + "</div>";
          }
        }
      }
 
      GmailApp.sendEmail(mailTo, subject + ": " + formVals[1], message, {"htmlBody": html});  
      form.getCell(1, flagCol+1).setValue(true);    
      SpreadsheetApp.flush();  // Make sure the cell is updated right away in case the script is interrupted    
    }
  }

Triggering the Script and Finishing up

Finally, choose the menu option Triggers->Current Project's Triggers then click on Add a new trigger. Choose the name of your function(sendEmail for example) in the first box, from spreadsheet in the second and finally On Form Submit in the third. Save your changes, then save your script and it's done. From now on each time a reader submits that form, the spreadsheet collaborators are automatically notified by email with a detailed copy of the submitted form.

Conclusion

Email form notifications are a wonderful tool to improve correspondence with interested visitors. It saves a great deal of time and effort, while structuring the forms in a meaningful useful format. You even gain redundant copies of each message sent this way. Once setup you'll quickly and comfortably interact with forms through your Gmail account all for free. No need for 3rd party form accounts, just use Google with Apps Script. Give it a try and let me know how it works for you. I'm very happy with my own results thus far.
17 Comments
Comments

17 comments :

vinhdizzo said...

Hi,

Thanks for this! I've been looking for something like this for the past two days and finally found it here. Some questions:

- the sender of the notification is the email account of the owner of the form, correct?
- Suppose I have a field named "Email Address" on the form. Is it possible to add this to the recipient list?
- Is it possible to make a conditional statement on who to send to depending on the results of a particular field?

Thanks!

Unknown said...

Thanks for the questions.

1) Yes, the form owner is the sender.
2) Possible, but would require a customization.
3) Also possible with a customization.

vinhdizzo said...

Thanks again for this. I was able to accomplish what I wanted.

I do however, would like to note a bug. When the first person submits a form (row 2 of the spreadsheet), the script never marks "TRUE" under "Email Notice Sent". When the second person submits, two emails are sent out (for rows 2 and 3). Everything then works properly after that.

Unknown said...

You are correct, I never noticed that. It's related to the creation of the flag column on the first execution. I confirmed the issue while reusing this script for a new form for another site I'm working on. Thanks for the heads up.

James

GNB Bank said...

Thank you so much! This is absolutely great. It's just what I've been missing so long at Google Docs.

Just one little thing:

In my case, I have a form with an input for "Email". The problem is, when I recieve the mail notification, the title of the input is just toguether with the email, for example:

"Mail:ooooo@gmail.com"

So the mail reader interprets the email as "mail:ooooo@gmail.com" and gives me the link to that one. Could it be possible to place an space between the input title and the text???

That would be just awesome....

Anyway, thank you

Unknown said...

This line seems to be the culprit for html messages

html += "<div style='margin-bottom: 10px;'>" + labels[col] + ":"

Just add a space after the colon.

Eddie said...

Hi James,
I just wanted to say thank you for this script.
I was looking to replace a club membership form which had been written on Jot Forms and we were paying $10 per month to have 100+ submissions.
The main selling point of Jot Forms was the delivery of an email summary - from which our database admin could cut & paste replies.
Now we can do it with Google Forms then our problems are solved!
Thanks again.
Eddie

mrme said...

I am looking for a way to have users directed to a url upon clicking submit. Can you help?

Unknown said...

@John, I don't think Google Docs forms allow that, but it may be possible with some custom javascript that monitors the iFrame in which the form embeds itself for changes in the url. I've not had need for that sort of application though and would have to research the limitations of cross domain iframe communication to see exactly what can be seen on the host domain. Typically, I've worked with domains I controlled both ends of for that sort of cross talk.

James

WonderingWeb said...

This is great! Thank you. Is there a way to add another email address to receive this email notification once the form is submitted?

WonderingWeb said...

...or is there a way to edit the "mailto" address to another (non-gmail) email address?

sam said...

Hi,
how can I tell it if cell B18 is changed or greater than 20 then send email
Thanks

Bunnyslippers said...

James, is it possible to have the email notification sent only to me (the spreadsheet owner) and possibly to the form submitter, but not to other collaborators?

Bunnyslippers said...

James, what do you think of this other solution? It seems simpler. http://www.labnol.org/internet/google-docs-email-form/20884/

Unknown said...

Hi James,

Great advice. I have many google doc forms using this script. Everything works great. However, when I click reply to on the form submissions I receive in my email, the reply to always defaults to my gmail account email. Is there a way to make the script show the reply to section as the email provided by the individual(s) submitting the form?

Script used is below:
function sendEmail() {
var formSheet = SpreadsheetApp.getActiveSheet();
var firstRow = 2; //Skip a row for column labels
var lastForm = formSheet.getLastRow();
var lastCol = formSheet.getLastColumn();
var flagCol = null;
var subject = formSheet.getName() + " Form";
var mailTo = "";
var collaborators = SpreadsheetApp.getActiveSpreadsheet().getCollaborators();


GmailApp.sendEmail('lwillis@promedeq.com', subject + formVals[1], message, {"htmlBody": html});
form.getCell(1, flagCol+1).setValue(true);
SpreadsheetApp.flush(); // Make sure the cell is updated right away in case the script is interrupted
}
}
}

It would not accept DIV tags, so I had to remove a few things. Your support is greatly appreciated.

Unknown said...

Hi!

If I wanted to add a link or short statement in the email below the message body, what would be the best way to achieve this?

Thank you!

jt said...

I am working on a spreadsheet (300+ columns) that collects all the responses from a form. The spreadsheet currently sends an email using your script. Works great!

However, since now I have two groups filling out the form (part1 & part 2), I would also need another email notification when the 2nd group completes the entry. Group 1 skips to last page to submit the form (this is when your script above sends an email). Then the 2nd group goes back into the form (edit mode) to complete the 2nd half (this is when I need another email notification). One of the columns (column X) contains the value that will determine whether the form is complete.

How do I set this up so that when a cell in column X = NO, no email is sent out (other than the email sent out by your script), but when X = YES, an email notification is sent to all collaborators.

Appreciate your help!

Thank you!

Post a Comment