• facebook
  • twitter
  • linkedin

Check for Associations with Custom Workflow Actions

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) to false.
  • 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

  1. Settings → Integrations → Private Apps → Create app
  2. Name it something like “Object Association Check”.
  3. Scopes – enable:
    crm.objects.contacts.read & crm.objects.contacts.write
    crm.objects.custom.read (this changes depending upon the object)
  4. Copy the token; you’ll paste it into the workflow’s secret.

3. Drop the Custom Code Action Into Your Workflow

  1. Automation → Workflows — build (or edit) a Contact-based workflow.
  2. Add a “Custom Code” action right after enrollment.
  3. Open Secrets, add a new secret, name it, and paste your token.
  4. 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

  1. Reads the contact’s EDITTHIS property.
  2. 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.
  3. 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

  1. Create a dummy contact with a EDITTHIS that doesn’t exist in your Listing object.
  2. Manually enroll the contact.
  3. Watch the execution history:
    • Code action should run → flag = false → contact flows down the “Missing association” branch.
  4. 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!

Comments (0)
Other

Insights You Might Like

Automatically Tag...

HubSpot stores heaps of data about your contacts, but it doesn’t natively track
Read More

Rank the Top Candidates...

Matching applicants to open roles is only half the battle; you still need to...
Read More

Auto-Populate Deals from...

When a subscription is created in HubSpot—often via Stripe, Chargebee or a...
Read More