Route HubSpot leads by territory and company size using Make
Prerequisites
- Make account (Core plan or higher recommended)
- HubSpot connection configured in Make via OAuth
- Slack connection configured in Make
- Enriched company data in HubSpot (state, country, employee count)
Why Make?
Make's visual Router module makes branching logic transparent — you can see every territory path on the canvas at once. The JavaScript Code module (Core plan, $10.59/mo) handles complex routing in a single block, which is cleaner than chaining Router filters for each territory. Make is also significantly cheaper than Zapier for high-volume routing: the Core plan gives you 10,000 operations/month (~1,700 routed leads) for $10.59 vs. Zapier's $29.99 for 2,000 tasks.
The trade-off is that Make uses polling (Watch Contacts checks for new contacts on a schedule), so routing isn't instant. The default interval is 15 minutes; you can reduce it on paid plans. For sub-minute routing, use the Code approach with webhooks.
How it works
- Watch Contacts module polls for new contacts at a set interval
- HTTP module fetches the contact's company association and company data
- Router branches: existing account owner vs. new territory assignment
- Code module applies enterprise override and territory matching on the new-account branch
- HubSpot module updates the contact's owner
- Slack module DMs the assigned rep
Step 1: Add a Watch Contacts trigger
Create a new scenario. Add a HubSpot CRM -> Watch Contacts module:
- Connection: Your HubSpot OAuth connection
- Watch: New contacts
- Limit: 10
- Properties: Select
firstname,lastname,email,company,jobtitle,state,country,hubspot_owner_id
Step 2: Get the associated company
Add an HTTP module to fetch the contact's company association:
- URL:
https://api.hubapi.com/crm/v3/objects/contacts/{{1.id}}/associations/companies - Method: GET
- Headers: Use HubSpot connection for auth
Then add a HubSpot CRM -> Get a Company module:
- Company ID:
{{2.results[1].id}}(first associated company) - Properties:
name,numberofemployees,state,country,hubspot_owner_id
Step 3: Check for existing account owner
Add a Router with two routes:
Route 1: Existing account owner (company has hubspot_owner_id)
- Filter:
hubspot_owner_idis not empty - This route skips territory logic and assigns the contact to the existing company owner
Route 2: New account — apply territory rules
- Filter:
hubspot_owner_idis empty (or does not exist)
Step 4: Apply territory routing with a Code module
On Route 2, add a JavaScript Code module:
const state = (company.state || contact.state || '').toUpperCase();
const employees = parseInt(company.numberofemployees || '0');
const territories = {
'NY': { ownerId: '111111', slackId: 'U01AAAA', rep: 'Alice' },
'MA': { ownerId: '111111', slackId: 'U01AAAA', rep: 'Alice' },
'CT': { ownerId: '111111', slackId: 'U01AAAA', rep: 'Alice' },
'CA': { ownerId: '222222', slackId: 'U02BBBB', rep: 'Bob' },
'WA': { ownerId: '222222', slackId: 'U02BBBB', rep: 'Bob' },
'FL': { ownerId: '333333', slackId: 'U03CCCC', rep: 'Carol' },
'TX': { ownerId: '333333', slackId: 'U03CCCC', rep: 'Carol' },
};
const enterpriseRep = { ownerId: '444444', slackId: 'U04DDDD', rep: 'Dave' };
const defaultRep = { ownerId: '555555', slackId: 'U05EEEE', rep: 'Eve' };
let assigned, reason;
if (employees >= 1000) {
assigned = enterpriseRep;
reason = `Enterprise (${employees} employees)`;
} else if (territories[state]) {
assigned = territories[state];
reason = `Territory: ${state}`;
} else {
assigned = defaultRep;
reason = 'Fallback — no territory match';
}
return { assigned, reason };If you're on Make's Free plan (which doesn't include the JavaScript Code module), use a Router with one route per territory. Each route has a filter checking the state value. It's more visual but harder to maintain as territories grow.
Step 5: Update contact owner in HubSpot
Add a HubSpot CRM -> Update a Contact module (on both routes):
- Contact ID:
{{1.id}} - Contact Owner: The owner ID from either the existing company owner (Route 1) or the territory code output (Route 2)
Step 6: Send a Slack DM
Add a Slack -> Create a Message module:
- Channel ID: The Slack user ID of the assigned rep
- Text:
🆕 *New Lead Routed to You*
*{{1.firstname}} {{1.lastname}}* at {{company.name}} ({{company.numberofemployees}} employees)
📍 {{state}}
Routing: {{reason}}Since the Router creates two branches, you need a Slack module on each branch (or merge them back with an Aggregator before a single Slack module). Most people just duplicate the Slack module on each branch.
Step 7: Schedule and activate
- Set the scenario schedule to Immediately
- Toggle the scenario to Active
Troubleshooting
Common questions
How many Make operations does each routed lead consume?
Each lead uses 5-6 operations: Watch Contacts (1) + HTTP association lookup (1) + Get Company (1) + Router (0, free) + Code module (1) + Update Contact (1) + Slack (1). On the Free plan (1,000 ops/month), that handles ~170 leads. Core plan (10,000 ops) handles ~1,700.
Can I use the Router without the Code module on the Free plan?
Yes, but it's tedious. Create one Router path per territory, each with a filter checking the state value. For 10+ territories, this becomes a sprawling canvas that's hard to maintain. The Code module (Core plan, $10.59/mo) consolidates all territory logic into one block. Worth the upgrade if you have more than 3-4 territories.
How fast does the Watch Contacts module poll for new contacts?
The minimum polling interval depends on your plan: Free plan runs every 15 minutes, Core and Pro plans can run as frequently as every minute. For real-time routing, use the Code approach with a HubSpot webhook.
What if I need to route leads from multiple sources (forms, imports, API)?
The Watch Contacts module catches all new contacts regardless of source. However, contacts from imports may arrive in batches that exceed Make's per-execution limits (the Watch module's Limit setting controls how many contacts to process per run). Set a reasonable limit (10-20) and ensure the scenario schedule runs frequently enough to clear the queue.
Cost
- Free plan: 1,000 credits/month. Each routed lead uses ~5-6 credits. Handles ~170 leads/month on free.
- Core plan: $10.59/mo for 10,000 credits. Handles ~1,700 leads/month.
Looking to scale your AI operations?
We build and optimize automation systems for mid-market businesses. Let's discuss the right approach for your team.