Skip to content

Instantly share code, notes, and snippets.

@mackncheesiest
Last active October 10, 2020 18:27
Show Gist options
  • Save mackncheesiest/e305b33145bcb88f0f90008b108eb1c4 to your computer and use it in GitHub Desktop.
Save mackncheesiest/e305b33145bcb88f0f90008b108eb1c4 to your computer and use it in GitHub Desktop.
Google Apps Script for listening for form submissions and turning those into contacts with a particular label
/* Set this label to match whatever label you want the contacts to be grouped under */
const CONTACT_LABEL = "CONTACT LABEL";
const TRIGGER_PROP = "TRIGGER_ID";
const NONAME_PROP = "NO_NAME_GIVEN";
const MENU_LABEL = "Form2Contact";
/*
* Clears the TRIGGER_PROP property so that the registration menu pops up again (in case i.e. permissions change and we need to re-register the script)
*/
function clearTrigger() {
const trigger_uuid = PropertiesService.getScriptProperties().getProperty(TRIGGER_PROP)
// If we have a registered trigger ID, delete the property and disable the trigger
if (trigger_uuid) {
PropertiesService.getScriptProperties().deleteProperty(TRIGGER_PROP);
const triggers = ScriptApp.getProjectTriggers()
for (let i = 0; i < triggers.length; i++) {
const trigger = triggers[i];
if (trigger.getUniqueId() === trigger_uuid) {
Logger.log(`Removing trigger with UUID ${trigger_uuid}`);
ScriptApp.deleteTrigger(triggers);
break;
}
}
}
// If the script property isn't set, we don't need to do anything
return;
}
/*
* Adds a small menu that can be used to initialize the trigger for listening to form submission events
*/
function onOpen() {
if (PropertiesService.getScriptProperties().getProperty(TRIGGER_PROP)) {
/* Trigger has already been registered, exit */
return;
}
let menu = [{ name: 'Add trigger to create mailing list contacts based on form submissions', functionName: 'registerFormTrigger_' }];
SpreadsheetApp.getActiveSpreadsheet().addMenu(MENU_LABEL, menu);
}
function registerFormTrigger_() {
let ss = SpreadsheetApp.getActiveSpreadsheet();
let newTrigger = ScriptApp.newTrigger("formSubmissionListener").forSpreadsheet(ss).onFormSubmit().create();
PropertiesService.getScriptProperties().setProperty(TRIGGER_PROP, newTrigger.getUniqueId());
Browser.msgBox("Form trigger registered! When forms are submitted to this spreadsheet, the name and email of the associated submission will be added to your Gmail contacts under the \"" + CONTACT_LABEL + "\" label");
ss.removeMenu(MENU_LABEL);
}
/*
* Assuming this is associated with a form spreadsheet, this trigger should be set to run whenever a form submission is made
*/
function formSubmissionListener(e) {
if (typeof e === "undefined") {
Logger.log("Tried to run without event object. Exiting...");
return;
}
let contactGroup = ContactsApp.getContactGroup(CONTACT_LABEL)
if (contactGroup === null) {
Logger.log("Contact label " + CONTACT_LABEL + " does not exist! Creating!");
contactGroup = ContactsApp.createContactGroup(CONTACT_LABEL);
}
const namedValues = e.namedValues;
Logger.log("For debugging, the named values I received were " + JSON.stringify(namedValues));
const emailAddress = namedValues["Email address"][0].trim();
let name = namedValues["Name"][0].trim();
if (name === "") {
let idx = 1;
if (PropertiesService.getScriptProperties().getProperty(NONAME_PROP)) {
idx = Math.round(PropertiesService.getScriptProperties().getProperty(NONAME_PROP)) + 1;
PropertiesService.getScriptProperties().setProperty(NONAME_PROP, idx);
} else {
PropertiesService.getScriptProperties().setProperty(NONAME_PROP, idx);
}
name = `NONAME NUM_${idx}`;
Logger.log("The name was empty! Setting name to be " + name);
}
let existingContact = checkForContact_(contactGroup, name);
if (existingContact !== null) {
updateExistingContact_(existingContact, name, emailAddress);
} else {
addNewContact_(contactGroup, name, emailAddress);
}
sendConfirmationEmail_(emailAddress)
}
/*
* Utility functions
*/
function checkForContact_(contactGroup, name) {
let existingContact = null;
const contacts = contactGroup.getContacts()
for (let i in contacts) {
const contact = contacts[i];
if (contact.getFullName() === name) {
Logger.log("Contact already exists for " + name);
existingContact = contact;
break;
}
}
return existingContact;
}
function updateExistingContact_(existingContact, name, emailAddress) {
Logger.log("Because a contact already exists for " + name + ", I'm just going to update their primary email address to the newly submitted one.");
let emailList = existingContact.getEmails(ContactsApp.Field.HOME_EMAIL);
let primaryEmail = null;
for (var i in emailList) {
if (emailList[i].isPrimary()) {
primaryEmail = emailList[i];
break;
}
}
if (primaryEmail !== null) {
Logger.log("Found existing primary email. Updating from " + primaryEmail.getAddress() + " to " + emailAddress);
primaryEmail.setAddress(emailAddress);
} else {
Logger.log("Didn't find an existing primary email. Adding a new email and setting it as primary");
let newEmail = existingContact.addEmail(ContactsApp.Field.HOME_EMAIL, emailAddress);
newEmail.setAsPrimary();
}
}
function addNewContact_(contactGroup, name, emailAddress) {
Logger.log("I couldn't find an existing contact for " + name + ", so I'm adding a new contact");
let splitName = name.split(" ");
let givenName = splitName[0];
let familyName = "";
if (splitName.length > 1) {
familyName = splitName.slice(1).join(" ");
}
let contact = ContactsApp.createContact(givenName, familyName, emailAddress);
let contactEmails = contact.getEmails();
contactEmails[0].setLabel(ContactsApp.Field.HOME_EMAIL);
contactEmails[0].setAsPrimary();
contact.addToGroup(contactGroup);
}
function sendConfirmationEmail_(emailAddress) {
linkStr = "https://www.google.com"
MailApp.sendEmail({
to: emailAddress,
subject: "Confirmation Email!",
body:
`This is a template email body
It consists of multiple lines of content
You can interpolate values into the body like this link: ${linkStr}
<3,
J
`
})
}
@mackncheesiest
Copy link
Author

Usage:

  • Create a google form
  • Set it to require email address
  • Add a (potentially optional) short answer field for "Name"
    (the script assumes keys "Email address" and "Name" exist in the submitted object atm)
  • Open your form results spreadsheet
  • In the form results spreadsheet, go to Tools -> Script editor
  • Paste these functions into the script editor window
  • Change the CONTACT_LABEL to whatever label you want to store your contacts under
  • Reload the spreadsheet page, and there should be a Form2Contact toolbar that appears next to Help after a short time
  • Click that -> click Add trigger to create mailing list contacts based on form submissions, and it should prompt you to accept the permissions this script requires (creating contacts and accessing spreadsheet info). Since this is not an officially-registered app, it will probably present a scary security warning
  • Accepting permissions, though, should give a popup notifying the successful registration of the submission listener.
  • Whenever a form is submitted, the function formSubmissionListener will be run. Executions can be monitored from the script editor by going to view -> executions or by navigating directly to script.google.com

@mackncheesiest
Copy link
Author

Update: you can also set a confirmation email to be sent through the sendConfirmationEmail_ function by adjusting the email body to include any content you would like at the bottom of the file.

Additionally, if new functionality is added such that script permissions change, the script can be un-registered so that the registration menu shows up in Google Spreadsheets for re-registration by running the clearTrigger function as a standalone function in the script editor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment