Average margin hides the spread, and the spread is where the fix lives. Crew-level job costing takes one number per job, labor hours per square, and turns it into a weekly management tool instead of a quarterly surprise.
Why Company-Wide Margin Misleads
A roofing square is 100 square feet of roof. Bids are built on it, so labor should be measured on it. If your estimate assumes 3.5 crew hours per square on a tear-off and re-roof and one crew consistently runs 4.4, no one sees the gap until the job closes, and by then the next three jobs have the same problem. The variance is rarely material cost. Shingles cost the same for every crew. The difference is hours: tear-off pace, rework, waiting on deliveries, and drive time between jobs.
Worked Example: Two Crews, One $10,260 Gap
Illustrative numbers. Two crews each complete ten 30-square residential tear-offs in a quarter, 300 squares each. The estimate assumes $140 of burdened labor per square. Burdened means wages plus payroll taxes, workers' comp, and insurance, at an illustrative $38 per labor hour.
| Crew A | Crew B | |
|---|---|---|
| Labor hours logged | 1,050 | 1,320 |
| Hours per square | 3.5 | 4.4 |
| Burdened labor per square | $133.00 | $167.20 |
| Total labor cost | $39,900 | $50,160 |
| Versus $140/sq estimate | $2,100 under | $8,160 over |
The two crews differ by $10,260 on identical scope and identical materials. Blend them and you see $6,060 of net overrun on 600 squares, or $10.10 per square. That looks like a pricing problem. Fixing it by raising bids penalizes the work Crew A does well.
What to Track
Three fields per job, entered weekly rather than at close-out:
- Squares installed (actual, not estimated).
- Labor hours by crew, from timesheets.
- Burdened labor cost, from payroll allocated to the job.
Divide hours by squares. That is the number to compare to the estimate and to other crews. Track tear-off and install separately if you can, since layered tear-offs and steep pitch distort a single blended figure.
Setting It Up in QuickBooks Online
Use Projects for the job and a Class for the crew, so every payroll and subcontractor cost carries both tags. Then run the Profit and Loss by Class report for a date range, and pull hours from your time tracking export. Cost tagged to the wrong crew is the main failure. Assign the class at time entry, not at payroll close, and review untagged labor weekly. This is the same discipline described in our job costing setup guide.
Reading the Gap Correctly
A high hours-per-square number is a prompt to investigate, not a verdict. Common causes:
- Scope mismatch: unreported decking replacement, extra layers, or steep or cut-up roofs. This is an estimating issue, so update your assumptions.
- Rework and callbacks: hours charged back to the original job show up in warranty reserve accounting.
- Idle time: material not on the roof at start, or weather delays paid as regular hours.
- Crew composition: a new hire lowers pace for a few weeks. Expect it and budget it.
Using the Numbers
Three decisions follow directly. First, set the estimating standard from your own trailing four-quarter median, not from a supplier's rule of thumb. Second, flag any job whose hours per square exceeds the estimate by 10% while it is still in progress. Third, tie crew lead incentives to hours per square and callback rate together, so speed does not come at the cost of quality. For the fully loaded picture, see the true cost of a roofing job.
Crew job costing is not extra bookkeeping. It is the same payroll data, tagged once, and read weekly.