HubSpot’s built-in If/then branch condition Association exists is handy—until it isn’t. When the condition fails (for example, a contact isn’t associated with a deal or custom object) the record still plows straight through the rest of the workflow, often triggering emails or not and updates you never intended.
The custom coded action below fixes that gap:
- It checks whether the current record is associated to another object (in this tutorial: a Listing custom object).
- If no match is found, it flips a Boolean property on the contact (
associated
) tofalse
. - That flag lets you branch the workflow cleanly—no more orphaned contacts slipping through the cracks.
When to Use This Pattern
Scenario | Why It Helps |
---|---|
Real-estate brokerages (your yacht & boat listings) | Skip nurture emails when a lead isn’t tied to an active listing. |
B2B account-based marketing | Halt hand-off steps when a contact isn’t linked to a target account object. |
Event registrations | Prevent confirmation sequences if a registrant record never linked to the correct Event object. |
Step-by-Step Implementation
1. Create or Confirm the Key Properties
Property | Object | Type | Purpose |
---|---|---|---|
boatsgroupid |
Contact | Single-line text (or number) | Holds the external ID you’ll match on. |
associated_with_listing |
Contact | Boolean (Yes/No) | Becomes the branch trigger. Default to Yes. |
2. Spin Up a Private App Token
- Settings → Integrations → Private Apps → Create app
- Name it something like “Object Association Check”.
- Scopes – enable:
•crm.objects.contacts.read
&crm.objects.contacts.write
•crm.objects.custom.read
(this changes depending upon the object) - Copy the token; you’ll paste it into the workflow’s secret.
3. Drop the Custom Code Action Into Your Workflow
- Automation → Workflows — build (or edit) a Contact-based workflow.
- Add a “Custom Code” action right after enrollment.
- Open Secrets, add a new secret, name it, and paste your token.
- Paste and update the code below.
// ---- Begin Custom Code Action ----
const axios = require('axios');
exports.main = async (event) => {
const contactId = event.object.objectId; // Current contact
const boatsGroupId = event.inputFields['EDITTHIS'];
if (!boatsGroupId) {
console.log('No boatsgroupid value. Skipping...');
return { outputFields: {} };
}
const SEARCH_URL = 'https://api.hubapi.com/crm/v3/objects/2-40512918/search'; // custom object ID
const TOKEN = process.env.EDITTHIS;
try {
// 1️⃣ Does a Listing exist with EDITTHIS = EDITTHIS ?
const searchRes = await axios.post(
SEARCH_URL,
{
filterGroups: [{
filters: [{ propertyName: 'EDITTHIS', operator: 'EQ', value: EDITTHIS}]
}],
properties: ['hs_object_id']
},
{ headers: { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' } }
);
const listingsFound = searchRes.data.total || 0;
console.log(`Listings found: ${listingsFound}`);
// 2️⃣ If zero, set associated_with_listing = false
if (listingsFound === 0) {
await axios.patch(
`https://api.hubapi.com/crm/v3/objects/contacts/${contactId}`,
{ properties: { associated_with_listing: false } },
{ headers: { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' } }
);
console.log(`Flag flipped for contact ${contactId}.`);
}
} catch (err) {
console.error('Error in association check:', err.response?.data || err.message);
throw err; // surfaces error in workflow log
}
return { outputFields: {} };
};
// ---- End Custom Code Action ----
How it works
- Reads the contact’s
EDITTHIS property
. - Searches the Listing custom object (be sure to update your objects in the code and private app scopes to what is relevant for you) for a matching
EDITTHIS on that object
. - Updates the contact’s Boolean flag to
false
if no match exists.
4. Build the Branch
Add an If/then branch immediately after the code action:
- Branch 1 – “Is associated” →
associated
is Yes
Proceed with your standard nurture, notifications, etc. - Branch 2 – “Missing association” → associated is No
Send to an error queue, create a task, or trigger an internal alert.
Pro tip: set the Boolean’s default to Yes. Only unlinked contacts flip to No, keeping existing workflow logic intact.
5. Test Before You Go Live
- Create a dummy contact with a EDITTHIS that doesn’t exist in your Listing object.
- Manually enroll the contact.
- Watch the execution history:
• Code action should run → flag = false → contact flows down the “Missing association” branch. - Repeat with a contact whose EDITTHIS does match a Listing to verify the positive path.
Results & Benefits
- Bullet-proof branching — records without the needed association are cleanly diverted.
- Higher data hygiene — erroneous or orphaned contacts are flagged instantly.
- Less manual cleanup — sales & success teams spend time closing deals, not fixing workflows.
Wrapping Up
HubSpot’s out-of-the-box association checks are useful but incomplete when you need deterministic branching. With a lightweight custom coded action and a single Boolean property, you gain precise control over your workflow logic—ensuring only properly linked records reach your downstream automation.
Have questions or want to see other Operations Hub recipes? Drop us a line ben@noboundsdigital.com and let’s keep building smarter workflows!