After your next pay run finishes, could you say what a specific job, client, or placement cost you in labor, without opening a spreadsheet, in under a minute?
For most payroll teams, the honest answer is no. That's not a sign your team is slow or that you're missing some obvious report. It means your payroll system is built to track employees, not work.
That was the premise of a recent Greenshades webinar, led by Robert Crooms, our Product Intelligence Manager, and hosted by Rachel Moberg, Director of Lifecycle and Customer Growth. You can watch the full session here.
This recap covers the case for transaction-level tracking and what came up live. For the complete breakdown of the problem and the step-by-step setup inside Greenshades, see what not being able to track payroll by job, client, or project is costing you and how to track payroll by job, client, or project with custom fields.
Payroll vs. labor data
Payroll data and labor cost data can look like the same thing. They aren't.
Payroll data answers what an employee earned: hours, rate, taxes, deductions. Labor cost data answers what a specific job, client, or placement cost. Most systems only answer the first question well, so someone ends up translating it into the second by hand, every pay cycle. That translation work is where most of the manual effort in a payroll team's week actually comes from.
The root cause isn't a training gap or a reporting gap. It's structural. Most payroll systems are built around the employee as the central unit. When a paycheck processes, the system records what that person earned in total, not which job, client, or project that labor supported, unless something is deliberately built to capture it.
35% vs. 18%
PwC's 2024 Finance Effectiveness Benchmarking study found the median finance team spends 35% of payroll-related time on manual, automatable tasks — top-quartile companies have cut that to 18%.
Why job codes aren't the fix
Job codes work fine when the work is simple. They fall apart because they're one-dimensional: a single bucket assigned to an employee for a pay period.
That's fine until reality gets messier. A staffing employee works three placements in a week. A construction worker splits time across five job sites. A nurse picks up a shift at a different facility mid-period. In every one of those cases, the job code gets assigned to whatever the primary context is, and everything else gets estimated, annotated after the fact, or lost.
Job codes were built for a workforce where one person did one kind of work in one place. That's not how staffing, healthcare, construction, or transportation actually run today, and that's not a criticism of anyone's setup. It's a mismatch between simple tools and complex work.
The fix: tag the earning, not the employee
The fix is transaction-level tracking: attach context to the individual earning inside the paycheck, not to the employee for the whole pay period.
Say a nurse works a shift at Facility A for Client X, then a different shift at Facility B for Client Y later in the same pay period. Each earning carries its own tags. The employee still gets one clean paycheck. Underneath it, every line carries its own context.
Robert laid out three requirements any payroll system needs to meet for this to actually work:
- Identifiers attach at the earning level, not just the employee level.
- Admins add, edit, and retire field values themselves, without opening a ticket every time a new client or GL dimension shows up.
- The data is reportable and exportable. Captured data you can't query is just storage.
In Greenshades, this shows up as three field types. Payroll custom fields (client, job, placement, GL dimension) are the only ones that flow into cost reports and the general ledger. Timesheet custom fields capture context at clock-in. Profile custom fields hold static, employee-level data like department or credential level. Robert's rule of thumb: if you need it on a cost report, it has to be a payroll custom field.
What this looks like by industry
- Staffing. Each earning carries a placement ID, supporting both client billing and placement-level reporting. Teams running Bullhorn alongside Greenshades can have that placement ID flow in automatically through the integration.
- Healthcare. Tag each earning with a facility, patient identifier, or care unit for cost visibility across sites and departments.
- Construction. Job-level cost tracking lives inside payroll itself, so project managers see cost per job site without a manual allocation step.
- Professional services. Custom fields tie each earning to a client or project, which is what makes it possible to generate invoices directly from payroll data and see profitability at the engagement level.
The mechanism is the same across staffing, healthcare, and construction. What changes is what you tag and why.
Q&A
Do employee benefits get tied to cost reports, or is that still manual?
No. Custom field values attach to benefits the same way they attach to earnings, so benefit costs connect to the same placement or client IDs in your cost reports. Overtime and time off are included the same way.
How do you test custom fields without touching a live payroll run?
Robert's recommendation: open a special pay run with a small group of employees, build out your fields and list values, and confirm everything looks right on screen, then cancel the run instead of completing it. Nothing is permanent until you submit, and you can edit or delete a custom field at any point without contacting support.
Can you filter a report by more than one custom field at once?
Yes. A combination like facility plus patient, for example, filters together in the same report.
What happens to historical data if you add a new custom field mid-year?
New fields aren't retroactive. You can go back and manually add a value to a specific past earning if needed, but a new field won't break existing reports or force you to backfill anything.
Curious how this fits your setup?
Talk to your Greenshades contact about payroll custom fields.
Request a Demo