A Lead CRM and Call Ranker for a Wholesale Supplier
The sales team was spending hours on the phone. The fix was deciding who to call first.
Result: closing rate per call rose about 50% once the sales team started prioritizing calls with the ranker.
The problem
A wholesale meat supplier sells to restaurants and other food businesses, and its sales team spent many hours phoning leads. The ask was vague: make the calling more efficient. Before building anything, I asked clarifying questions, then costed several options against the current process, including labor hours and API cost per hour.
The CRM
I built the team an internal lead CRM: a private, bilingual (Spanish and English) web app.
- Leads from open data. It imports the city's open gastronomy dataset with its source attached to every record, so the team always knows where a lead came from. A rerun of the import changes nothing that's already loaded.
- Map and table in sync. A Google Maps view searches leads by radius and stays in sync with a spreadsheet-style table.
- Calls as records. Each lead keeps its call attempts, outcomes, notes, contacts, and follow-up dates. Calling sessions are resumable, so a rep can stop mid-list and pick up in the same place.
- Sales metrics. Contact, interest, quote, and customer-conversion rates, plus follow-ups due.
It runs on Next.js and TypeScript with a FastAPI back end, SQLite with a PostGIS option, and Alembic migrations. Docker Compose puts it behind Caddy with backups and rollback, and Python, frontend, and Playwright end-to-end tests run in GitHub Actions.
The ranker
On top of the CRM, I trained a random-forest classifier that sorts strong leads from weak ones, so reps spend their calls where they count. I deployed it on Google Cloud's Vertex AI so it could plug into the CRM and scale with it. The model was lean enough that cost per lead rose only about 10%.