One brand, many sites: every inquiry routed to the right location and owner, with roll-up reporting managers cannot peek past.
Bring your stack to a call and we will scope it against how your business actually runs.
Book a callA single-location business that grows to four does not get four times the problems. It gets a different problem. Inquiries arrive at one brand and have to reach one of several places, and nothing in the original setup knows how to decide which. So the business improvises. A general inquiry inbox that someone at head office forwards. A single phone number that rings a receptionist who asks "which branch?" and transfers. One shared calendar that nobody trusts. Four separate logins because each location bought its own tools. Leads land in the wrong place, get worked twice, or get worked by nobody because each location assumed another had it.
The money leaks in ways that are hard to see from the center. Misrouted leads are the obvious one: an inquiry sent to the wrong branch is usually dead by the time it arrives at the right one, and nobody logs it as a loss because nobody logs it at all. Double-contacted leads are worse, because the prospect notices and draws the obvious conclusion about how organized the business is. Then there is the unowned lead: in a shared pipeline, an opportunity with no named owner is everyone's and therefore nobody's, and it sits in the first stage until someone archives it. And there is the capacity problem running underneath. One location is turning work away while another has empty slots, and the routing has no idea because it was built on ZIP codes rather than on availability.
The reporting failure is the one that compounds. Head office wants one view: leads, bookings, revenue, speed to lead, close rate, per location, comparable. What it usually gets is four spreadsheets with different definitions, assembled late, by hand, by someone who then has to defend the numbers in a meeting. Meanwhile each location manager wants the opposite. Their own data, their own team, their own pipeline, and no visibility into their neighbor's performance or their neighbor's customers, which is both a trust matter and often a data protection one. Those two requirements sound contradictory and are not. One data model with a location field on every record, a permission layer that filters by it, and reporting that aggregates above the filter satisfies both. This build is that model.
Everything in this build depends on one decision: a single location field, mandatory, on every contact, opportunity, appointment, form submission, task and conversation. Nothing enters the system without it. Get this right first and the rest is configuration; get it wrong and no amount of workflow fixes it.
location: dropdown, the authoritative field. Values are short codes, not display names, so a rebrand does not break every filter: loc-north, loc-south, loc-east, loc-central.location_assigned_by: dropdown: Form selection / ZIP code match / IP geolocation / Phone line / Round-robin overflow / Manual reassignment / Default fallback. This field is how you audit the routing later.location_confidence: dropdown: Explicit / Inferred / Fallback. Only Explicit should ever skip the confirmation step.location_previous: text, written on every reassignment, so transfers are traceable.service_requested: dropdown; some services exist at only some sites, and this field drives the service-aware routing branch.ZIP code: text, required on every form that routes geographically.owner_user: user reference, the named human accountable.speed_to_first_contact_mins: number, written by workflow on the first outbound touch.routing_override_reason: text, required whenever a human moves a record between locations.capacity_flag: dropdown on the location record: Open / Tight / At capacity / Closed. Set by the manager or by a rule reading calendar availability.One pipeline definition, identical stages, replicated per location rather than shared. Identical stages are what make the roll-up possible; separate pipelines are what make the permissions clean.
Pipeline per location: "[Location] Sales"
lost_reasonCentral pipeline: "Routing Exceptions", visible only to head office: Unresolved Location, Out of Area, Multi-Location Inquiry, Capacity Overflow, Duplicate Across Locations, Resolved.
service_requested plus location and only offers legitimate combinations, which prevents the single most common multi-site booking error.Five mechanisms, evaluated in strict order of confidence:
capacity_flag is Open, and always with location_confidence = Fallback so the first message asks rather than assumes.service_requested, location picker with "not sure" as an explicit option, consent checkbox. "Not sure" plus ZIP code routes geographically; "not sure" with an unmatched ZIP code goes to Routing Exceptions.routing_override_reason and the receiving location; triggers the handoff workflow rather than letting someone silently edit the field.location and location_assigned_by = Phone line before the transfer, so a dropped call is still a captured lead.location_confidence is not Explicit; answer location-specific logistics; book into that location's calendar only; chase unanswered inquiries.One location tag per site (loc-north and so on, mirroring the field for reporting convenience), plus routing-explicit, routing-inferred, routing-fallback, transferred, multi-location-inquiry, out-of-area, capacity-overflow, duplicate-cross-location, sla-breach.
This is the part that makes the build viable politically as well as technically. Four roles:
location equals their assigned location. No access to other locations' records, no cross-location search, no exports. Their pipeline view shows one pipeline. Their calendar view shows one calendar group.capacity_flag, and the ability to raise a Transfer Request. Explicitly not: other locations' dashboards, the roll-up report, or any cross-location benchmark unless the brand chooses to publish a league table deliberately.Implementation notes that matter: the permission filter must apply to search, to exports, to saved reports and to notification routing, not only to the pipeline view, which is the one place people remember to check. Test it by logging in as a location user and trying to find a contact you know exists at another site. Shared assets (email templates, snippets, the brand's social accounts) stay centrally owned and read-only to locations, or four teams will quietly fork the brand. And every workflow notification must be addressed to owner_user or the location's channel; a single central notification channel destroys the whole model on day one.
lost_reason breakdown, and an SLA breach list.location_assigned_by, distribution of location_confidence, reassignment rate, and the top ten ZIP codes producing exceptions, which is your maintenance list for the lookup table.loc-south as primary, loc-central as secondary.capacity_flag is Open. So location = loc-south, location_assigned_by = ZIP code match, location_confidence = Inferred. Tag routing-inferred applied.owner_user set. The holding record closes.speed_to_first_contact_mins = 1.location_previous = loc-south, location = loc-central, location_assigned_by = Manual reassignment, routing_override_reason = "Customer requested at first contact". The south opportunity moves to Transferred Out; a new opportunity opens in Central Sales at Routed: Awaiting Contact with the full conversation history and the original source and campaign intact. A new owner_user is assigned from central's on-shift staff. Both location channels are notified; the south owner's task is closed automatically so nobody works a lead they no longer own.sla-breach, reassign to the next available north staff member, and notify the north manager, not head office, and not the other locations.location_confidence = Fallback, routes it to the Routing Exceptions pipeline at Out of Area, and head office handles it, either adding the prefix to the table or sending a polite out-of-area reply with the nearest alternative.Trigger: any inbound lead event. Form submission, inbound SMS, inbound call completed, chat conversation started, or manual contact creation without a location.
Actions, in strict order: each step exits the workflow on a match:
location, location_assigned_by = Form selection, location_confidence = Explicit, tag routing-explicit. Go to step 6.location from the channel mapping, location_assigned_by = Phone line, location_confidence = Explicit, tag routing-explicit. Go to step 6.ZIP code up in the prefix table. On a single match: set location, location_assigned_by = ZIP code match, location_confidence = Inferred, tag routing-inferred. On an overlap: take the primary. On no match: go to step 5.location_assigned_by = Form selection, location_confidence = Inferred.service_requested is not offered at the matched location: branch. If exactly one other location offers it, reassign there, set location_assigned_by = Manual reassignment, routing_override_reason = "Service not available at matched location", and tell the customer in the first message. If several do, route to Routing Exceptions at Multi-Location Inquiry.capacity_flag. Open or Tight: proceed. At capacity or Closed: if a secondary location from the ZIP code table is Open, reassign, tag capacity-overflow, set location_assigned_by = Round-robin overflow, and say so in the first message. If no secondary is open, proceed to the original location anyway and notify its manager, overflowing a lead to a site the customer cannot reach is worse than a wait.duplicate-cross-location, and notify both locations' managers plus head office. A prospect contacted by two branches of the same brand is the single most damaging routing failure, so this check runs before owner assignment, not after.owner_user by round-robin among staff at that location who are on shift per the staffing calendar and below their open-lead cap. If nobody qualifies, assign the location manager. Apply the location tag. Close the holding record.owner_user due in 10 minutes. Never notify a central channel.Stop conditions: contact already has an open opportunity at the correctly matched location (append the conversation, do not duplicate); contact tagged do-not-contact; the submission is a known internal test record.
Trigger: opportunity enters Routed: Awaiting Contact.
location_confidence:speed_to_first_contact_mins on send. All messages originate from the assigned location's number and sender name.lost_reason = No response.location inline. Fire Workflow 4.Stop conditions: appointment booked; stage advances; customer replies (pause and notify owner_user); transfer initiated; opt-out.
Trigger: opportunity has been in Routed: Awaiting Contact for 15 minutes with no logged human touch (call, manual message or note) during that location's opening hours. Outside opening hours the timer starts at open.
sla-breach. Notify owner_user directly: "{{contact_first_name}} has been waiting 15 minutes. Their inquiry: {{service_requested}}."owner_user to the next on-shift staff member at the same location, log the previous owner, and notify the location manager. The manager, not head office.Stop conditions: any human touch logged; stage advances; appointment booked; contact asks for a specific later callback time (set a snooze and clear the flag).
Trigger: Transfer Request form submitted by staff, or a customer reply naming a different location, or head office resolving a Routing Exception.
routing_override_reason. A transfer with no reason is refused. The field is what makes the routing auditable, and without it the weekly routing accuracy figure is fiction.location_previous = current location; set location to the receiving site; set location_assigned_by = Manual reassignment; apply transferred.owner_user at the receiving location by the same on-shift round-robin.Stop conditions: receiving location rejects the transfer (routes to Routing Exceptions for head office to arbitrate); customer declines the move.
Trigger: record enters any Routing Exceptions stage.
location_confidence = Explicit and close the exception. Wait 1 day with no answer → head office call task. Wait 3 days → Lost, lost_reason = No response.Stop conditions: routed successfully; customer out of area and declining; duplicate resolved.
Trigger: schedule, hourly, during opening hours, per location.
capacity_flag: above 40 percent free → Open; 15 to 40 percent → Tight; under 15 percent → At capacity. A manager can override manually, and a manual override holds for 24 hours before the rule resumes. Otherwise the automation and the manager fight each other all day.Trigger: appointment booked on any location calendar.
location. On mismatch, halt, alert both managers, and do not send a confirmation until a human resolves it.Trigger: schedule, Monday 7am in each location's own time zone.
location equals that site: leads by source; median and 90th-percentile speed_to_first_contact_mins; contact rate; booking rate; show rate; quote rate; win rate; pipeline value by stage; lost_reason counts; SLA breaches with owner and hour; transfers in and out.Trigger: schedule, Monday 7.30am, head office only.
location_assigned_by; distribution of location_confidence; reassignment rate as a share of all leads; mean time from creation to final location.Trigger: manual, run by head office when a site opens.
location dropdown and to the ZIP code table, reassigning prefixes from neighbouring sites deliberately rather than by overlap.This workflow is what makes the build scale. Without it, location five is three weeks of manual configuration and two weeks of routing bugs.
location field, applied at the user level, and verify it against all six surfaces: pipeline views, calendar views, contact search, exports and saved reports, notification routing, and conversation inboxes. Most builds secure the first two and leak through the other four.loc-unknown value rather than a guess.The territory table, the permission model and the roll-up definitions are worked out on a call, against your actual sites and corporate structure. Book one and bring your location list.
Every build on this page is something we configure, test and hand over with the SOPs your team needs to run it.
Book a call