Most cleaning, security and facility services businesses know whether they made money last month. Far fewer can say which sites and contracts made it, and which ones quietly lost it. The reason is rarely a lack of effort. The revenue for a site is in the invoicing system, but its costs are spread across the roster, the timesheet app, payroll, consumables purchasing, subcontractor bills and vehicle costs, and none of them is recorded against the same site in the same way. Until those costs carry the same site or contract code, the profit and loss can only show the business as a whole.
Why it's hard to see
Margins in contract cleaning are under steady pressure. INCLEAN's report on the 2025 Building Service Contractor survey says inflation, higher wages and client pricing demands continue to squeeze margins, with labour shortages and cost pressures among the top challenges. When every contract is tight, a few weak ones can cancel out the good ones, and the overall P&L hides which is which.
Here's where each piece of a site's numbers usually lives:
- Revenue: the contract schedule (monthly fee, periodic works, extras) in a spreadsheet or contract system, and the invoices in the accounting software.
- Rostered hours: the rostering tool, by worker and shift.
- Actual hours worked: the timesheet or clock-in app, sometimes a site sign-in book.
- Pay cost: payroll, including penalty rates, overtime, allowances, leave, super and payroll tax.
- Consumables and equipment: purchase orders and supplier invoices, often coded to one expense account for the whole business.
- Subcontractors: their invoices, coded to "subcontractors" rather than to the site they worked on.
- Vehicles and travel: fuel cards, mileage and travel time between sites.
- Supervision and admin: area managers and the office, usually treated as overhead.
Each system is correct on its own terms. The problem is that they don't share a site code, so joining them means a spreadsheet, a day of exports and a lot of judgement. That's what people mean by [data silos](/guides/plain-english-glossary#data-silos): information stuck in separate systems that never meet.
Paid hours versus billed hours
The single most useful number for a labour-based contract is the gap between the hours you paid for and the hours you could bill.
The contract says the site gets a set number of cleaning or guarding hours each week. What you actually pay for that site often includes more:
- travel time between sites, where the award or your arrangements require it to be paid
- minimum shift lengths that are longer than the work
- overtime and penalty rates when a regular worker is away and cover comes in
- handover, induction and training shifts that the client doesn't pay for
- extra visits to fix a complaint
- supervisor time on site.
For example, if a site's contract covers 990 hours in a month but the roster, timesheets and cover shifts add up to 1,040 paid hours, those 50 hours are cost with no revenue against them. Nobody chose to give them away. They just never showed up next to each other.
Seeing that gap needs three numbers per site, per period, from three different systems: hours billed (from the contract and invoice), hours rostered (from the roster) and hours paid (from timesheets and payroll). Our article on pay rate versus charge rate covers the rate side of the same problem in labour hire, and our post on award pay errors in cleaning and security covers getting the paid hours right.
The pattern behind it
The same four causes sit under almost every "we can't see profit by job" problem we work on:
- Information typed in again. New sites are set up in the roster, payroll, purchasing and invoicing separately, so the site name is spelt four ways. That's [double data entry](/guides/plain-english-glossary#double-data-entry), the same information typed into two or more systems.
- No [single source of truth](/guides/plain-english-glossary#single-source-of-truth), one agreed list of sites and contracts that every system uses.
- Knowledge in people's heads. The area manager knows which sites always run over and which client keeps asking for extras that aren't on the schedule.
- Reports built by hand. Contract profitability is reviewed once a year, at renewal, from a spreadsheet, which is too late to fix a loss-making price.
A simple site P&L model
You don't need a complicated costing system to start. A useful site P&L has just a few lines, each fed from a system you already have:
- Contract revenue for the period: the regular fee plus periodic works and approved extras actually invoiced.
- Direct labour: paid hours for that site multiplied by the true hourly cost (base rate plus penalties, leave, super, workers comp and payroll tax), from payroll and timesheets.
- Subcontractor cost for work on that site.
- Consumables and equipment charged to the site.
- Travel and vehicles allocated by site visits.
- Site contribution = revenue minus lines 2 to 5.
- A share of supervision and overheads, allocated on a rule you agree (for example, by hours or by revenue).
- Site profit = contribution minus the overhead share.
Alongside it, show billed hours, rostered hours and paid hours, so the reason for a weak margin is visible, not just the result.
Start with lines 1, 2 and 6. Direct labour is usually most of the cost on a cleaning or security contract, so paid hours against revenue by site already tells you where to look. Add the other lines as you get the coding right.
What fixing it generally involves
- One site and contract list. Agree a single code for every site and contract, held in one place, and use it in the roster, timesheets, payroll, purchasing and invoicing. This is often settings and data clean-up rather than new software.
- Hours flow by site. Make sure the timesheet or clock-in records carry the site, and that the export to payroll keeps it. Our article on where the standard Deputy integration stops covers one common gap.
- Costs coded at entry. Purchase orders for consumables and subcontractor bills get the site code when they're raised, not at month-end.
- Extras reach the invoice. Ad hoc works and call-outs recorded against the site are invoiced from the same record.
- Report from one place. Pull revenue, hours and costs by site into one report, refreshed weekly rather than built once a year. That's the kind of business intelligence and reporting work we do, using the systems you already run.
What it looks like when it's fixed
On Monday morning, the operations manager opens one screen showing last week's margin for every contract, with billed, rostered and paid hours side by side. Three sites are flagged red. One has had cover shifts all week because a regular cleaner was on leave. One had an unbilled extra clean the client asked for on Thursday, which can still be invoiced. One has been underwater for months, and the renewal is due in the new year, so you go into that conversation with the numbers.
None of that requires everyone to change software. It requires the systems you have to agree on what a site is, and pass the information across instead of someone retyping it.
Frequently asked questions
How do I work out profit per cleaning contract?
Take the revenue invoiced for the contract, then subtract the direct costs for that site: paid labour at its true cost, subcontractors, consumables and travel. That gives you the site's contribution. Then subtract a fair share of supervision and overheads. The hard part is getting labour and costs coded to the right site, not the formula.
Why are our paid hours higher than our billed hours?
Usually because of travel between sites, minimum shift lengths, cover shifts at overtime or penalty rates, training and handover shifts, and extra visits the client doesn't pay for. Seeing billed, rostered and paid hours side by side for each site shows which of these is driving it.
Can our rostering or accounting software report profit by site?
Partly. Rostering tools report hours and wage cost by location, and accounting software can tag revenue and costs by site with tracking categories or job codes. Neither usually sees the other's data, so a true site P&L generally means combining them in one report.
Is this only for big contractors?
No. A smaller business with a few dozen sites often benefits most, because one loss-making contract has a bigger effect on the whole business. Start with paid hours against revenue by site.
See the wider problem of not seeing job profit until it's too late, the same pattern in transport, profit per run, our cleaning, security and facility services page, and the industries we work with. If you'd like your numbers mapped first, our $5,000 Process & Systems Audit documents how hours, costs and invoices move through your business today and where the site code drops off.
If you can't say which of your contracts make money, book a free initial chat and we'll talk through what it would take to see profit by site.