HubSpot Integration
This guide explains how to send HubSpot CRM events as goal events to ABsmartly using HubSpot Workflows. This allows you to track CRM activities — such as deal creation, contact form submissions, or lifecycle stage changes — as metrics in your experiments.
Prerequisites
- ABsmartly account with access to the Web Console and a valid SDK API Key.
API Keys can be created under
Settings > API Keysin the ABsmartly Web Console. - HubSpot account with an Operations Hub Professional or Enterprise subscription (required for custom code workflow actions).
- A unit type (e.g.
user_idoremail) that is shared between your ABsmartly experiments and your HubSpot contacts so that events can be attributed to the correct user.
info
HubSpot's built-in Send a webhook action only supports flat key-value JSON payloads. Because the ABsmartly Collector API requires nested objects (
units, goals), this guide uses a Custom Code Action instead, which gives full control over the request body.Step 1 — Store Your API Key as a Secret
- In HubSpot, go to Automation > Workflows.
- Open or create a workflow.
- Click the + icon to add an action, then select Custom code.
- In the Secrets section, click Add secret and create a secret:
- Secret name:
ABSMARTLY_API_KEY - Secret value: Your ABsmartly SDK API Key
- Secret name:
Step 2 — Create a Workflow with a Custom Code Action
- Create a new workflow and choose a type (e.g. Contact-based or Deal-based).
- Set up your enrollment triggers. You can add multiple triggers within the same
object type. For example, for a deal-based workflow:
Deal is createdDeal stage is Closed WonDeal property pipeline is changed
- Click the + icon and select Custom code.
- Set the Language to
Node.js 20.x. - Under Properties to include in code, add the HubSpot properties you need.
For example, for a deal-based workflow:
dealnamedealstagepipeline- Associated contact
email hs_enrollment_trigger(contains the trigger that enrolled the record)
- Paste the following code:
const axios = require("axios");
const GOAL_NAMES = {
"CREATE-deal": "hubspot_deal_created",
"PROP_CHANGE-dealstage-closedwon": "hubspot_deal_won",
"PROP_CHANGE-pipeline": "hubspot_deal_pipeline_changed",
};
function resolveGoalName(trigger) {
for (const [key, goalName] of Object.entries(GOAL_NAMES)) {
if (trigger.includes(key)) {
return goalName;
}
}
return "hubspot_deal_event";
}
exports.main = async (event) => {
const email = event.inputFields["email"];
if (!email) return;
const trigger = event.inputFields["hs_enrollment_trigger"] || "";
const goalName = resolveGoalName(trigger);
const now = Date.now();
await axios.put(
"https://your-subdomain.absmartly.io/v1/context",
{
publishedAt: now,
units: [
{
type: "email",
uid: email,
},
],
goals: [
{
name: goalName,
achievedAt: now,
properties: {
deal_name: event.inputFields["dealname"],
deal_stage: event.inputFields["dealstage"],
pipeline: event.inputFields["pipeline"],
},
},
],
},
{
headers: {
"Content-Type": "application/json",
"X-API-Key": process.env.ABSMARTLY_API_KEY,
"X-Application": "www",
"X-Application-Version": "0",
"X-Environment": "production",
"X-Agent": "hubspot-workflow",
},
}
);
};
- Click Save and turn the workflow on.
The code uses the hs_enrollment_trigger property to determine which trigger enrolled
the record and maps it to the appropriate ABsmartly goal name. Edit the GOAL_NAMES
mapping to match the triggers you configured in step 2.
tip
Replace
your-subdomain with your actual ABsmartly subdomain, and update the X-Application and X-Environment header values to match your ABsmartly Web Console settings under Settings > Applicationsand Settings > Environments.tip
Adjust the
units type and value to match the unit type you use in your ABsmartly experiments. For example, if your experiments use a user_id unit, include a custom HubSpot property that stores the user ID and reference it in the code.Step 3 — Create the Goals in ABsmartly
- In the ABsmartly Web Console, go to Settings > Goals.
- Create goals matching each name in the
GOAL_NAMESmapping (e.g.hubspot_deal_created,hubspot_deal_won). - You can now use these goals as metrics in any of your experiments.
Tracking Different Object Types
A single workflow can handle multiple triggers within the same HubSpot object type. For different object types, create a separate workflow for each:
| Workflow type | Example triggers | Goal names |
|---|---|---|
| Deal-based | Deal created, Deal stage changed, Deal won | hubspot_deal_created, hubspot_deal_won |
| Contact-based | Contact created, Lifecycle stage changed, Form submitted | hubspot_contact_created, hubspot_became_customer, hubspot_form_submitted |
| Ticket-based | Ticket created, Ticket status changed | hubspot_ticket_created, hubspot_ticket_closed |
Verifying the Integration
- Trigger a test event in HubSpot (e.g. create a test deal) from a user whose identifier is also being tracked in an ABsmartly experiment.
- Check the ABsmartly Web Console under the experiment's goals to verify the event was received.
- In HubSpot, check the workflow's History tab to confirm the custom code action executed successfully.
info
Custom code actions must complete within 20 seconds and use a maximum of 128 MB of memory. Failed requests due to rate limiting (429) or server errors (5xx) are automatically retried by HubSpot for up to three days. If you add a
try/catch block, make sure to re-throw the error after logging — otherwise HubSpot won't retry the action.If you have any issues setting up the HubSpot integration, please contact us at [email protected].