From 31f8c7e5483a7f7f770f170845b6bca93eb5922c Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 16 May 2024 15:38:09 -0500 Subject: [PATCH] Website: Create new Salesforce helper, update contact form actions and signup action. (#19082) Changes: - Added a new helper: `salesforce/update-or-create-contact-and-account-and-create-lead`, a wrapper for the `update-or-create-contact-and-account` and `create-lead` helpers that is intended to be run in the background. - Updated the `signup`, `deliver-contact-form-message`, and `deliver-talk-to-us-form-submission` actions to use the new helper --- .../deliver-contact-form-message.js | 37 +++----- .../deliver-talk-to-us-form-submission.js | 44 ++++----- website/api/controllers/entrance/signup.js | 18 ++-- ...ate-contact-and-account-and-create-lead.js | 90 +++++++++++++++++++ 4 files changed, 123 insertions(+), 66 deletions(-) create mode 100644 website/api/helpers/salesforce/update-or-create-contact-and-account-and-create-lead.js diff --git a/website/api/controllers/deliver-contact-form-message.js b/website/api/controllers/deliver-contact-form-message.js index 532308baf2..03696e07b2 100644 --- a/website/api/controllers/deliver-contact-form-message.js +++ b/website/api/controllers/deliver-contact-form-message.js @@ -71,31 +71,18 @@ module.exports = { `Name: ${firstName + ' ' + lastName}, Email: ${emailAddress}, Message: ${message ? message : 'No message.'}` }); - await sails.helpers.salesforce.updateOrCreateContactAndAccount.with({ - emailAddress: emailAddress, - firstName: firstName, - lastName: lastName, - }); - - - // Send a POST request to Zapier - await sails.helpers.http.post( - 'https://hooks.zapier.com/hooks/catch/3627242/3cxcriz/', - { - 'emailAddress': emailAddress, - 'firstName': firstName, - 'lastName': lastName, - 'message': message, - 'webhookSecret': sails.config.custom.zapierSandboxWebhookSecret - } - ) - .timeout(5000) - .tolerate(['non200Response', 'requestFailed'], (err)=>{ - // Note that Zapier responds with a 2xx status code even if something goes wrong, so just because this message is not logged doesn't mean everything is hunky dory. More info: https://github.com/fleetdm/fleet/pull/6380#issuecomment-1204395762 - sails.log.warn(`When a user submitted a contact form message, a lead/contact could not be updated in the CRM for this email address: ${emailAddress}. Raw error: ${err}`); - return; - }); - + // Use timers.setImmediate() to update/create CRM records in the background. + require('timers').setImmediate(async ()=>{ + await sails.helpers.salesforce.updateOrCreateContactAndAccountAndCreateLead.with({ + emailAddress: emailAddress, + firstName: firstName, + lastName: lastName, + leadSource: 'Website - Contact forms', + leadDescription: `Sent a contact form message: ${message}`, + }).tolerate((err)=>{ + sails.log.warn(`Background task failed: When a user submitted a contact form message, a lead/contact could not be updated in the CRM for this email address: ${emailAddress}. Error:`, err.raw); + }); + });//_∏_ (Meanwhile...) } diff --git a/website/api/controllers/deliver-talk-to-us-form-submission.js b/website/api/controllers/deliver-talk-to-us-form-submission.js index d07f2474b4..9978b856f5 100644 --- a/website/api/controllers/deliver-talk-to-us-form-submission.js +++ b/website/api/controllers/deliver-talk-to-us-form-submission.js @@ -74,37 +74,23 @@ module.exports = { throw 'invalidEmailDomain'; } - await sails.helpers.salesforce.updateOrCreateContactAndAccount.with({ - emailAddress, - firstName, - lastName, - organization: organization, - primaryBuyingSituation: primaryBuyingSituation === 'eo-security' ? 'Endpoint operations - Security' : primaryBuyingSituation === 'eo-it' ? 'Endpoint operations - IT' : primaryBuyingSituation === 'mdm' ? 'Device management (MDM)' : 'Vulnerability management', - }); - - await sails.helpers.http.post.with({ - url: 'https://hooks.zapier.com/hooks/catch/3627242/3cxwxdo/', - data: { - emailAddress, - firstName, - lastName, - organization, - numberOfHosts, - primaryBuyingSituation, - webhookSecret: sails.config.custom.zapierSandboxWebhookSecret, - } - }) - .timeout(5000) - .tolerate(['non200Response', 'requestFailed'], (err)=>{ - // Note that Zapier responds with a 2xx status code even if something goes wrong, so just because this message is not logged doesn't mean everything is hunky dory. More info: https://github.com/fleetdm/fleet/pull/6380#issuecomment-1204395762 - sails.log.warn(`When a user submitted a contact form message, a lead/contact could not be updated in the CRM for this email address: ${emailAddress}. Raw error: ${err}`); - return; - }); - - + // Use timers.setImmediate() to update/create CRM records in the background. + require('timers').setImmediate(async ()=>{ + await sails.helpers.salesforce.updateOrCreateContactAndAccountAndCreateLead.with({ + emailAddress: emailAddress, + firstName: firstName, + lastName: lastName, + organization: organization, + numberOfHosts: numberOfHosts, + primaryBuyingSituation: primaryBuyingSituation === 'eo-security' ? 'Endpoint operations - Security' : primaryBuyingSituation === 'eo-it' ? 'Endpoint operations - IT' : primaryBuyingSituation === 'mdm' ? 'Device management (MDM)' : primaryBuyingSituation === 'vm' ? 'Vulnerability management' : undefined, + leadSource: 'Website - Contact forms', + leadDescription: `Submitted the "Talk to us" form.`, + }).tolerate((err)=>{ + sails.log.warn(`Background task failed: When a user submitted the "Talk to us" form, a lead/contact could not be updated in the CRM for this email address: ${emailAddress}. Error:`, err.raw); + }); + });//_∏_ (Meanwhile...) return; - } diff --git a/website/api/controllers/entrance/signup.js b/website/api/controllers/entrance/signup.js index 387cd8f8ae..2aecd88055 100644 --- a/website/api/controllers/entrance/signup.js +++ b/website/api/controllers/entrance/signup.js @@ -138,24 +138,18 @@ the account verification message.)`, .intercept({name: 'UsageError'}, 'invalid') .fetch(); - if(sails.config.environment === 'production') { - let recordIds = await sails.helpers.salesforce.updateOrCreateContactAndAccount.with({ + // Use timers.setImmediate() to update/create CRM records in the background. + require('timers').setImmediate(async ()=>{ + await sails.helpers.salesforce.updateOrCreateContactAndAccountAndCreateLead.with({ emailAddress: newEmailAddress, firstName: firstName, lastName: lastName, organization: organization, - }); - - await sails.helpers.salesforce.createLead.with({ - salesforceContactId: recordIds.salesforceContactId, - salesforceAccountId: recordIds.salesforceAccountId, leadSource: 'Website - Sign up', - }) - .tolerate((err)=>{ - sails.log.warn(`When a user signed up, a lead could not be created in the CRM for this email address: ${newEmailAddress}. Error from create-lead helper: ${err}`); - return; + }).tolerate((err)=>{ + sails.log.warn(`Background task failed: When a user (email: ${newEmailAddress} sign up for a fleetdm.com account, a Contact, Account, and Lead record could not be created/updated in the CRM. Error:`, err.raw); }); - } + });//_∏_ (Meanwhile...) // Store the user's new id in their session. this.req.session.userId = newUserRecord.id; diff --git a/website/api/helpers/salesforce/update-or-create-contact-and-account-and-create-lead.js b/website/api/helpers/salesforce/update-or-create-contact-and-account-and-create-lead.js new file mode 100644 index 0000000000..0b5e8f2023 --- /dev/null +++ b/website/api/helpers/salesforce/update-or-create-contact-and-account-and-create-lead.js @@ -0,0 +1,90 @@ +module.exports = { + + + friendlyName: 'Update or create contact and account and create lead', + + + description: 'Updates or creates a contact and account in Salesforce, then uses the IDs of the created records to create a Lead record.', + + extendedDescription: 'This is a wrapper for the update-or-create-contact-and-account and create-lead helpers used to run both of them in the background with timers.setImmediate().', + + inputs: { + + // Find by… + emailAddress: { type: 'string' }, + linkedinUrl: { type: 'string' }, + + // Set… + firstName: { type: 'string', required: true }, + lastName: { type: 'string', required: true }, + organization: { type: 'string' }, + primaryBuyingSituation: { type: 'string' }, + psychologicalStage: { + type: 'string', + isIn: [ + '1 - Unaware', + '2 - Aware', + '3 - Intrigued', + '4 - Has use case', + '5 - Personally confident', + '6 - Has team buy-in' + ] + }, + // For new leads. + leadDescription: { + type: 'string', + description: 'A description of what this lead is about; e.g. a contact form message, or the size of t-shirt being requested.' + }, + leadSource: { + type: 'string', + required: true, + isIn: [ + 'Website - Contact forms', + 'Website - Sign up', + 'Website - Waitlist', + 'Website - swag request', + ], + }, + numberOfHosts: { type: 'number' }, + }, + + exits: { + + success: { + extendedDescription: 'Note that this deliberately has no return value.', + }, + + }, + + + + fn: async function ({emailAddress, linkedinUrl, firstName, lastName, organization, primaryBuyingSituation, psychologicalStage, leadSource, leadDescription, numberOfHosts}) { + if(sails.config.environment !== 'production') { + sails.log('Skipping Salesforce integration...'); + return; + } + + let recordIds = await sails.helpers.salesforce.updateOrCreateContactAndAccount.with({ + emailAddress, + firstName, + lastName, + organization, + linkedinUrl, + primaryBuyingSituation, + psychologicalStage, + }); + + await sails.helpers.salesforce.createLead.with({ + salesforceContactId: recordIds.salesforceContactId, + salesforceAccountId: recordIds.salesforceAccountId, + leadDescription, + leadSource, + numberOfHosts, + }); + + return; + } + + +}; +