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

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