Custom code workflow actions

In workflows, you can use the Custom code action to write and execute JavaScript or Python (in beta) in your workflow. With custom code actions, you can extend workflow functionality within and outside of HubSpot. To learn more about HubSpot's APIs, you can refer to either the developer documentation for the latest versions or the legacy developer documentation for our older APIs. To see examples of common custom code actions, view HubSpot's Programmable Automation Use Cases.

Custom code actions support JavaScript using the Node 12.x runtime framework. If you're using Python for your custom code action, the custom code action will use Python 3.6 runtime framework. When an action executes, the runtime compute is managed through a serverless function by HubSpot and AWS Lambda.

Node.js supported libraries

If you're using Node.js, the following libraries are available for use within the code action. These libraries can be loaded using the normal require() function at the top of your code.

  • @hubspot/api-client ^3.4.1
  • async ^3.2.0
  • aws-sdk ^2.858.0
  • axios ^0.20.0
  • lodash ^4.17.20
  • mongoose ^5.11.19
  • mysql ^2.18.1
  • redis" ^3.0.2
  • request" ^2.88.2
  • bluebird 3.7.2
  • random-number-csprng 1.0.2
  • googleapis 67.1.1

Python supported libraries

If you're using Python, you can load the following libraries with an import statement at the top of your code. The import statement should be formatted as from [libraryname] import [item], such as  from redis.client import redis.

  • requests 2.26.0
  • @hubspot/api-client 4.0.4
  • google-api-python-client 2.31.0
  • mysql-connector-python 8.0.27
  • redis 4.0.1
  • nltk 3.4.5

If you're using anything from the standard library, you can use import, such as  import os.

Create a custom code action

To add a custom code action to a workflow:

  • In your HubSpot account, navigate to Automation > Workflows.
  • Click the name of a workflow, or create a new workflow
  • Click the + plus icon to add a workflow action.
  • In the right panel, select Custom code.
 

custom-code-action-select

  • In the right panel, set up your action:
    • By default, custom code actions will use Node.js 12.x. If you’re in the Python beta and want to build your action with Python, click the Language dropdown menu, then select Python.
    • To add a new secret, such as an API key, click Add secret. Learn more about how you can access and retrieve your HubSpot API key. You can also learn more about secrets in HubSpot's developer documentation.
    • In the dialog box, enter the Secret name and Secret value.
    • Click Save. You can now select this secret in future custom code actions.
    • To edit or delete existing secrets, click Manage secrets.
  • To include properties in your custom code, click the Choose property dropdown menu, then select a property. You can use existing properties or previously formatted property values in the workflow. After selecting your property, enter a Property name to use in your code. Learn how to reference properties in your custom code
  • To add another property, click Add property. Each property can only be added once and must have a unique Variable ID.  You can use up to 50 properties with your custom code. 
  • To delete a property,  click the delete icon.
  • In the code field, enter your JavaScript or Python.
  • To define data outputs that can be used as inputs later in the workflow, for example with a Copy property value action:
    • Under Data outputs, click the Data type dropdown menu, and select a type of data.
    • In the Name field, enter a name for the data output.
    • To add multiple outputs, click Add output.
  • Click Save.

The code field will not display lint errors when using Python. 

When building custom code actions, keep the following in mind: 

  • The def main(event): function is called when the code snippet action is executed.
  • The event argument is an object containing details for the workflow execution.
  • The callback() function is used to pass data back to the workflow. It should be called in the exports.main function. This can only be used with Node.js. 

The event object will contain the following data:

JSON
//example payload
{
  "origin": {
    // Your portal ID
    "portalId": 1,    // Your custom action definition ID
    "actionDefinitionId": 2,
  },
  "object": {
    // The type of CRM object that is enrolled in the workflow
    "objectType": "CONTACT",    // The ID of the CRM object that is enrolled in the workflow
    "objectId": 4,
  },
  // A unique ID for this execution.
  "callbackId": "ap-123-456-7-8"
}

Test the action

When adding a custom code action to a workflow, you can test the action to ensure that your code runs as expected before turning the workflow on.

When testing a custom code action, you'll start by selecting a record to test the code with, then run the code. This test will run only the code in your custom action, not any of the other actions in the workflow. When the code is finished running, you'll be able to view the code outputs and the log of your test.

When testing your custom code, the code will run and any changes will apply to the selected test record. It's recommended to create a dedicated test record if you want to avoid updating your live records. 

To test a custom code action:

  • In the workflow timeline, click the custom code action.
  • At the bottom of the right sidebar, click Test action to expand the testing section.
    workflow-custom-code-test-expand
  • Select a record to test your code with by clicking the [Object] dropdown menu, then selecting a record.
    workflow-custom-code-action-test2
  • If you're using previously formatted property values in the workflow, enter a test value for the formatted data.   

  • To run the code, click Test.
  • In the dialog box, confirm that you want to test your code against the selected record by clicking Test.
  • Once your code is done running, the sidebar will display the results of your test:
    • Status: the success or failure status of your custom code action.
    • Data outputs: the values that resulted for your defined data outputs. An alert will display next to any outputs that the code generated which weren't defined either in the Data outputs section or in the code editor. You'll need to add those outputs in order to use them later in the workflow.
    • Logs: information about the test itself, such as how much memory the action took to execute and the total runtime. 

      workflow-custom-code-action-test0results0
  • To update your custom code action, click Create action to expand the action editor. Continue to update and test your code as needed.
  • When you're done testing the action, click Save to save your changes.

Secrets

There are times you will want your code to reference something that shouldn't be widely shared. Most often, this is a means of authentication, like an API key.  You can manage the secrets your function has access to directly in the workflow action definition.

From there, you will be able to add whatever values you need, including your HubSpot API key. You can access your HubSpot API key from your account settings. 

Once added, the secrets will be available as environment variables. 

const hubspot = require('@hubspot/api-client');
exports.main = (event, callback) => {
  return callback(processEvent(event));
};function processEvent(event) {
  // secrets can be accessed via environment variables
  const hubspotClient = new hubspot.Client({ apiKey: process.env.HAPIKEY });
  hubspotClient.crm.contacts.basicApi.getById(event["object"]["objectId"], ["email", "phone"])
  .then(results => {
    let email = results.body["properties"]["email"]
    let phone = results.body["properties"]["phone"]
    // ...
  })
  .catch(err => {
    console.error(err)
  })
}

Add HubSpot properties to your custom code

At times, you may need to fetch object properties in your custom code action. Rather than using HubSpot's APIs, you can add these properties directly in the workflow action definition. Add properties and set property names to reference properties in your code. You can add up to 50 properties in each custom code action.  

Once added, the property can be referenced in the custom code. 

const email = event.inputFields['email'];

Logging

An important tool for developers is ability to print outputs from their code. It helps you debug issues and provide better support for your end users. To see the output of the logs, you can find them in the "History" tab of the workflow.  

custom_code_logs

How to Define Outputs

In the function, define the output fields you want to use later in the workflow. Then, in the right sidebar, select the data output type (e.g., number, string, boolean, datetime, enum, date phone number) and input the field you want to output.

The output fields should be part of a json object formatted accordingly, depending on the language used:

  callback({
    outputFields: {
      email: email,
      phone: phone
    }
  });
Custom Code - Output

You can then use the output from your code action as in input to the Copy property value action. This removes the need to make another API call to store the value as a property on your object.

If you're using the Copy property value action, please also take note of compatible source and target properties. Do also note that if you're copying an output to a datetime property, the output will need to be in UNIX millisecond format.

custom_code_actions_output_usage

Limitations

Custom code actions must finish running within 20 seconds and can only use up to 128 MB of memory. Exceeding either of these limits will result in an error. 

Retries

You may need to fetch object properties using the HubSpot API or to call other HubSpot API endpoints in your custom code action. Like any other API call, you'll still need to comply with HubSpot API rate limits.

  • If you're using Node.js and encounter a rate limiting error but you want HubSpot to retry your call, you'll need to throw the error in the catch block of your custom code action.

  • If you're using Python and encounter a rate limiting error but you want HubSpot to retry your call, you'll need to raise the error in the except block of your custom code action.

If the call fails due to a rate limiting error, or a 429 or 5XX error from axios or @hubspot/api-client, HubSpot will reattempt to execute your action for up to three days, starting one minute after failure. Subsequent failures will be retried at increasing intervals, with a maximum gap of eight hours between tries

Caveats

If you're using Node.js for your custom code, do take note of the following caveats: 
  • Generating random numbers: it's common to use Math.random to generate random numbers but users may see the same numbers generated across different executions. This is because Math.random is seeded by the current time. Since HubSpot may enroll many objects into a workflow at the same time and clear the state on every execution, different executions end up seeding Math.random in the same way. Instead, you can use of random-number-csprng 1.0.2 library which guarantees cryptographically secure pseudo-random number generation.
  • Variable re-use:  to save memory, any variables declared outside the exports.main function may be re-used for future executions of the custom code action. This is useful when connecting to external services like a database, but any logic or information that needs to be unique to each execution of the custom code action should be inside the exports.main function.

If you're using Python for your custom code, do take note of the following caveats:

  • Variable re-use: similar to the above, any variables declared outside the def main function may be re-used for future executions of the custom code action.
    • If you've declared a variable outside the def main function but do not plan on altering it, you can reference the variable directly.
    • If you plan on altering a variable, you can declare the variable within the def main function with a global keyword before referencing it. 
HubL
a = 1
def main(event):
  global a
  a += 1

Was this page helpful? *
This form is for feedback on our developer docs. If you have feedback on the HubSpot product, please share it in our Idea Forum instead.