ProductSolutionsTradesPricingArticlesContact Log in Start free trial

Field & cost

How to track labor hours by job and cost code without three sets of numbers

For the office manager or PM at a commercial sub who owns both payroll and the job-cost report, and has to make them agree.

9 min read

Most commercial subs can tell you what they paid in labor last month. Far fewer can tell you which job it went to, and almost none can tell you which part of which job.

That gap is not a reporting problem. It is a collection problem. Labor is the single biggest number on a specialty sub’s income statement, and if you cannot attribute it you cannot bid the next one, defend a productivity claim, or notice that the second floor is eating you alive while there is still a third floor to go.

This article is about the part nobody writes down: how the hours get captured so they survive payroll, job costing and an argument.

The three sets of hours, and why they never agree

Walk into most subcontractors’ offices and the same week of work exists three times.

  1. Payroll hours. What the company pays. Gross, by person, by pay period. Accurate to the cent, because somebody would complain otherwise.
  2. Job hours. What the job cost. Assembled by the office from timesheets or a foreman’s text, usually a week late.
  3. Field hours. What the foreman says happened — in a notebook, a group chat, or a daily report.

Everybody knows those three should be one number. They are not, for a structural reason: each is collected by a different person for a different purpose on a different schedule. Payroll is collected to be paid. Job hours are collected to be reported. Field hours are collected because a GC asked.

Three collections means three chances to be wrong and no way to tell which one is. When the costed position says a job used 2,140 hours and payroll says 2,310, the honest answer is that nobody knows which is right, and the review ends with “we’ll look into it.”

The fix is boring and total: capture the hour once, at the point it is worked, at a grain you can report on. Everything else here is detail hanging off that sentence.

What a cost code is actually for

“Cost code” sounds like accounting. It is not. A cost code is a bet about where your money goes, and its only job is to let you compare this job to the last one.

So the test for a cost-code structure is not whether it is complete. It is whether a foreman will use it correctly at 3:30 on a Friday.

Most subs fail in one of two directions.

Too few codes. One bucket called “labor” per job. You learn that the job lost money and nothing about where. Useless for bidding, because every historical unit rate is an average of everything.

Too many codes. Eighty-four codes imported from a GC’s schedule or an estimating template. Field crews pick the first plausible one, or the same one all month, and now you have precise-looking data that is wrong — which is worse than coarse data that is right, because you will act on it.

The number that works for most $5–30M subs is six to twelve codes per job type, organized the way the work actually sequences for your trade.

  • Electrical: temp power, underground, rough-in by floor or area, gear and equipment set, devices and trim, fire alarm, controls, punch.
  • Mechanical: shop fabrication, equipment set, duct rough, piping rough, insulation, controls, start-up and balance, punch.
  • Plumbing: underslab, above-ground rough, water and waste risers, fixture set, equipment, gas, test and punch.
  • Drywall and framing: layout, framing, hanging, taping and finishing, patch and rework, punch.

Two codes matter more than people expect, and both are usually missing.

Punch and rework. If punch hours hide inside the production code, every unit rate you bid off that history is quietly optimistic. Break them out and you will find the real number is larger than you assumed — and you will start bidding it.

Backcharge and out-of-scope work. Hours worked because somebody else was wrong. If they live in your production codes you are absorbing the cost and losing the evidence. They belong in their own code the day they happen, which is also the day the change order conversation should start.

Choose your grain, then stop

A labor hour can be tagged with job, cost code, area or floor, worker, and date. Every tag you add multiplies the field’s chance of getting it wrong.

Pick the smallest set that answers a question you will actually ask.

  • Job plus date plus worker is the floor. Without it you have no payroll and no cost at all.
  • Job plus phase or cost code is where useful reporting starts. This is the level that tells you whether the rough-in is tracking.
  • Job plus phase plus area or floor is worth it on repetitive vertical work, and only then. If the job is one floor of one building, area tagging buys nothing and costs accuracy.

The test is simple: if nobody is going to run the report, do not collect the field. A dimension collected and never read is pure cost to the people in the field, and they know it.

Five rules that make the hours reconcile

1. One entry, at the source, on the day

The foreman who was there enters the hours, on the day, on the job. Not the office from a photo of a timesheet on Monday. Every re-entry is a translation, and translations are where hours move between jobs.

This is also why labor belongs on the daily log, or on a time clock tied to the same job, rather than in a separate timesheet app nobody reconciles. The foreman is already writing down the day. Hours are one more field on a form he is already filling in, not a second system to remember. If you are designing that form, here are the eleven fields a daily log needs.

2. Snapshot the rate on the day it was worked

This one is subtle and it ruins more costing reports than anything else.

In a homemade spreadsheet, labor cost is usually hours times the worker’s current rate. So when you give a journeyman a raise in June, every hour he worked since January silently re-costs. Last quarter’s margin changes because of something you did this week, and no two reports ever reconcile again.

The hour must be costed at the rate that applied on the date it was worked, frozen. A raise changes the future and nothing else.

3. Set the burden explicitly, and know what is in it

A bare wage is not a cost. Payroll taxes, workers’ comp, general liability, union benefits or fringes, vacation and holiday, and small tools all ride on top. Depending on trade, state and comp rate, the loaded cost of an hour runs well north of the bare wage, and for some trades and states by a large margin.

Two mistakes here. Using the bare wage, then wondering why profitable jobs do not produce cash. Or using a burden somebody set years ago that nobody can explain.

Write the percentage down with what it includes, review it when your comp rate changes, and build it once for both uses: your cost per hour and the rate you bill T&M at come from the same arithmetic, with markup added on the billing side.

4. Keep billing hours out of your cost hours

If you bill a T&M ticket and also post those hours to job cost from the ticket, you double-count every hour of extra work. Every job with extras on it looks like it is losing money, which is the fastest way to lose faith in a costing report.

A T&M tag is a billing document. Your cost comes from the labor record. The same hour appears on both — once as money you are owed, once as money you spent — and it should land in actuals from one of them only.

5. Exclude people an hourly cost would be a fiction for

Salaried PMs and superintendents, and piece-rate crews, do not have a meaningful hourly cost. Spreading a salary across jobs by hours is an allocation, not a cost, and it will not reconcile with anything.

Track them and charge them if your system does that deliberately, but keep them out of the hourly labor cost line so the number means one thing.

Make the report answer three questions

If your labor reporting cannot answer these in under a minute, the structure is not earning its keep.

Where are we against budget, by code, right now? Not at closeout. The point of a cost code is to show you that taping is at seventy percent of budget with half the building left, while there is still a decision to make.

What did this unit of work cost last time? Hours per fixture, per device, per thousand square feet, per floor. This is the only honest basis for the next bid, and the whole reason the codes exist.

Which hours were somebody else’s fault? Backcharge and out-of-scope hours, by job, by month. That number is a claim if you captured it and a loss if you did not.

How SubMark handles it

SubMark is built on the one-entry rule above, so here is exactly what it does and where the edges are.

  • Hours are recorded once, from the time clock or the daily log’s labor entries, per worker, per job, per day. Those same hours feed the weekly payroll report and job costing. Field users are free and unlimited, so no license decision ever determines who records a day.
  • Each hour is costed at the rate that applied on that date. A raise next month does not rewrite last month’s margin.
  • Labor burden is a percentage you set, applied on top of the logged cost. It defaults to zero, so the number is never quietly inflated by an assumption you did not make.
  • Costing is per job, grouped by cost type — labor, crew lump sum, materials invoiced, materials committed, QuickBooks costs and subcontractors — against your budget lines, with estimated, actual and variance on each.
  • Labor broken out by phase or work type needs phase tracking switched on. The drywall pack ships with it on; for every other trade it is a switch in Settings, not an upgrade. Your trade pack loads the phase names, so the breakdown reads in your own terminology.
  • Open purchase orders count as committed cost before any invoice arrives, which is the difference between a budget line that is fine and one that is already spent.
  • Overrun alerts fire on the job total and on labor specifically, with the dollar amount and the percentage.
  • T&M hours stay out of costing actuals on purpose, per rule four.

Two honest limits. The grain is job, cost type, and phase when phase tracking is on — not a free-form cost-code library you define from scratch, so map your codes onto your trade’s phases rather than the other way round. And salaried and piece-rate workers are excluded from labor cost by design, per rule five.

Job costing covers the budget-versus-actual side in more detail, and daily logs cover the capture side.

What to do this month

  1. Write down six to twelve codes for your most common job type, in your trade’s sequence, including punch and backcharge.
  2. Pick your grain — almost certainly job plus phase — and refuse the extra dimension nobody will report on.
  3. Calculate your burden percentage from this year’s comp rate and benefits, and write down what is in it.
  4. Move hour capture to the person who was there, on the day, in whatever system your field already touches.
  5. Run one job’s budget-versus-actual by code at the end of the month and ask the three questions above. Whether the answers are good or bad, you will know something you did not know a month ago.

None of this is sophisticated. It is the hour, captured once, at a grain you chose on purpose — and that is the difference between a labor number you can bid off and one you can only apologize for.

Make the hours count once.

In SubMark the hours from the time clock and the daily log are the hours on the payroll report and the hours job costing uses, costed at the rate that applied on the day they were worked.

Start free trial

14-day free trial, no card needed. Field users and the subs you invite are free and unlimited — see how pricing works. What SubMark does