Using Custom Code in HubSpot Workflow

Share This Post

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: (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:

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:

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.

HubSpot Workflow
Access Workflow Editor

Click on Create workflow at the top right of the screen.

Create HubSpot Workflow
Create a New Workflow

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. 

Custom HubSpot Workflow
Name and Start

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.

Configure HubSpot Workflow
Define Type of Workflow

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:

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.

HubSpot Workflow Trigger
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.

Workflow Trigger Type
Define Trigger Event Step 1
Define Trigger Event Step 2
Workflow Filter
Define Trigger Event Step 3
Save HubSpot Workflow
Define Trigger Event Step 4

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.

HubSpot Add Action to Workflow
Add an Action
Create a Custom Code Action

The next step on the screen will look like the screenshot below:

Configure Custom Code in Workflow

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.

Workflow Credentials
Add a Secret

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.

Add Secret Name and Value

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.

Select and Use the Secret

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.

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 =;

        console.log("****** Contact email for current contact: " + currentContactsEmail);

        unsubscribeInDotdigital(currentContactsEmail).then(unsubscribeResponse => {

                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
            .then(results => {
            .catch(err => {
                console.error("***** Got an exception while attempting to load current contact: " + err.message);


function unsubscribeInDotdigital(emailToUnsubscribe) {
    console.log("ENTERING: unsubscribeInDotdigital");

    return new Promise(function (resolve, reject) {

        let options = {
            'method': 'POST',
            'hostname': '',
            '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) {
            res.on("end", function (chunk) {
                let body = Buffer.concat(chunks);
                console.log("****** Made API call to merge. Resulting body: " + body.toString());
            res.on("error", function (error) {

        let postData = JSON.stringify({
            "email": emailToUnsubscribe



View HubSpot Custom Code
Test Action

Once you are satisfied with the code provided, you can hit Save.

Publish HubSpot Custom Code

Now click on Review and Publish to engage the workflow and your custom code action.

Review and Publish

On the last screen, you may now click Turn on and run your workflow! 

Activate Workflow
Turn on and Run

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.

More To Explore

great software requirements word cloud

The Value of Documenting Great Requirements

Why Great Requirements Matter When properly captured, requirements are the ground-level representation of core business goals. Defining good requirements can lead to fantastic products and delighted clients. But capturing clear

How to facilitate a great meeting

A Great Facilitator Drives Successful Conversations

How to Be a Great Meeting Facilitator Being an effective facilitator of company meetings is no easy feat. Effective facilitators employ many skills and often must think and act quickly