Pick a town. Get back every business in it, each one scored on how strong it is, how weak its web presence is, and how close it sits to your door, so the best leads float to the top of a single ranked list. Here's how I built it, using my own backyard on the South Shore as the guinea pig.
OpenStreetMap · Google Places · BigQuery · OSRM · Python · Cloudflare
Prospecting · Targeting · Where to start
Truth be told, anybody who sells to local businesses runs into the same wall. You've got hundreds of shops, restaurants, contractors, and offices within a short drive, and no good way to tell which ones are actually worth a conversation. So outreach ends up driven by whoever you happened to notice last week, or an alphabetical list you lose patience with somewhere around the letter C.
The useful signal is buried in there, but it's real. A business with great reviews and a steady stream of customers, that still has no website and barely shows up on social, is a wildly different prospect from a slick operation with a full marketing team already humming. The first one has proven demand and a visible gap you can help with. The second one is doing just fine without you. The whole trick is measuring that difference across every business at once, instead of one gut feeling at a time.
So I built GeoOutbound to do exactly that, and pointed it at the five towns around Scituate for the first run, because I figured I'd start with the backyard I actually know. What comes out the other side is a single dashboard where the highest-opportunity businesses sort straight to the top, each one with a phone number already attached.
Outreach driven by memory and chance. No way to compare one prospect to another. The businesses that most need help are invisible inside a flat list of names.
Every business in range scored 0 to 100 on a consistent opportunity model, ranked, filterable by town and web status, with contact details on every row.
Discovery · Enrichment · Data Quality
Discovery starts with OpenStreetMap, which catalogs businesses by location for free, which is exactly the price I like to start at. For each town the pipeline pulls every named shop, office, and service, then works out two distances from the seed address: a straight-line distance and a real driving time routed through OSRM. Proximity feeds the score, so I wanted a measured drive time, not a rough "eh, that's about ten minutes" guess.
Now, OpenStreetMap has a blind spot worth being honest about. It misses a fair number of small businesses, and its town-name matching is loose enough that a "Hingham" in Montana and a "Marshfield" in Missouri both tried to sneak into my South Shore dataset. A hard geographic boundary check tosses those out, and then Google Places fills the coverage gaps and confirms which businesses are actually open for business.
That Google layer is where the dataset really earns its trust. Each business gets matched to its Google Maps listing, which hands back a star rating and a review count. A bakery sitting at 4.9 stars with 152 reviews isn't a guess about demand, it's a measurement of it, and that rating becomes the backbone of the whole opportunity score. It's what separates a thriving business with a presence gap (a great lead) from a quiet one that simply has no customers to lose (not your problem to solve).
No single source covers every local business cleanly. Free data is incomplete and noisy; paid data is expensive to use blindly.
A free-first pipeline that discovers broadly, filters out geographic noise, and spends on Google only where it adds the rating signal the score depends on.
OpenStreetMap Overpass · OSRM routing · Google Places API · bounding-box validation · Python httpx
Opportunity Model · Web Presence · Ranking
For every business, the pipeline checks whether a website even exists, and if it does, it scores the quality out of ten on plain, explainable stuff: does it load, is it secure, is it mobile-ready, does it carry real contact details, is it more than a parked placeholder somebody forgot about. Then it goes looking for the business across Facebook, Instagram, Bluesky, and X, and grabs whatever contact details are public along the way, phone, email, address, the works.
All of that rolls up into one opportunity score from 0 to 100. It rewards proven demand, pulled from the Google rating and review count. It rewards a presence gap, so a business with no site scores higher than one that already has a polished one. And it rewards proximity, decaying as the drive time grows, because a great lead an hour away is a worse lead than a good one down the street. Every score keeps its component breakdown attached, so I can always explain a ranking instead of asking anyone to take it on faith.
The output is a private, password-protected dashboard. Sort by score and the best targets are already sitting on top. Filter to a single town, or just to businesses with no website at all, and the list reshapes itself instantly. Every row carries a phone number, so the distance between deciding who to call and actually calling them is exactly one click.
Web presence judged one business at a time, by eye, with no way to weigh it against demand or distance.
A single transparent score blending demand, web gap, social gap, and proximity, with the math shown for every business on the list.
BigQuery SQL scoring · website quality heuristics · social + listings detection · Cloudflare Pages (gated dashboard)
Architecture · Reusability · What this becomes
The geography lives in a config setting instead of being buried somewhere in the code. Change the seed address and the town list, re-run the pipeline, and the same discovery, enrichment, and scoring all run against a brand new market. The South Shore was just the proving ground. The machine itself goes wherever you point it.
Every stage writes to Google BigQuery, so the whole dataset stays queryable, auditable, and cheap to keep around. The data model already has room to grow: the same pool of scored businesses can be re-ranked against different criteria as the questions change, without me rebuilding the foundation every time. It started life as a prospecting tool, but truth be told, what I actually built is a local market intelligence engine that just happens to point at lead generation first.
Python · Google BigQuery · OpenStreetMap · OSRM · Google Places · Cloudflare Pages + Functions
The gap between a list of names and a ranked list of the right names is where most outreach quietly stalls out. I'm happy to build this engine pointed at your market, your criteria, and your front door. Let's have a chat.