Plan sales territories that stay fair and covered: check the account data first, score accounts by potential, balance potential against workload and travel per unit of rep capacity, write assignment and split rules for accounts that move, and run a quarterly rebalance check with named owners. Ships a territory checker that validates the account list, reports balance with deviation and variation math, and proposes cluster-whole assignments with the disruption cost shown. Use when designing or redrawing territories, splitting a territory for a new rep, rebalancing after a departure or a big win or loss, fixing attainment spreads that track the map, or writing territory assignment rules. For planning one named account use account_planning; for scoring leads use lead_scoring; for routing inbound leads use lead_routing.
./install.sh sales-territory-planningname: sales_territory_planning description: "Plan sales territories that stay fair and covered: check the account data first, score accounts by potential, balance potential against workload and travel per unit of rep capacity, write assignment and split rules for accounts that move, and run a quarterly rebalance check with named owners. Ships a territory checker that validates the account list, reports balance with deviation and variation math, and proposes cluster-whole assignments with the disruption cost shown. Use when designing or redrawing territories, splitting a territory for a new rep, rebalancing after a departure or a big win or loss, fixing attainment spreads that track the map, or writing territory assignment rules. For planning one named account use account_planning; for scoring leads use lead_scoring; for routing inbound leads use lead_routing."
A territory plan decides which rep owns which accounts, and whether each rep gets a fair shot at their number with a workload a person can actually carry. A good plan balances three things at once: potential, so each territory can produce its quota, workload, so no rep drowns while another idles, and travel or coverage cost, so the plan works in the real week and not just on the map.
Equal account counts and equal land area are the two shortcuts that fail. Accounts differ in value and in the hours they consume, and Salesforce's own territory teaching makes the same point in plain form: balance work assignments and give every rep an equal shot at quota, rather than drawing equal shapes. Territory planning defines where and what each rep owns. Quota planning defines how much each rep must produce, and quotas should be set from territory potential after the map is settled, not before.
This skill differs from a bare optimizer in one way that matters: it checks the data before it balances anything, and it counts the cost of moving accounts alongside the gain. A map that is balanced on paper, built on duplicate accounts and missing potential, and that moves half the book to gain two points of balance, is not a good plan.
Build the account list described in references/data-checks.md: one row per account with cluster, tier, potential, planned visits, visit hours, travel hours, owner, and customer or prospect status. Then run the checker:
bash
python3 ~/workspace/skills/sales-territory-planning/bin/territory_check.py --accounts accounts.csv
Fix duplicate accounts, missing values, and bad numbers to zero before going further. The checker exits with code 2 on those errors. List unassigned accounts and split clusters in the plan itself. Read references/data-checks.md for the full check order, including stale potential and house or named accounts held out of the pool.
Score each account using references/balance-math.md.
Potential: for a named account, a documented estimate based on size and expansion surface, with the basis recorded. For white space, number of possible accounts times buying power per account, using external counts where you can get them, such as Census establishment counts by industry and area, instead of last year's invoices alone.
Workload: planned visits per year times hours per visit, plus travel hours per year, account by account. This is the classic workload approach: classify accounts by tier, set a visit frequency per tier, and total the hours the coverage plan actually requires.
Write the tier frequencies and any extra load weights down in the plan. Weights you cannot explain, you cannot defend.
Run the checker on current owners and read all of it: per territory, account count, A tier count, potential and its deviation from the mean, workload and its deviation, travel hours, plus the coefficient of variation for the plan as a whole.
Name the pattern in words. High attainment where potential is high and low attainment where potential is low points at the map first. An overloaded territory with neglected small accounts points at workload. A rural territory with high travel and low potential needs a different fix, and possibly a different measure, from a dense territory with too many A accounts.
Group by cluster, the set of accounts a rep would travel or work together, and assign clusters rather than single accounts where you can. Splitting a cluster puts two reps on the same route.
bash
python3 ~/workspace/skills/sales-territory-planning/bin/territory_check.py --accounts accounts.csv --assign --reps "Ana,Ben,Cid" --out assignments.csv
python3 ~/workspace/skills/sales-territory-planning/bin/territory_check.py --accounts accounts.csv --assign --reps "Ana,Ben,Cid" --capacity "Cid=0.5" --out assignments.csv
The assign mode searches placements of whole clusters, scores each on potential deviation, workload deviation, and disruption, and reports the disruption cost: how many accounts and how much potential change hands. Capacity adjusts for ramping or partly loaded reps, so a new rep is not handed a full share on day one and then judged on it.
Compare the proposal against the current balance on all three axes. If clusters are too coarse to land inside your band, say so and name the cluster you would split and why, instead of scattering single accounts to fake a clean result. The full worked run, with real checker output on a 24 account list, is in references/worked-example.md.
Assignment is not only arithmetic. Match industry knowledge, language, existing relationships outside the moving set, and whether a rep works dense routes or wide rural coverage better. Where a rep's strength changes the assignment, write that reason in the plan next to the numbers.
Then set or adjust quotas from the new territory potential. A balanced map with quotas copied from the old map recreates the old unfairness in a new shape.
Use references/assignment-rules.md. One page covering: one owner per account, new lead routing by territory with named accounts overriding geography, round robin only inside a territory, house and named accounts listed with a review date, how relocations and new units of current customers are handled, and who covers a vacant territory.
For accounts that move, publish the stage based split rule for in flight deals, the renewal protection, the cutover date, and the handover steps: notify both reps, joint account review, outgoing rep introduces the incoming rep, written transfer of commitments and open problems, CRM update on the effective date, and a fixed support window after the move.
Communicate in writing before the effective date: why, with the balance numbers, what changes, when, and how in flight deals are handled.
Follow references/rebalance-review.md. Quarterly: rerun the data checks and balance report, review the trigger list, move little, and record everything. Annually: rescore potential, revisit tier frequencies and capacity, and redraw only when the checks keep flagging the same problem or the strategy changed.
Name five owners in every review record: review owner, approver, CRM owner, comp owner, and the manager of each affected rep. Triggers for an out of cycle check include a rep joining or leaving, a territory outside the deviation band twice in a row, unassigned accounts appearing, a large account won, lost, or moved, and routing overrides climbing.
A territory plan containing:
publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e
No ratings yet — be the first to rate it.