You finished eleven jobs last quarter. Which one made the most money?
Most contractors can’t answer that. They can tell you which job was biggest, which customer was nicest, and which one ran long. But gross profit per job — actual dollars left after labor and materials — is a guess. And the guess is usually wrong in a specific direction: the jobs that felt good were often the ones that bled.
Here’s what that costs. Say you run $280,000 a year through the business at what you believe is a 22% gross margin. If three or four jobs a year quietly come in at 5% instead of 22%, you’re down $15,000–$25,000 and you never see where it went. It shows up as “slow year” or “material prices.” It’s neither. It’s two bad bids and a change order you never billed.
Job costing fixes this. Not the enterprise version with cost codes and WIP schedules — the fifteen-minute-a-week version that fits in a spreadsheet and still tells you everything you need.
What job costing actually is
Job costing is comparing what you estimated a job would cost against what it actually cost, job by job.
That’s it. Two columns, a difference, and the discipline to look at it.
The reason it matters more than your P&L: your P&L tells you the business made or lost money. Job costing tells you which decisions made or lost the money. A P&L showing 18% gross margin across the year could be eleven jobs at a steady 18%, or it could be eight jobs at 28% and three disasters at negative 5%. Those are completely different businesses with completely different fixes.
The seven columns you need
Open a spreadsheet. One row per job. Seven columns:
| Column | What goes in it |
|---|---|
| Job name | “Miller — bath remodel” |
| Contract price | Total billed, including approved change orders |
| Est. labor hrs | What you bid |
| Actual labor hrs | What you logged |
| Materials + subs | Actual receipts and sub invoices |
| Labor cost | Actual hrs × your fully-loaded rate |
| Gross profit | Contract price − materials/subs − labor cost |
Add two calculated columns and you’re done: gross margin % (gross profit ÷ contract price) and hour variance (actual hrs − est. hrs).
Note what’s not here: overhead. Don’t allocate overhead at the job level in this spreadsheet. It adds arithmetic and arguments without changing which job you’d fire. Track gross profit per job, and let your annual overhead number live in your hourly rate math where it belongs.
Use fully-loaded labor cost, not wage
This is where most homemade job-costing spreadsheets go wrong. If you pay a guy $28/hour and you put $28 in the labor cost column, every job looks ~20% better than it is.
Fully-loaded means wage plus payroll taxes plus workers’ comp plus any benefits. A rough build for a $28/hr employee:
| Item | Cost |
|---|---|
| Wage | $28.00 |
| Payroll taxes (~10%) | $2.80 |
| Workers’ comp + payroll-tied liability (~9%) | $2.52 |
| Fully-loaded | $33.32/hr |
Your comp rate varies hard by trade and state — roofing can run several times what a handyman pays. Pull your actual rate off your policy declarations page instead of using mine.
Do the same for yourself. If you’re on the tools, your hours go in the labor column at a fully-loaded rate, same as anyone else. The business doesn’t get free labor because the owner is swinging the hammer. If you skip this, every job looks profitable and you’ll never understand why the bank account doesn’t grow.
Round to one number and use it all year. Something like $33/hr for your crew rate and $40/hr for yours. Precision to the penny changes nothing.
The 15-minute Friday routine
Block it. Same time every week. Here’s the sequence:
- Open the time log. Pull hours by job for the week. If you’re using scheduling software, it’s a report. If you’re on paper, it’s the back of the truck binder. Either works — what matters is that hours are tagged to a job, not to a day.
- Enter hours. Add this week’s hours to each open job’s running total. Thirty seconds per job.
- Enter receipts and sub invoices. Everything from the week, assigned to a job. This is the part that falls apart if you let it pile up — six weeks of Home Depot receipts in a shoebox is a two-hour job, not a five-minute one.
- Close out finished jobs. For any job that wrapped, confirm the contract price includes every approved change order, then let the sheet calculate gross profit and margin.
- Look at the variance column on closed jobs. Ask one question: why?
Step five is the whole point. The first four steps are data entry. Step five is the business lesson.
If you only do one thing, tag every receipt and every hour to a job name on the day it happens. Everything downstream is easy once that habit exists. Everything downstream is impossible without it.
Reading the variance: what the numbers are telling you
A job came in 14 hours over estimate. That’s not a verdict — it’s a question. There are only about five answers:
| Cause | What it looks like | The fix |
|---|---|---|
| Bad estimate | Pattern across similar jobs, all over by 15–25% | Raise your hour assumptions for that job type |
| Scope creep | Hours over, contract price unchanged | Write change orders, every time |
| Unknown conditions | One-off: rotten subfloor, aluminum wiring | Allowance lines and unforeseen-conditions clause |
| Crew productivity | Same job type, different guy, different hours | Training, or a different guy |
| Rework | Hours with no new work to show for them | Checklists, better photos, clearer specs |
Each has a different fix. You can’t pick the fix until you’ve seen three or four jobs of data, which is why the weekly rhythm matters more than the precision. Twelve rough rows beat three perfect ones.
The scope-creep row is the most common and the most expensive. Hours went up, price didn’t. That’s not a costing problem — that’s a paperwork problem, and it’s fully solvable with a signed form before the extra work starts.
A worked example
Three jobs from one quarter. Fully-loaded labor at $35/hr.
| Job | Price | Est. hrs | Actual hrs | Mat’l + subs | Labor cost | Gross profit | Margin |
|---|---|---|---|---|---|---|---|
| Miller bath | $14,800 | 120 | 148 | $5,200 | $5,180 | $4,420 | 30% |
| Chen deck | $8,900 | 70 | 94 | $3,900 | $3,290 | $1,710 | 19% |
| Alvarez kitchen | $31,000 | 240 | 311 | $14,800 | $10,885 | $5,315 | 17% |
The Alvarez kitchen was the biggest job of the quarter and it felt like the win. It produced $5,315 in gross profit on 311 hours — $17/hour of gross profit. The Miller bath produced $4,420 on 148 hours — $30/hour. Nearly double, on a job less than half the size.
That’s the number that changes behavior: gross profit per labor hour. Add it as a ninth column. It’s the fairest way to compare a $9,000 deck against a $31,000 kitchen, because it normalizes for the thing you actually have a fixed supply of — hours.
Now look at the variance. All three jobs ran over: 23%, 34%, 30%. That’s not three unlucky jobs. That’s a systematic estimating error of roughly 30%, and the fix is arithmetic: add 30% to your hour assumptions on the next bid, or raise your rate until the real hours pay. Either works. Doing nothing means you repeat it eleven more times this year.
Where to keep the sheet
Google Sheets. Free, syncs to your phone, and you can enter hours from the truck.
If you’re already running Jobber, Housecall Pro, or similar, check whether job costing is built in — most have some version of it, though the quality varies and the labor rate is often set to wage instead of fully-loaded. Go find that setting and fix it. If you’re piecing together tools, the $100/month tech stack article covers what pairs well with a spreadsheet.
Don’t buy software to solve this. A spreadsheet you actually update beats a platform you log into twice. Graduate to the software version when the spreadsheet becomes the bottleneck — usually around the point you have two crews running simultaneously.
What changes after one quarter
Twelve rows of data and you’ll be able to answer things you currently guess at:
- Which job type earns you the most per hour (usually not the biggest one)
- Which customer type runs over (usually the one who “just has a few questions”)
- How far off your estimates run, as a percentage you can bid against
- Whether your material markup is covering the sourcing and hauling
That last one matters more than it sounds. If materials routinely come in above your estimate, you’re either under-shopping or under-marking. Both are easy fixes once you can see them.
Your pricing math is a theory until job costing tests it. A rate card built on 1,200 billable hours and a 15% target margin is a hypothesis. The spreadsheet is the experiment.
Start here
Pick the last three jobs you completed. Not all of them — three. Build the seven columns, fill them in from receipts and whatever hour records you have, and calculate gross profit per labor hour for each.
It’ll take you 45 minutes because you’re reconstructing from memory. That’s fine, and it’s the last time it’ll take that long. From Friday forward, it’s fifteen minutes a week — and you’ll know, in actual dollars, which kind of work to go sell more of.