fleet/website/api/controllers/webhooks/receive-from-clay.js
kilo-code-bot[bot] 05f2daad4b
Add 'Registered for a conference' intent signal (#41919)
## Summary

- Adds `'Registered for a conference'` to the `intentSignal` `isIn`
array in three files:
- `website/api/helpers/salesforce/create-historical-event.js` — between
`'Signed up for Fleet event'` and `'Engaged with Fleetie at event'`
- `website/api/controllers/webhooks/receive-from-clay.js` — between
`'Signed up for Fleet event'` and `'Engaged with Fleetie at event'`
-
`website/api/helpers/salesforce/update-or-create-contact-and-account.js`
— added to the `isIn` array
- This replaces the incorrect approach in PR #41918, which added the
signal to the handbook markdown table instead of the code where intent
signals are validated.

---

Built for [Sam
Pfluger](https://fleetdm.slack.com/archives/D0AF8QFBVHB/p1773789580384389?thread_ts=1773788922.891409&cid=D0AF8QFBVHB)
by [Kilo for Slack](https://kilo.ai/features/slack-integration)

---------

Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
Co-authored-by: Sam Pfluger <[email protected]>
2026-03-18 08:21:50 -05:00

162 lines
5.1 KiB
JavaScript
Vendored

module.exports = {
friendlyName: 'Receive from Clay',
description: 'Receive webhook requests from Clay.',
inputs: {
webhookSecret: {
type: 'string',
required: true,
},
// For finding/creating contacts.
firstName: {
type: 'string',
required: true,
},
lastName: {
type: 'string',
required: true,
},
linkedinUrl: {
type: 'string',
},
emailAddress: {
type: 'string',
},
contactSource: {
type: 'string',
required: true,
isIn: [
'Website - Contact forms',
'Website - Sign up',
'Website - Newsletter',
'Event',
'GitHub - Stared fleetdm/fleet',
'GitHub - Forked fleetdm/fleet',
'GitHub - Contributed to fleetdm/fleet',
'LinkedIn - Comment',
'LinkedIn - Reaction',
'LinkedIn - Share',
'LinkedIn - Liked the LinkedIn company page',
],
},
jobTitle: {
type: 'string',
},
// For creating historical event.
intentSignal: {
type: 'string',
required: true,
isIn: [
'Followed the Fleet LinkedIn company page',
'LinkedIn comment',
'LinkedIn share',
'LinkedIn reaction',
'Fleet channel member in MacAdmins Slack',
'Fleet channel member in osquery Slack',
'Implemented a trial key',
'Signed up for Fleet event',
'Registered for a conference',
'Engaged with Fleetie at event',
'Attended a Fleet happy hour',
'Stared the fleetdm/fleet repo on GitHub',
'Forked the fleetdm/fleet repo on GitHub',
'Contributed to the fleetdm/fleet repo on GitHub',
'Subscribed to the Fleet newsletter',
'Attended a Fleet training course'
]
},
historicalContent: {
type: 'string',
required: true,
},
historicalContentUrl: {
type: 'string',
},
relatedCampaign: {
type: 'string',
}
},
exits: {
success: { description: 'Information about LinkedIn activity has successfully been received.' },
duplicateContactOrAccountFound: {description: 'A contact or account could not be created because a duplicate record exists.', statusCode: 409 },
couldNotCreateContactOrAccount: { description: 'A contact or account could not be created in the CRM using the provided information.' },
couldNotCreateActivity: { description: 'An error occured when trying to create a historical event record in the CRM' },
},
fn: async function ({webhookSecret, firstName, lastName, linkedinUrl, contactSource, jobTitle, intentSignal, historicalContent, historicalContentUrl, relatedCampaign, emailAddress}) {
if (!sails.config.custom.clayWebhookSecret) {
throw new Error('No webhook secret configured! (Please set `sails.config.custom.zapierWebhookSecret`.)');
}
if(webhookSecret !== sails.config.custom.clayWebhookSecret){
throw new Error('Received unexpected webhook request with webhookSecret set to: '+webhookSecret);
}
let recordIds = await sails.helpers.salesforce.updateOrCreateContactAndAccount.with({
firstName,
lastName,
linkedinUrl,
emailAddress,
contactSource,
jobTitle,
})
.intercept((err)=>{
sails.log.warn(`When the receive-from-clay webhook received information about LinkedIn activity, a contact/account could not be created or updated. Full error: ${require('util').inspect(err)}`);
if(typeof err.errorCode !== 'undefined' && err.errorCode === 'DUPLICATES_DETECTED') {
return 'duplicateContactOrAccountFound';
} else {
return 'couldNotCreateContactOrAccount';
}
});
if(!recordIds.salesforceAccountId) {
sails.log.warn(`When the receive-from-clay received information about a user's activity (name: ${firstName} ${lastName}), activity: ${intentSignal}). A contact was successfully updated, but the webhook is unable to continue because this contact is not associated with any Salesforce account record. Contact ID: ${recordIds.salesforceContactId}`);
throw 'couldNotCreateActivity';
}
let trimmedLinkedinUrl;
if(linkedinUrl) {
trimmedLinkedinUrl = linkedinUrl.replace(sails.config.custom.RX_PROTOCOL_AND_COMMON_SUBDOMAINS, '');
}
// Create the new Fleet website page view record.
let newHistoricalRecordId = await sails.helpers.salesforce.createHistoricalEvent.with({
salesforceAccountId: recordIds.salesforceAccountId,
salesforceContactId: recordIds.salesforceContactId,
eventType: 'Intent signal',
intentSignal: intentSignal,
eventContent: historicalContent,
eventContentUrl: historicalContentUrl,
linkedinUrl: trimmedLinkedinUrl,
relatedCampaign,
})
.intercept((err)=>{
sails.log.warn(`When the receive-from-clay webhook received information about LinkedIn activity, a historical event record could not be created. Full error: ${require('util').inspect(err)}`);
return 'couldNotCreateActivity';
});
// All done.
return {
historicalRecordId: newHistoricalRecordId,
contactId: recordIds.salesforceContactId,
accountId: recordIds.salesforceAccountId
};
}
};