HubSpot is a powerful customer relationship management system that often needs to be integrated with many other systems. This can include ERPs, internal systems, marketing, and ecommerce platforms. Unless you chose HubSpot as the first CRM for your business, you may now be looking to, or already in the process of, transitioning to HubSpot.
Workflow-Powered Integration
For this reason, it is very helpful to know all the ways in which your HubSpot platform can communicate with your other systems. The most common way is through apps offered on HubSpot’s App Marketplace. Second is to manipulate the data in your HubSpot portal programmatically using the HubSpot API. Lastly, if you are a marketing hub professional, enterprise sales hub professional, enterprise service hub professional or enterprise operations hub professional customer then you have a third option! You can use your own custom logic in workflows.
If you’re not familiar with workflows, they’re an extremely easy way to automate complex business logic within your HubSpot portal. HubSpot offers a plethora of great documentation about workflows in their knowledge base and on “HubSpot Academy.” To learn more about what workflows are, take a deep dive into all the amazing things workflows have to offer here: https://app.hubspot.com/academy/lessons/1002820/4230 (HubSpot Academy Login is required)
Two Workflow Approaches
There are two very powerful ways to use your own custom logic in workflows. The first is utilizing triggers and webhooks. This allows you to make calls to an external endpoint and then perform an action on the external system. If you’re interested, we’ve written an article on how to utilize webhooks here: https://bluefishgroup.com/insights/ecommerce/setup-a-hubspot-magento-webhook/
Second is to use custom code in your workflow. This option allows nearly endless possibilities to achieve custom business logic using your own data housed in HubSpot. Essentially, you can write and execute custom Node.JS JavaScript code to manipulate data inside and outside of HubSpot. Again, HubSpot offers some pretty great documentation about using custom code in workflows on their knowledge base here: https://knowledge.hubspot.com/workflows/use-custom-code-actions-in-workflows
HubSpot and DotDigital Example
It can be very helpful to have real world examples to really understand how best to utilize a technology such as this. Hence the reason for this article! We have discovered, while migrating clients from other CRMs to HubSpot, that there is a period of transition where you may be running on both or many platforms at once. It then becomes incredibly important for these systems to be able to communicate with each other and keep their data in synch. For this example, we’d like to illustrate how to use custom code in workflows to keep contacts who have unsubscribed in HubSpot also unsubscribed in your legacy CRM. For this example, that legacy system will be DotDigital. Let’s get started!
Step-by-Step Instructions
First, after logging into your HubSpot CRM portal, navigate using the top menu to locate Automation > Workflows.
Click on Create workflow at the top right of the screen.
You are now on the workflow editor. First provide a name for your workflow. For this example, I will name it Using Custom Code in Workflows.
After you have edited the name, click on Start from scratch. This will allow you to create and manipulate a workflow in any way that you wish. For this example, I will be selecting Contact-based Workflow since I want to manipulate the data on a HubSpot Contact. But webhooks and triggers are available for other HubSpot entities as well. If you wanted instead to manipulate data for a HubSpot Deal, you would need to instead select a Deal-based Workflow. The information that can be manipulated via custom code is based on the type of workflow you choose.
All workflows start with an enrollment trigger – so you must start there. An enrollment trigger is an event that allows your workflow to be executed. For instance, if a HubSpot CRM contact fills out a specific form on your website or if they engaged with a specific marketing campaign. There are many different scenarios and qualifiers. HubSpot provides lots of helpful information about enrollment triggers here: https://knowledge.hubspot.com/workflows/set-your-workflow-enrollment-triggers
For this example, I wish to have my workflow run for any contact that opted out of receiving marketing communications using the HubSpot subscription preferences page. When first landing on the workflow editor, the first section will prompt you to set an enrollment trigger. Click on the button Set Enrollment Trigger.
The next panel that pops up will ask when you want this trigger to be executed. For this example, I am going to select Trigger this workflow when a Contact has opted out of all Customer Service communication.
Now you will add your next action. This is where you’re going to set up the webhook that will make a call to DotDigital to transmit data about this contact.
The next step on the screen will look like the screenshot below:
I’m going to pause for a moment to explain what you are seeing here. Secrets are configuration values that you can store relative to your HubSpot portal. For example, if you have API keys for a third-party service you want to contact as part of your custom code action, then you would want to store your API Key in a secret rather than storing it in the custom code itself. As HubSpot says, these values are encrypted and stored securely on HubSpot’s servers. You can define any number of secrets to be used across your HubSpot portal. In your custom code, you will only have access to the secrets in the dropdown shown in the screenshot that you have selected. If you have not selected the secret that you want to use, it will not be available to you and will throw an error. The dropdown is a multiple select, so you can utilize more than one secret at a time. In case it isn’t obvious, which it sometimes isn’t, you can add/manage secrets after opening the Choose a secret dropdown. Let’s go ahead and add a new secret to use in our custom code.
For this example, we’re going to be setting up a new secret for the Base64 API key allowing us to communicate with the DotDigital API.
HubSpot, being the super intuitive platform that it is, lets you know on the next screen how to use this new environment variable and already pre-selects this secret to be accessible in your custom code.
The next step is to then provide the code for the custom logic you wish to have triggered when your enrollment criteria has been met and your workflow logic has processed. HubSpot does a great job documenting how to code the logic for this section. Use these links to dive in and get a better understanding of using custom code, debugging, formatting, limitations, and testing.
https://knowledge.hubspot.com/workflows/use-custom-code-actions-in-workflows
https://developers.hubspot.com/docs/api/workflows/custom-code-actions
Here is our example of unsubscribing a contact from DotDigital using custom code:
Example Code
Finishing Up
This code contacts DotDigital via the unsubscribe API endpoint. This is quite a basic example but illustrates the formatting and basic practices of using custom code in workflows.
It is VERY important to note that HubSpot does NOT auto-save the contents of the code entered in the text area when editing the custom code action. If you are making changes, be sure to save frequently so that you don’t lose your changes.
If you were instead manipulating the data on a contact within HubSpot, the Test action feature is very helpful. You can trigger the custom code to process for a specific contact and then you can see the changes that were made as a result of your custom code being triggered.
const hubspot = require('@hubspot/api-client');
const https = require('follow-redirects').https;
exports.main = (event, callback) => {
// Secrets can be accessed via environment variables.
// Make sure to add your HAPIKEY under "Secrets" above.
const hubspotClient = new hubspot.Client({
apiKey: process.env.HAPIKEY
});
// First, we need to find the contact that's associated with this entity
let currentContactID = event.object.objectId;
console.log("******* Current contact ID is: " + currentContactID);
fetchContactByObjectId(hubspotClient, currentContactID).then(currentContact => {
let currentContactsEmail = currentContact.properties.email;
console.log("****** Contact email for current contact: " + currentContactsEmail);
unsubscribeInDotdigital(currentContactsEmail).then(unsubscribeResponse => {
callback({
outputFields: {
results: JSON.stringify(unsubscribeResponse)
}
});
});
});
}
function fetchContactByObjectId(hubspotClient, contactId) {
console.log("ENTERING: fetchContactByObjectId");
return new Promise(function (resolve, reject) {
// Get associated contacts for the current deal
hubspotClient.crm.contacts.basicApi.getById(contactId)
.then(results => {
resolve(results.body);
})
.catch(err => {
console.error("***** Got an exception while attempting to load current contact: " + err.message);
reject(err);
});
});
}
function unsubscribeInDotdigital(emailToUnsubscribe) {
console.log("ENTERING: unsubscribeInDotdigital");
return new Promise(function (resolve, reject) {
let options = {
'method': 'POST',
'hostname': 'r2-api.dotmailer.com',
'path': '/v2/contacts/unsubscribe',
'headers': {
'Content-Type': 'application/json',
'Authorization' : 'Basic ' + process.env.DOTDIGITAL_CREDS_BASE64
},
'maxRedirects': 20
};
let req = https.request(options, function (res) {
let chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function (chunk) {
let body = Buffer.concat(chunks);
console.log("****** Made API call to merge. Resulting body: " + body.toString());
resolve(body);
});
res.on("error", function (error) {
console.error(error);
reject(error);
});
});
let postData = JSON.stringify({
"email": emailToUnsubscribe
});
req.write(postData);
req.end();
});
}
Once you are satisfied with the code provided, you can hit Save.
Now click on Review and Publish to engage the workflow and your custom code action.
On the last screen, you may now click Turn on and run your workflow!
We hope that this article has been helpful in providing you the tools to be able to trigger custom code from a HubSpot CRM workflow. If you have any additional questions, please don’t hesitate to reach out to us! We are always happy to help.