• facebook
  • twitter
  • linkedin

Auto-Merge Call-Tracking Duplicates in HubSpot

Tools like CallRail push phone calls straight into HubSpot, creating contacts that often have no email address. Native duplicate management leans heavily on email, so phone-only contacts pile up fast. The custom code action below finds those records, confirms they match on full name and address, and merges them automatically—keeping your CRM tidy without manual intervention.

  • Eliminates duplicate contacts generated by call-tracking integrations.
  • Merges records in real time, before they trigger workflows or reports.
  • Uses city and street address for higher confidence when email is missing.

Typical Use Cases

Scenario Why It Matters
CallRail or similar phone-tracking apps Each phone call can create a new phone-only contact; merging prevents duplicates in reporting and sequences.
Brick-and-mortar businesses Customers often provide phone and address at checkout but not email; address helps verify true duplicates.
Service industries with repeat callers Returning clients may call again from ads, generating extra contacts that clutter pipelines.

Step-by-Step Implementation

1. Prerequisites

  • Create a private app token with crm.objects.contacts.read and crm.objects.contacts.write scopes. Store it in the workflow action as MyContacts.
  • Make sure your earlier deduplication step flags records with likely_duplicated_by = Full Name and Address.

2. Insert the Custom Code Action

  1. Create or edit a Contact-based workflow that runs after the duplicate-flagging step.
  2. Add a Custom Code action and reference the secret MyContacts.
  3. Paste the script below.

const hubspot = require('@hubspot/api-client');
exports.main = async (event) => {

  const hubspotContacts = new hubspot.Client({
    accessToken: process.env.MyContacts
  });

  // 1. Get current contact details
  let id, first, last, city, street, flag;
  try {
    const res = await hubspotContacts.crm.contacts.basicApi.getById(
      event.object.objectId,
      ['hs_object_id','firstname','lastname','city','address','likely_duplicated_by']
    );
    id     = res.body.properties.hs_object_id;
    first  = res.body.properties.firstname;
    last   = res.body.properties.lastname;
    city   = res.body.properties.city;
    street = res.body.properties.address;
    flag   = res.body.properties.likely_duplicated_by;
  } catch (err) {
    console.error(err);
    throw err;
  }

  // 2. Only proceed if this record was flagged by previous step
  if (flag !== 'Full Name and Address') return;

  // 3. Search for duplicates with same name + address, exclude self
  let dupIds = [];
  try {
    const search = await hubspotContacts.apiRequest({
      method: 'POST',
      path: '/crm/v3/objects/contacts/search',
      body: {
        filterGroups: [{
          filters: [
            { propertyName:'city',  operator:'EQ', value: city },
            { propertyName:'address', operator:'EQ', value: street },
            { propertyName:'likely_duplicated_by', operator:'EQ', value:'Full Name and Address' }
          ]
        }],
        limit: 100
      }
    });
    dupIds = search.body.results
      .filter(c => Number(c.id) !== Number(id) &&
                  c.properties.firstname === first &&
                  c.properties.lastname === last)
      .map(c => c.id);
  } catch (err) {
    console.error(err);
    throw err;
  }

  // 4. Merge if exactly one duplicate is found
  if (dupIds.length === 1) {
    try {
      await hubspotContacts.apiRequest({
        method: 'POST',
        path: '/contacts/v1/contact/merge-vids/' + dupIds[0],
        body: { vidToMerge: id }
      });
    } catch (err) {
      console.error(err);
      throw err;
    }
  }
};

3. Test Thoroughly

  1. Create two contacts through CallRail with same name and address.
  2. Run the duplicate-flagging step first, then this merge step.
  3. Confirm one master record remains and timelines are combined.
  4. Create a third contact with same city but different address and verify it is not merged.

Results and Benefits

  • Phone-only duplicates from call tracking are merged automatically.
  • Sales reps see a single timeline per caller, improving context and follow-up.
  • Lists, dashboards and attribution remain accurate without manual cleanup.

Wrapping Up

Email-centric deduplication misses many contacts created by call-tracking systems. By pairing a flag-then-merge workflow with custom code, you can keep HubSpot clean even when new records arrive with only a phone number. Adapt the filters to include other identifiers such as state or zip if your data requires tighter matching.

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