In January 2025 I started tracking every job. Materials cost. Hours billed. Hours actually worked. Drive time. Materials runs. Callbacks. Everything.
I expected to find some surprises. I did not expect to find that almost half the job types I was doing were either barely breakeven or actively losing money.
Twelve months and 187 jobs later, here is what the data said.
The job that triggered the spreadsheet
It was a kitchen rewire in Newtown. A repeat customer who had used me twice before. Job total: $3,790. Materials I quoted: $720. Labor I billed: 16 hours at the rate I was running.
It felt like a great job. Customer was thrilled. Got paid in full inside a week. Drove home that Friday feeling like I had a good week.
Then I sat down on Sunday and actually did the math, because something was nagging at me.
Real hours, including drive time and three materials runs: 22, not 16. Actual materials, with the two replacement items I had to swap: $890, not $720. Callback the next week for a flickering switch: another 90 minutes round trip, parts and time.
By the time I allocated overhead at $32 per billed hour, the job had cleared $410 in actual profit. On a $3,790 job. That is a 10.8 percent net margin on something I had been telling myself was a winner.
That weekend I built the spreadsheet.
What I tracked, and why
The spreadsheet was simple. Every job got a row. Every row got these columns:
- Job number and date
- Customer name and zip code (for drive time bucketing)
- Job type (panel swap, service call, troubleshoot, rewire, etc.)
- Total billed
- Materials cost (actual, not estimated)
- Billed labor hours
- Actual labor hours (including drive, materials runs, callbacks)
- Overhead allocation (hours actual times my overhead per hour)
- Net profit dollars
- Net profit per actual hour
That last column was the one that mattered most. Profit dollars hide a lot of sins. Profit per actual hour shows you, brutally, which jobs are actually paying you what your time is worth.
The most profitable job type
Surprise winner: service calls.
I had always thought of service calls as the small change of the business, jobs you do to fill gaps between bigger work. Turns out service calls were paying me the most per actual hour of any category, by a wide margin.
Average service call: $385 billed, 1.5 actual hours including travel, $190 net profit, $127 per actual hour.
Why they win: small material cost, almost no project management overhead, no waiting on permits or other trades, fast in and out. The drive time hurts on individual jobs but bunching them in geographic clusters (the data showed me which zip codes paid for themselves) made the math better than I expected.
The least profitable job type
Surprise loser: small renovation work for general contractors.
I had three GCs feeding me steady electrical work on remodels. It felt like good business. Steady volume. Less marketing burden. I liked the GCs personally.
The data was bleak. Net profit per actual hour for those jobs averaged $48. My target was $115. I was working for less than half my real rate on close to 30 percent of my volume.
The reasons came out when I dug in: I was on the GC's schedule, not mine, which meant a lot of wasted trips when the job was not ready. Their materials lists were always incomplete, which meant 2 to 3 supply house runs per job that I was eating. Their customers were not my customers, so no referrals or repeat work came out of it. And the GCs had negotiated me down on rate at the start, so I was billing 15 to 20 percent below my normal pricing.
The hidden cost that destroyed three categories
Drive time. The killer.
I had been pricing as if a one-hour job was a one-hour job. The data showed me that a one-hour job 35 minutes away is actually a 2 hour 10 minute job once you count round-trip drive time. If I am billing $240 for the hour of work and burning 70 minutes of unpaid travel, my actual hourly rate on that job is closer to $111.
Three categories got hammered by this:
- Small jobs outside my home zip code cluster. Below about $300 in billed labor, drive time ate the entire profit.
- Estimates that did not close. Every unconverted estimate was 60 to 90 minutes of unpaid time. I had been ignoring this. The data showed I needed a close rate above 65 percent or my estimate process was a net loss.
- Multi-visit jobs. Anything requiring three or more visits had its actual labor hours quietly double from what I had quoted, because every visit included drive time and a materials check.
What I changed because of the data
Six concrete changes, all driven by what the spreadsheet showed me:
1. Minimum job size for jobs outside my home zip code cluster: $400 billed labor. Below that, I quote a minimum trip charge or decline the work.
2. Trip charge for first-time customers more than 20 minutes away: $95, applied to the bill if work proceeds. Killed the freebie windshield-time estimates.
3. Service call cluster days: Tuesdays and Thursdays are now booked tight in geographic clusters. Other days are reserved for larger projects. Average drive time per service call dropped 40 percent.
4. GC pricing reset: I went to two of the three GCs and raised my rate 18 percent. One agreed. One pushed back and I stopped working for them. My total revenue dropped 8 percent and my profit went up.
5. Materials markup audit: I had been marking materials at 25 percent. I moved to 40 percent on standard items and 60 percent on specialty items. Customers noticed exactly zero of those bills.
6. Callback tracking: Every callback got its own row. Within three months I saw a pattern, one specific brand of switch was responsible for 60 percent of my warranty returns. I stopped installing them.
The two customers I stopped working for
The hardest call was firing one of the GCs. He was a friend. He sent me consistent work. But the data was unambiguous: I was working for him at $44 per actual hour. He was the lowest-paying customer in my database.
I sent him a one-paragraph email. Said I was raising my rate effective in 60 days. Gave him the new number. He pushed back. I held firm. We stopped working together. He told two other GCs in the area about it.
Three months later I had replaced his volume with direct residential work paying twice the rate. I would not have made that call without 12 months of data sitting in front of me.
The other one was a residential customer who had become a project. Multiple small jobs over 18 months, always demanding immediate response, always negotiating on price after the work was done, four callbacks for stuff that was not warranty. The spreadsheet said she was costing me money. I stopped returning her calls.
What I would tell a new contractor
You cannot price intelligently without knowing what your jobs actually cost.
You cannot fire bad customers if you do not know who they are.
You cannot tell your spouse why you are working 60-hour weeks and still tight on cash without a spreadsheet that shows where the money is leaking.
The whole exercise takes 10 minutes a day. Open the spreadsheet at the end of each work day, fill in the row for whatever jobs you touched. Once a month, look at the totals by category. Once a quarter, decide what to change.
Twelve months of that data turned a business I thought was healthy into a business that actually was.