Work your sales territory from a map, not a CRM list

Plot every account and open deal on a map, spot the ones nobody has called in months, and build a drive time route in a few clicks.

App
MapboxHubSpotSalesOperationsLead EnrichmentResearch & Monitoring
PromptCreate

Build me a territory board my field sales reps open every morning instead of scrolling a list view in the CRM. The whole idea is that a rep should see their entire patch at a glance, spot the accounts worth driving to today, and plan the run without leaving the screen. It is built on HubSpot for the account and deal data and Mapbox for the map, the address lookups, the drive times and the route ordering. The audience is field reps and the managers who ride along with them.

Load the data like this. Pull companies with HubSpot Search Companies, requesting the address properties (address, city, state, zip, country) along with the owner property hubspot_owner_id and the activity recency properties notes_last_contacted and hs_last_sales_activity_timestamp, which are what the staleness filter is computed from. Pull open deals with Search Deals, requesting dealstage, amount, closedate and the associated company, so each company can be joined to its open deals. Pull the main contacts per account with Search Contacts so the detail panel and the visit brief know who to actually ask for. Resolve owner ids to human names with List Owners so the owner filter shows names rather than numeric ids.

Turn addresses into map pins with Mapbox Batch Geocode (v6), which takes up to 1000 queries in a single request, so batch the book rather than geocoding one company at a time. Cache the resulting coordinates in the app's own storage keyed by company id, and store a hash of the address alongside them so an account is only re-geocoded when its address actually changes. This cache is what makes reopening the board instant instead of re-geocoding thousands of accounts on every page load. Two things to be careful about: Mapbox coordinates are longitude,latitude order and not lat,lon, which is the single most common way this kind of app breaks; and persisting geocoding results long term is a Mapbox plan question, so use the permanent option on the geocoding call where the account is entitled to it. Companies with a missing or unresolvable address must never be silently dropped. Collect them into an unmapped accounts list with a visible count, so the board doubles as an address cleanup queue.

The main view is the map. Every company is a pin. Colour the pins by the stage of that company's largest open deal, with a distinct, visually quieter treatment for companies that have no open deal at all, and size the pins in bands by deal value so a big opportunity reads as a big dot. Include a legend for both encodings, because a map where colour and size mean something undocumented is just decoration. Cluster pins at low zoom so a dense city does not become an unreadable blob, and expand clusters as the rep zooms in. Clicking a pin opens a detail panel with the company name, address, owner, open deals with stage and value, the primary contacts, and the number of days since anyone last touched the account.

Above the map put a filter bar with four filters that apply to the map and to any list view together: owner, deal stage, deal value range, and a staleness switch for accounts not contacted in the last 60 days, computed from the HubSpot activity timestamps. Default the owner filter to whoever is signed in, so a rep lands on their own patch, while a manager can clear it to see the whole team. Make the staleness filter prominent, because surfacing neglected accounts is the main reason this board beats a list view.

The rep selects nearby accounts directly on the map, either by clicking pins or by dragging a selection over a cluster, and the selection shows as a running stop list beside the map. A Build route button then does three things. First it geocodes the rep's starting address. Then it calls Mapbox Get Distance Matrix with the start as the origin and the selected accounts as destinations to get real drive times rather than straight line distances. Then it calls Mapbox Get Optimization (V1) to work out the best visiting order. Render the result as an ordered stop list showing each account, its address, the drive time to that stop and a running total for the day, together with a route thumbnail rendered by Mapbox Get Static Map Image with the ordered stops drawn as numbered markers.

There is a hard limit here that has to be enforced in the interface, not just handled when the call fails. Mapbox Optimization (V1) accepts between 2 and 12 waypoints in total, and the starting address counts as one of them, which leaves a maximum of 11 selected accounts on a single route. Enforce that cap in the UI: show the count as the rep selects (for example "7 of 11 stops"), stop further selection once the cap is reached, and say plainly why rather than letting someone select thirty accounts and hit an error. If a rep wants more stops, they build a second route.

A Brief this route button kicks off a background agent over the accounts on the built route. For each account the agent gathers what the CRM knows, reading that company's open deals with Search Deals and its contacts with Search Contacts, then researches the company on the open web for anything recent and relevant such as news, expansion, hiring or leadership changes. It writes a one page visit brief covering who to ask for, what is open and at what stage, how long the account has been quiet, and two or three concrete talking points for the visit. Each brief lands in two places: filed back onto the HubSpot company record with Create Note, so it lives in the CRM where the rest of the account history is, and posted into the app so the rep can read the briefs stop by stop before driving. Show per account progress while the agent runs, so briefs appear one by one rather than the rep watching a blank screen.

One constraint on that agent worth knowing up front: HubSpot exposes an operation for creating notes but none for reading the body of existing notes, so do not build any step that tries to read past note content. The account history signal comes from the activity timestamp properties on the company, the open deals from Search Deals, and anything the app itself has stored.

Rules to hold throughout. Geocodes are cached and only refreshed when an address changes. Coordinates go to Mapbox as longitude,latitude. The route builder never sends more than 12 total waypoints to the optimizer. Get Distance Matrix is only ever called on the selected stops rather than the whole book, because it bills per origin and destination pair and an uncapped call gets expensive fast. Accounts that cannot be mapped are surfaced in the unmapped list rather than hidden. And the map is the primary surface: any list view is a secondary way to read the same filtered set, not the main way to work.

What does this prompt do?

  • Puts every company and open deal from your CRM on one map, with pins coloured by deal stage and sized by deal value, so the whole patch is readable at a glance instead of buried in a list view.
  • Filters the board by owner, stage, deal size and a not contacted in 60 days switch, so the accounts quietly going cold stand out instead of scrolling past.
  • Lets a rep select a cluster of nearby accounts and hit Build route, which works out drive times from wherever they are starting, puts the stops in the best visiting order, and shows the run as a map thumbnail.
  • Includes a Brief this route button that sends a background assistant off to research every account on the run, write a one page visit brief for each, file it on the company record, and post it back into the app to read before driving.

What do I need to use this?

  • A HubSpot account where companies have street addresses filled in and an owner assigned to each one
  • A Mapbox account for the map, the address lookups, the drive times and the route ordering
  • Deal stages and amounts kept reasonably current, since that is what the pin colours and pin sizes are drawn from

How can I customize it?

  • Change the staleness window from 60 days to whatever counts as neglected in your business, such as 30 days for active accounts or 90 for a long sales cycle
  • Switch what the pin colours mean, for example colour by owner or by lifecycle stage instead of by deal stage, and set the deal value bands that drive pin size
  • Set the default starting address per rep, and change what goes into the visit brief, such as adding recent news, competitor mentions or the last order date

FAQs

Why can I only put about a dozen stops on one route?
The route optimizer that works out the best visiting order accepts a maximum of twelve points on a single run, and your starting address counts as one of them. That leaves eleven accounts per route. In practice this matches how field days actually work, and you can build a second route for the afternoon.
Will this work on HubSpot Free?
Yes for the core of it. Companies, deals and notes are standard CRM records available on free plans. What really matters is your data hygiene: an account needs a street address to appear on the map, and an owner assigned so the board can filter by rep. Pin colours and sizes are only as good as the deal stages and amounts you keep updated.
What happens to accounts with a missing or messy address?
They cannot be placed on the map, so the board collects them in a separate unmapped list with a count, rather than silently dropping them. That list doubles as a data cleanup queue, and accounts start appearing on the map as soon as someone fixes the address in the CRM.
Does the map have to look up every address again each time I open it?
No. The board remembers each account's map location after the first lookup and only looks up addresses that are new or have changed, so reopening it is fast even with a few thousand accounts.
Can each rep see only their own accounts?
Yes. The owner filter can default to whoever is signed in, so a rep opens the board on their own patch, while a manager can clear the filter and look across the whole team.

Related templates

Turn Mailjet email clicks into ranked HubSpot follow-ups

Twice a day we spot the people clicking your pricing and demo pages, create a follow-up task for their owner, and post a ranked recap to Slack.

Mailjet
HubSpot
Slack Bot
Agentic Task
iMessage campaign console with pre-flight checks and delivery board

Build every text campaign in one screen: check who is actually reachable, see a realistic send plan, then watch delivery land row by row.

LoopMessage
Google Sheets
HubSpot
App
A searchable RFP answer library your bid team drafts from

Every proposal you have ever submitted in one searchable archive, with the closest past answers lined up against each question in a new RFP.

General Input Storage
General Input Database
Mistral AI
+2
App
See which target accounts just started advertising on LinkedIn

Open one board each Monday to see which of your target accounts are running LinkedIn ads right now, and which only switched them on this week.

LinkedIn Ad Library
HubSpot
General Input Database
App
Account health board that puts product usage next to your CRM

Your customer success team opens one board where every account's logins, seats and usage trend sit beside its owner, plan and renewal date.

Looker
HubSpot
Slack Bot
App
Look up a customer's full chat history mid conversation

Your agent types an email and sees every past conversation, rating and tag next to the CRM record, then files notes without ever leaving the chat.

LiveChat
HubSpot
App

Stop working your territory from a CRM list.

Give your field reps a map that shows the whole patch, flags the accounts going cold, and plans the drive before they leave.