Whofits Agency
WhoFits Agency is OCTYN's own lead engine for blue-collar trades. It reads state licence registries, filters out the rows not worth enriching before any network call, then fans out across six search engines to find a website, an email and a phone number. Scoring is a transparent 0 to 100. 3,000 plus qualified leads at the 2026-07-05 reading.
Whofits Agency in use

Internal lead-gen pipeline sourcing qualified leads for HVAC, plumbing, electrical, roofing at pace.
This is OCTYN's own lead engine, built for our own outbound and then generalised so other verticals run on it. We operate it.
1. The situation
Blue-collar contractors are hard to reach for a boring reason: they exist in public records and nowhere else useful. A licence board knows who holds an HVAC licence in Florida. It does not know their email, their website, or whether the business is one person with a van. The premise was that the registry is the right starting point because it is public and unglamorous, and the value is entirely in what gets added after it.
2. Why it was hard
Roughly 46 percent of these businesses have no findable online presence, so nearly half the list can never be enriched however good the tooling is. The registries are mixed quality too: Florida returns person names in the business-name column and Texas returns counties rather than cities, so searching the raw row returns noise. And the searching is fragile, because free datacentre proxies die after two to five searches and the major engines block quickly.
3. What was built
Ingestion reads state registries directly: a bulk CSV from the Florida board, a Socrata API from the Texas one, about 59,500 raw records across the two.
Pre-filters run before any network call, because enrichment is the expensive step and most rows do not deserve it. Master-electrician licences are employees rather than owners, a comma in the business name means a person, a two-word alphabetic name is a person. These drop the working set to eight or ten thousand.
Enrichment then fans out across six search engines at once, some through proxies and some direct at a slow steady rate. That is not redundancy for its own sake, it is the answer to proxies that die in single-digit requests. Counties are mapped to cities first, because the query decides the result quality.
Extraction pulls email, phone and social links from the page, then puts every email through five checks: a junk list, a web-developer filter, a domain match against the business name, a format check, and an exception for personal Gmail addresses, because contractors genuinely use them. Scoring is a transparent 0 to 100, qualifying at 40. The dashboard is Next.js on Coolify over Supabase, multi-tenant, with the tenant resolved from the session rather than from the request.
4. What it does under load
About 59,500 raw records from two states, filtered to eight to ten thousand enrichable, at the 2026-04-15 reading. Of enriched leads, about 54 percent yield a website and about 40 percent qualify. Throughput is roughly 50 leads per five minutes, putting 2,000 qualified leads at about eight hours. The exported qualified-lead file holds 3,207 rows as of 2026-06-24, against the 3,000-plus figure recorded on 2026-07-05.
5. What happens when it breaks
Four rules carry most of the failure handling, and each exists because the obvious alternative failed. Never scrape from an address you depend on, because a blocked residential IP is a personal outage and a blocked server IP is a client outage. Never validate a proxy pool, because validation costs the same request the search costs, so a validated pool is already half dead. Never trust what a model returns unless the text is literally present in the fetched page, which is what stops an invented email address reaching a send queue. And run bulk work on a workstation, because search engines wall a datacentre address doing volume.
Failure is partial by design. An engine that blocks takes its share of the queue and the others keep going, and a lead that cannot be enriched is marked and left rather than retried forever. The dashboard is the rollback surface: status changes are per lead and reversible, so a bad batch is visible as rows rather than a silent overwrite.
6. Who maintains it, and what that costs in attention
The dashboard costs close to nothing. Deployment is a push to the branch, and the platform builds and restarts it.
The sourcing pipeline is the attention. It is not a service that runs unattended forever and we do not describe it as one. It is a batch job someone starts, watches for the first minute, and checks the yield on afterwards. A registry changes its export format once or twice a year and that state's parser needs a look. Proxies degrade continuously, which is expected and absorbed by the fan-out rather than fixed.
The check that matters is the yield rate. If the share of enriched leads finding a website drops well below the usual figure, an engine is silently returning nothing. Reading that number is the standing cost.
7. What changes when requirements change in six months
Configuration, no code. Trades, city tiers, scoring weights, the qualification threshold and the per-tenant ICP are all data. Adding a vertical is supposed to be a JSON file rather than a commit, and when it is not, the thing that had to change belongs in the ICP. Three tenant configs already run on the engine.
A code change, small and predictable. A new state. Each licence board is its own scraper against its own site, sharing one base class and one trade classifier, so a new state is a known day of work rather than an open question.
A code change, larger. A new country. Licence registries are a United States structure, and the United Kingdom or Australia has trade bodies and accreditation schemes instead, which changes what the first stage even is.
A rebuild, only if the input changes character. Everything downstream of discovery is generic over a company name and a location, so moving from registries to permit filings reuses enrichment, scoring and the dashboard whole and replaces only the front.
8. What we would do differently
Measure yield per engine from the first run, because for a while nobody was counting which engines pulled their weight.
Treat the dashboard's totals as a real feature. Its summary counts were computed over the current page rather than the whole database, which is a small bug with a large consequence: the number a person reads is the number they will quote.
Build the tenant boundary before the second tenant. The gap where a page was blocked but the API behind it was not is the kind of thing only found by going looking.
More platforms
what teams run their business on1- WhoFitsCreator-discovery engine and creator-marketing service.
Want something like Whofits Agency for your operation?
Book a call →