Last active
October 10, 2020 18:27
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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 | |
` | |
}) | |
} |
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
Usage:
(the script assumes keys "Email address" and "Name" exist in the submitted object atm)
Tools
->Script editor
CONTACT_LABEL
to whatever label you want to store your contacts underForm2Contact
toolbar that appears next toHelp
after a short timeAdd 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 warningformSubmissionListener
will be run. Executions can be monitored from the script editor by going toview
->executions
or by navigating directly toscript.google.com