HVAC Markup and Margin: A Worked Check on Past Jobs With AI

Coding Liquids tutorial cover featuring Sagnik Bhattacharya for HVAC Markup and Margin: A Worked Check on Past Jobs With AI.
Coding Liquids tutorial cover featuring Sagnik Bhattacharya for HVAC Markup and Margin: A Worked Check on Past Jobs With AI.

Export 50 completed jobs with price, parts, equipment and labour hours. In a sheet, work out job cost, profit, margin (profit divided by price) and markup (profit divided by cost), then flag every job below your target margin. Let AI write the formulas, but check the totals by hand, because AI arithmetic slips.

Markup and margin are different numbers: a 50% markup is only a 33.3% margin. Most online charts quote markup, while overhead and profit targets are margins, so a company that "marks up 50%" discovers it kept a third. The audit below shows where that gap hides, using an imagined sample of 50 jobs.

Follow me on Instagram@sagnikteaches

Markup and margin on one page

Markup is profit as a percentage of cost. Margin is profit as a percentage of price. The same job carries two percentages, and markup is always the larger. Buy a part for $200 and sell it for $300: profit is $100, markup is 50% and margin is 33.3%. A 40% markup on that part sells it for $280, which is only a 28.6% margin. To earn a 40% margin you divide the cost by 0.6 and charge $333.33, and the markup that produces is 66.7%.

Connect on LinkedInSagnik Bhattacharya
  • Price for a target margin: cost divided by (1 minus the margin).
  • Markup needed for a target margin: margin divided by (1 minus the margin).
  • Margin from a markup: markup divided by (1 plus the markup).
Margin you wantMarkup you needMarkup you useMargin you get
30%42.9%25%20.0%
35%53.8%50%33.3%
40%66.7%75%42.9%
45%81.8%100%50.0%
50%100.0%150%60.0%

The two halves of that table are independent: read the left pair to find the markup a margin target needs, and the right pair to see what a favourite markup really earns. Both numbers show up in the software you already use. Jobber's help pages describe markup as the percentage added to a unit cost to get the unit price, and define the estimated margin on a quote as price minus cost of goods sold, divided by price. Its job costing view calculates profit margin as profit divided by revenue. Markups are listed as available to admin users on select plans, and job costing on the Grow and Plus plans. Whatever you use, check which of the two a screen is showing before you compare it with a target.

Subscribe on YouTube@sagnikteaches

What counts as job cost, and what stays in overhead

A margin is only as honest as the cost under it. The usual error is leaving out labour or using a wage instead of what the technician really costs. Decide the buckets once, write them down, and use them for every job.

ItemIn job cost?Note
Equipment, parts and materialsYesAt what you paid the supplier, including freight you were charged.
Subcontractors, permits, disposalYesOften missing from quote templates.
Technician time, on site and drivingYesAt the loaded rate: wage plus payroll costs and benefits.
Sales commission tied to the jobYesOtherwise replacements look better than they are.
Financing fees paid by youYesPer job, when the customer finances.
Van running costsYour choicePer-job charge or overhead; be consistent.
Office wages, rent, marketing, insuranceNoOverhead, covered by the margin.
Rework and callback labourTrack separatelyTag it as rework so the original job is not quietly penalised.

Jobber's job costing help page is explicit about the labour point: the employee cost entered for each user should include wage, benefits and taxes, and it applies to future timesheets, not past ones. It also warns against adding labour to line items when timesheets already record it, and says that where a job has both line item costs and expenses it currently counts both, so a material entered twice drags the margin down. On the Plus plan, supplier invoice scanning turns uploaded supplier invoices into draft expenses for you to approve, which is an easy way to double-count materials already entered as line item costs. Whatever software you use, check once that no cost sits in two places.

The effect of leaving labour out is large. In the imagined sample below, the 50 jobs earn a 38.3% gross margin with labour counted and would show 52.8% without it, which is 14.5 points of false comfort. Labour you cannot see is the cost most likely to be missing from an old quote. For where rework labour goes once you start tracking it, see the tutorial on logging the cause of every HVAC callback.

The Complete Excel Course with AI Integration thumbnail

The Complete Excel Course with AI Integration

From formulas and pivot tables to Power Query, DAX, VBA and AI with Copilot, ChatGPT and Claude — hands-on from the first lesson.

By Sagnik Bhattacharya and Virginia Thorn, Primetime Emmy Award winner

Buy now

Set the target margin from your own overheads

A target margin should come from arithmetic, not from a chart. Add your yearly overheads to the net profit you want, and divide by yearly revenue. That is the gross margin the average job has to earn.

Take an imagined company with revenue of $1,200,000 and overheads of $380,000. It wants a net profit of 10%, which is $120,000. Overheads plus profit come to $500,000, and $500,000 divided by $1,200,000 is 41.7%. The jobs must average a 41.7% margin, which is a 71.4% markup. If the owner wants 15% net instead, the sum is $380,000 plus $180,000 over $1,200,000, a 46.7% margin and an 87.5% markup. These are invented figures. Take your own overheads from last year's accounts, and ask your accountant which costs they treat as cost of sales, so your job cost and overhead split matches theirs.

Different job types can carry different targets, because a cheap tune-up and a $9,000 replacement behave differently. The blended result across the year still has to reach the number. That is why the audit below looks at types separately and then at the whole. If you are still deciding how to charge for visits and repairs, testing flat rate against hourly with AI and building a service call fee from your costs cover the pricing side that this audit then tests.

Export 50 jobs and pick them fairly

Choose the 50 before you look at the numbers. Take every nth completed invoice from the last six to twelve months, and make sure at least 10 are replacements, because that is where most of the money sits. Do not pick your best jobs, and do not leave out discounted ones or callbacks. A sample picked by hand will flatter you.

You need these columns for each job: job ID, job type, price before any tax, materials and equipment cost, subcontract cost, permits and disposal, and labour hours including driving. The loaded labour rate is one number in a cell.

Where the data comes from depends on your software. In Jobber, on the Grow and Plus plans, the one-off jobs report under Insights, then Reports, then Work reports includes job costing columns. The job costing help page says reporting is not available for job costs on recurring jobs. The report itself has an Export to CSV option that emails the file to the address you log in with, with all columns or only the ones you selected. Job costing only works if each user has a labour cost entered and each line item has a unit cost, and the page says a new labour cost applies to future timesheets only, so old jobs may show no labour. In accounting software, use a profit-by-customer or project report if you have set up job tracking, or build the columns from invoices, supplier bills and timesheets. Without any of those, a sheet built by hand from invoices and the job card for 50 jobs takes about an hour. How to build a job costing sheet in Excel with AI help explains that setup in more detail.

Before anything goes near an AI tool, delete customer names, addresses and phone numbers. The job ID is enough. Allow two hours for the whole audit: 45 minutes to export and clean, 30 to build, 45 to check and read.

Build the sheet so every number can be checked by hand

Put the loaded labour rate in one cell, say P1, and the target margin in P2. Then add columns for labour cost, total job cost, profit, margin, markup and a flag. Every one is a single short formula that you can verify on a calculator. The summary table by job type sums revenue and cost first and divides second; it never averages the row margins.

I2  Labour cost      =G2*$P$1
J2  Total job cost   =D2+E2+F2+I2
K2  Profit           =C2-J2
L2  Margin           =IF(C2=0,"",K2/C2)
M2  Markup           =IF(J2=0,"",K2/J2)
N2  Flag             =IF(L2<$P$2,"LOW","")

Summary by type (type name in R2):
S2  Jobs             =COUNTIFS($B$2:$B$51,R2)
T2  Revenue          =SUMIFS($C$2:$C$51,$B$2:$B$51,R2)
U2  Cost             =SUMIFS($J$2:$J$51,$B$2:$B$51,R2)
V2  Profit           =T2-U2
W2  Margin           =V2/T2
X2  Markup           =V2/U2

Control totals:      =SUM(C2:C51)   =SUM(J2:J51)

AI is good at writing and explaining those formulas. Describe the columns, say where the rate and target sit, and forbid it from calculating anything itself.

I have a spreadsheet of 50 completed HVAC jobs. Columns: A job ID, B job type, C price before tax, D materials and equipment, E subcontract, F permits and disposal, G labour hours (on site plus driving). Cell P1 holds the loaded labour rate per hour and P2 holds my target margin.
Write formulas for row 2, which I will fill down: I labour cost, J total job cost, K profit, L margin as profit divided by price, M markup as profit divided by cost, N the word LOW when margin is below P2.
Then write a summary table by job type with jobs, revenue, cost, profit, margin and markup. Group margin must be total profit divided by total revenue, never an average of row margins.
Give formulas only, with one line of explanation each. Do not calculate any totals yourself.

In an illustrative reply, three of the formulas needed correcting, and a quick read caught each one.

CellWhat the AI wroteProblemFix
Markup, row 2Profit divided by priceThat is margin again, so the markup column duplicates it.Profit divided by cost.
Group marginAn average of the row marginsSmall jobs with high margins drag the answer up.Group profit divided by group revenue.
FlagA target of 0.417 typed inside the formulaChanging the target in P2 would change nothing.Refer to $P$2 instead.

Excel and Sheets have AI features of their own. Excel's Copilot side pane is still there, but the =COPILOT() worksheet function was retired on 14 September 2026 and should not appear in any sheet you build. Gemini's =AI() function in Sheets generates text for a range of cells, cannot be nested and does not refresh by itself, so it is no tool for sums. Use AI to write the formulas once, then let ordinary formulas do the arithmetic. Prompt ideas for getting formulas rather than answers are in Google Sheets AI prompts.

The audit: 50 jobs, 14 flags and one clear leak

The imagined sample holds 22 repairs, 12 tune-ups, 13 replacements and 3 other jobs (a thermostat upgrade, duct sealing and an air cleaner), all costed with a loaded labour rate of $52 an hour. The company's target is the 41.7% from the overhead sum above. Here are ten of the 50 rows, picked to show the spread.

JobTypePriceCostProfitMarginMarkupFlag
J-3123Tune-up$169$95.20$73.8043.7%77.5%
J-3133Tune-up$149$89.20$59.8040.1%67.0%LOW
J-3103Repair$440$206.00$234.0053.2%113.6%
J-3111Repair$715$304.60$410.4057.4%134.7%
J-3150Other$1,880$962.00$918.0048.8%95.4%
J-3145Replacement$9,190$5,405.20$3,784.8041.2%70.0%LOW
J-3146Replacement$12,230$7,401.40$4,828.6039.5%65.2%LOW
J-3140Replacement$7,250$4,722.60$2,527.4034.9%53.5%LOW
J-3143Replacement$8,350$5,790.40$2,559.6030.7%44.2%LOW
J-3141Replacement$7,390$5,166.80$2,223.2030.1%43.0%LOW

Take the last row apart to see where cost comes from. Equipment $3,110, materials $380, an electrical subcontract $280 and permits and disposal $310 come to $4,080. Labour was 20.9 hours at $52, which is $1,086.80. Total cost is $5,166.80, profit $2,223.20, margin 30.1% and markup 43.0%. If the owner had priced it "cost plus 40%", the price would have been $7,233.52 and the margin 28.6%, which is where thinking in markup leads. The price that earns 41.7% is $5,166.80 divided by 0.5833, about $8,857.

Now summarise the full 50 by type, with margin worked from group totals.

TypeJobsRevenueCostProfitMarginMarkup
Repairs22$13,310$5,791.80$7,518.2056.5%129.8%
Tune-ups12$2,108$988.20$1,119.8053.1%113.3%
Replacements13$110,010$70,991.20$39,018.8035.5%55.0%
Other3$3,830$1,919.20$1,910.8049.9%99.6%
All 50 jobs50$129,258$79,690.40$49,567.6038.3%62.2%

Three things stand out. Repairs and tune-ups are comfortably above target, so the small-job side of the business is not the problem. Replacements are a quarter of the jobs but 85.1% of the revenue and 78.7% of the profit, so their 35.5% margin sets the whole company's result. And the blended 38.3% is about 3.3 points under the 41.7% target. If this sample reflects a year of $1,200,000 revenue, that is a gross profit shortfall of roughly $39,800. The replacements would need a markup of 71.4%; they are earning 55.0%.

Catching AI arithmetic slips before they reach a decision

An assistant can summarise a table in seconds and get a figure wrong in ways that read perfectly. Run these five checks on any number you did not calculate with a formula.

  1. Control total. The sum of the price column must equal your accounting software's total for the same invoices, to the cent. Sum the cost column too, and compare it with supplier bills and timesheets where you can.
  2. Recompute five rows. Pick five at random, including one replacement, and redo them on a calculator.
  3. Sanity limits. A margin can never exceed 100%, and a markup should always be larger than the margin on the same row.
  4. Sort the extremes. Open the top and bottom five by margin. A job at 85% or below zero is a data entry error until proved otherwise.
  5. Ask for formulas, not answers. If the tool gives a total, ask it to show the formula it would use, then compare that formula's result with the AI's total.

Three illustrative slips show how these work in practice. In the first, the assistant's summary reported total revenue of $129,109. The sheet said $129,258, and the $149 difference is exactly job J-3133, a tune-up the assistant skipped. Nothing about $129,109 looked wrong, and only the control total caught it. In the second, the assistant reported an "average margin of 49.8%". That is the simple average of the 50 row margins, which counts each of the 37 non-replacement jobs as heavily as a $9,000 replacement. The correct group figure is total profit over total revenue, 38.3%, and the 11.5-point gap is the difference between feeling fine and being under target. In the third, a margin column showed 113.6% for job J-3103. Margin cannot exceed 100%, so the column was holding markup, and the sanity limit caught it in seconds.

Flagged jobs: sort by dollars short, then find the cause

Fourteen of the 50 jobs sit below 41.7%: all 13 replacements and one tune-up. A percentage flag alone is a poor guide to what to fix, because it treats a $4 shortfall like a $1,600 one. Add a column showing the price that would reach target, which is cost divided by one minus the target, and the gap between that and the actual price. Sorted by dollars, the picture changes.

JobMarginPrice at targetDollars shortCause found in the job notes (illustrative)
J-314430.4%$9,871$1,601Labour ran to 23.9 hours. A duct modification was not in the estimate.
J-314330.7%$9,926$1,576A $350 subcontract was not on the quote template.
J-314130.1%$8,857$1,467Quote written seven weeks before the order. Equipment cost rose in between.
J-313340.1%$153$4Dispatch discounted the tune-up to $149. Trivial, but a pattern if it repeats.

All 14 together are $11,693 short of target, and the 13 replacements account for $11,689 of it. The tune-up is $4 adrift and not worth anyone's time. The three big replacements show three different causes: an estimate that missed a task, a quote template with no line for a subcontractor, and a quote that sat too long. An AI assistant is useful for this step in a reading role. Paste the job notes for the flagged jobs, with names removed, and ask it to propose a cause for each, citing the sentence it relied on. Then confirm each against the job card yourself.

Now the what-if. If all 13 replacements had been priced to reach 41.7%, revenue would have been $121,699 instead of $110,010, which is $11,689 more, an average of $899 a job or 10.6%. Whether your market accepts that rise is a separate question. The alternatives are to cut equipment cost with a second supplier quote, to estimate labour from your own recorded hours, and to stop absorbing subcontract costs. The audit does not tell you which. It tells you where to look, and how much is at stake.

From audit to price book: three changes and a re-test

Make changes that attack the causes you found, not a general price rise.

  • A margin floor for replacement quotes. No quote leaves the office below 41.7% unless the owner signs it off, and the sheet shows the margin before the quote is sent. Jobber's quote screen already shows an estimated margin to the user building it, if you use that product.
  • A shorter quote life. Equipment prices move, so a replacement quote is valid for a set number of days, with wording that lets you re-price if the supplier's cost changes before the order.
  • Parts markup that falls as cost rises. A flat percentage over-charges expensive parts and under-earns on cheap ones. Here is an illustrative tier table, with the margin each tier produces.
Part cost bandMarkupResulting margin
Up to $50150%60.0%
$50.01 to $200100%50.0%
$200.01 to $50066.7%40.0%
Over $50050%33.3%

The bands are an example, not a recommendation: set yours from your own figures, and test them against your market before you rely on them. The good-better-best approach in a worked replacement quote written with AI is one way to make sure each option clears the floor.

Then rerun the audit. Draw a fresh 50 jobs a quarter later, use the same sheet, and put the new summary table beside the old one. The numbers to watch are replacement margin, the number of flagged jobs and the total dollars short. Save the control totals each time, since they are what make the workbook trustworthy. If the replacement margin has not moved after one quarter of changes, the cause is probably something the job notes do not show, and a day with the estimator is more useful than another formula.

Markup and margin questions from HVAC owners

Is a 50% markup a good HVAC markup?

A 50% markup is a 33.3% margin, so it is only good if your overheads and profit target are covered by that. Work out your own number: add your yearly overheads and the net profit you want, divide by yearly revenue, and that percentage is the gross margin every job must average. In the worked example below it comes to 41.7%, which needs a markup of 71.4%.

Should van costs go into job cost or overhead?

Either is defensible, but pick one and use it everywhere. Charging a fixed amount per job for the van puts the cost where it is incurred and makes short jobs look as expensive as they are. Treating vans as overhead is simpler, but then your target margin must be set from a version of the accounts that treats them the same way.

Can I paste my job list into ChatGPT or Claude?

Yes, once you have removed customer names, addresses and phone numbers; job IDs and numbers are all it needs. Check your account's training setting if it is a consumer plan, since business plans from the main vendors do not train on your content by default. Whatever you paste, verify every total it gives back against your own sheet.

How often should I rerun the audit?

Quarterly on a fresh sample of 50 jobs is enough for most firms, plus once after any supplier price rise, wage change or change to your price book. Keep each run's summary table in the same workbook so you can see whether replacement margin, the usual weak spot, is moving the right way.

Further reads

Sources: Jobber help pages on job costing, markups on quotes and the one-off jobs report (read November 2026). The 50 jobs, prices, costs and overhead figures are invented for illustration, and so are the AI replies shown.

Want your margin check built into your software?

On a 1:1 call we can look at how your jobs, costs and labour hours are recorded, decide what a monthly margin report needs, and check whether your current tools can produce it.

Book a 1:1 call with me