Export a year of sales by product with quantities, prices and discounts, add each product's landed cost and the costs that come with every sale (payment and platform fees, shipping, packaging, returns), then have AI calculate contribution margin per product in code. Rank products by total contribution, not percentage, and check three of them by hand.
The margin in your accounts usually won't answer this question. It's one gross figure for the whole business, and the costs that differ most between products (free shipping on a heavy item, a marketplace's fee, a high return rate) are lumped into overheads. That's why the products that look best on price are often the ones that earn least once every cost is in.
The margin stack: from list price to what a product really earns
Build each product's figure in layers, per unit sold:
- List price, what the product is advertised at.
- Minus average discount: promotions, voucher codes, trade and volume discounts. Use the average actually given, not the planned one.
- Equals net price, what customers actually paid.
- Minus landed cost: purchase price plus inbound freight, duties and any cost of getting the product onto your shelf.
- Minus variable selling costs: payment processing, marketplace or platform fees, packaging, the shipping you pay beyond what the customer paid, and the cost of returns and breakages.
- Equals contribution per unit: what each sale adds towards fixed costs and profit.
- Times units sold equals total contribution, the number that decides which products matter.
Gross margin stops at step 4. Contribution margin goes to step 6. The gap between the two is where most surprises live.
The data you need and where it usually hides
| Data | Usual source | Common gap |
|---|---|---|
| Units, price, discount per product | Sales platform or till export, by order line | Discounts applied to the whole order, not the line |
| Landed cost per unit | Purchase invoices, stock system cost field | Freight and duties billed separately and never added |
| Payment fees | Payment provider statements | Recorded as one monthly expense |
| Marketplace fees | Marketplace settlement reports | Netted off payouts, so they never appear as a cost |
| Shipping cost per order | Carrier invoices or shipping software | Not linked to the order or the products in it |
| Returns and refunds | Returns log, refund reports | Handling cost and unsellable returns ignored |
If you sell through Shopify, its Gross profit by product report is a useful starting export, with two limits worth knowing from Shopify's help pages: it only reports profit for products that had a cost recorded at the time they were sold, and the cost per item field is static, so if you haven't updated costs when supplier prices changed, the report is using old ones. It also stops at gross profit, so you still need the rest of the stack.
The worked example: five products, five different stories
Take an illustrative bookkeeping firm asked by a client, an online kitchenware seller, why sales are up but the bank balance isn't. The bookkeeper joins a year of order lines with cost, fee, shipping and returns data, and asks the AI to build the stack for each product:
Attached: order_lines (order_id, sku, qty, list_price,
discount), costs (sku, landed_cost), shipping (order_id,
cost_to_us, charged_to_customer, weight_kg per sku),
fees (order_id, channel, payment_fee, platform_fee),
returns (order_id, sku, qty, refund, handling_cost,
resaleable yes/no).
For each sku, calculate in Python and show the code:
units, avg net price, landed cost, payment fee, platform
fee, shipping subsidy (cost_to_us minus charged_to_customer,
split across the lines in each order by weight), packaging
({rate} per order split by weight), returns cost per unit sold
(refund value of unsaleable returns + handling), contribution
per unit, contribution %, total contribution, and gross
margin % (net price minus landed cost only).
Sort by total contribution. Check that total net sales match
{figure from the accounts}; report any difference.
An illustrative extract of the result, per unit sold:
| Product | Net price | Landed cost | Fees, shipping, packaging, returns | Contribution | Gross margin | Contribution margin | Units | Total contribution |
|---|---|---|---|---|---|---|---|---|
| Cast-iron pan | $58.88 | $27.50 | $11.67 | $19.71 | 53% | 33.5% | 1,850 | $36,464 |
| Knife set | $102.00 | $41.00 | $19.56 | $41.44 | 60% | 40.6% | 620 | $25,693 |
| Utensil set | $17.10 | $5.20 | $4.41 | $7.49 | 70% | 43.8% | 3,400 | $25,466 |
| Stand mixer | $260.10 | $168.00 | $71.52 | $20.58 | 35% | 7.9% | 410 | $8,438 |
| Glass storage jars | $32.30 | $11.80 | $17.07 | $3.43 | 63% | 10.6% | 1,200 | $4,116 |
Three things jump out, and none of them were visible in the accounts.
- The storage jars look like a star on gross margin (63%) and earn almost nothing. They're heavy and fragile, so the business pays $11.40 a unit in shipping beyond what customers pay, plus $2.10 in protective packaging and $2.60 in breakages. Each sale adds $3.43.
- The stand mixer sells mostly through a marketplace whose 15% fee takes $39 a unit. Add $18 shipping and a 7% return rate on a bulky item, and a $289 product contributes about $20.
- The cast-iron pan has a lower percentage than the utensil set but earns the most in total. Percentages tell you efficiency; totals tell you what the business depends on. Rank by total contribution first.
What to fix in the AI's first pass
The first run is rarely right, and the errors are usually in allocation rather than arithmetic. In this example, the bookkeeper caught three:
- Payment fees counted twice on marketplace orders. The marketplace fee already includes payment processing, but the AI applied the payment provider's percentage as well, understating the mixer's contribution by about $7 a unit. The fix was one line: "platform orders have no separate payment fee".
- Shipping split by price instead of weight on a first attempt that didn't specify the method. That made the knife set carry part of the jars' shipping cost in mixed orders. Splitting by weight is usually fairer for physical goods; say so in the prompt.
- Returned stock that was resold counted as a loss. A returned pan in good condition goes back on the shelf, so only the handling cost counts. The returns file needed a resaleable column, which is why it's in the prompt above.
None of these were maths mistakes, and all of them changed the ranking. The AI does what the instructions say; the judgement is in deciding how shared costs should be split. For why arithmetic should always run in code rather than in the chat, see why AI is unreliable at maths.
Two layers worth a closer look: discounts and channels
Discounts. The knife set's average discount of 15% looked like a pricing decision until the AI split order-level discounts back onto the lines they applied to. Most of it came from one source: a 15% welcome code for newsletter sign-ups, used on 38% of knife set orders, because the most expensive item in a first basket gets the biggest saving from a percentage code. The follow-up question was what would happen if the welcome offer became a fixed $10 off, or excluded the knife set. At an average discount of 8% instead of 15%, the net price rises to $110.40 and contribution rises by about $8 a unit after the slightly higher payment fee: roughly $5,000 a year on 620 sets, if volume holds. Whether it would hold is a test to run, not an assumption to make, but the size of the prize says the test is worth running.
Channels. The same product can have very different margins depending on where it sells. Split by channel, the stand mixer contributes about $52 a unit on the client's own website (a 3% payment fee of $7.80 instead of the marketplace's $39) and about $21 on the marketplace. The marketplace isn't simply worse: it brings buyers who would never find a small online store, and some of them come back to buy direct. But it changes the question from "should we sell the mixer?" to "should we price the mixer differently on each channel?", which is a much better question to be asking. Ask the AI for every product's contribution by channel as a second table; for businesses selling on more than one platform, it's often the most useful table in the whole analysis.
A quick way to check the numbers before believing them
Before anyone acts on the table, run four checks:
- Totals reconcile. Total net sales and total landed cost in the analysis match the accounts for the same period, within a small tolerance for timing.
- Three products by hand. Pick the top product, the bottom one and one in the middle. For the jars: 32.30 − 11.80 − 0.97 − 11.40 − 2.10 − 2.60 = 3.43. If your hand sum doesn't match, find out which layer differs.
- Nothing implausibly high. A product showing contribution above about 80% usually has a cost missing, often freight or duties.
- Units match stock movement. Units sold per product should roughly match what left the warehouse. A big gap means the order-line export and the stock system are counting different things.
What to do with each product once you know
| Pattern | Example | Typical response |
|---|---|---|
| High contribution, high volume | Cast-iron pan | Protect it: stock availability, supplier terms, don't discount it without reason |
| High contribution %, low value per unit | Utensil set | Use it as an add-on: suggest it to lift orders over the free-shipping threshold |
| Low contribution because of one cost layer | Storage jars (shipping) | Fix the layer: charge shipping on single items, sell as multi-packs, change packaging |
| Low contribution because of the channel | Stand mixer (marketplace fee) | Reprice on that channel, push the own-site channel, or drop it from the marketplace |
| Negative contribution | None here | Reprice, change supplier, or stop selling unless it's a deliberate loss-leader you can justify |
Ask the AI to model the fixes before you make them. For the jars, the question "what would contribution be if single jars carried a $6 shipping charge and 4-packs shipped free?" gets an answer in a minute, using the same stack. In this example, it came out at around $8 a unit on the assumption that half of buyers switched to 4-packs, which is worth testing for a month. If a price rise is the answer, planning and announcing a price increase covers how to do it without losing your best customers.
When the "products" are services: an insurance broker's lines
The same stack works for businesses whose products aren't physical. An illustrative insurance broker earns commission and fees on several product lines, and the costs that vary by line are mostly staff time: placing and renewing cover, handling mid-term changes, and supporting clients through claims. The broker had no time recording, so it used a proxy: its broking system logs every activity (call, email, document, task) against a policy, and the AI counted activities per policy by line over a year. A two-week sample of timed work gave an average of 11 minutes per activity, which turned activity counts into hours. At an average staff cost of $45 an hour:
| Line | Policies | Income | Handling cost | Claims support cost | Contribution | Margin |
|---|---|---|---|---|---|---|
| Fleet | 60 | $111,000 | $37,800 | $16,200 | $57,000 | 51% |
| Professional indemnity | 150 | $96,000 | $27,000 | $3,375 | $65,625 | 68% |
| Landlord | 420 | $88,200 | $47,250 | $15,120 | $25,830 | 29% |
| Personal home | 900 | $85,500 | $64,800 | $28,350 | −$7,650 | −9% |
The home insurance book, the largest by policy count and a line the broker had seen as a steady base, cost more to service than it earned: 1.6 hours of handling and 0.7 hours of claims support a year for an average of $95 in income. The response wasn't necessarily to drop it. The options the broker modelled were a policy fee on the smallest policies, moving home renewals to a lighter process with less manual work (see automating insurance renewals), or referring new home enquiries elsewhere. The first two together brought the line back to a small positive contribution in the model.
The weak point in any service version is the time estimate. Activity counts are a proxy, and some activities take two minutes while others take an hour. Before acting, sample a week of real timings on the lines that look worst.
Fixed-fee services: a law firm's packaged work
Firms that sell fixed-fee packages have the same question in a simpler form: does the fee cover the time? An illustrative law firm compared its fixed fees with recorded time at an average cost of $120 an hour. Wills at $650 averaged 4.1 hours, costing $492 and leaving a contribution of $158 (24%). Commercial lease renewals at $1,800 averaged 9.5 hours, costing $1,140 and leaving $660 (37%).
The averages hid the useful finding. When the AI split lease renewals by the hours they took, one in five needed more than 18 hours, and those were almost all leases where the landlord's solicitors proposed substantial changes. Those matters lost money; the rest were comfortably profitable. The firm now prices lease renewals in two bands, standard and negotiated, with the band decided once the landlord's draft arrives. For service businesses that price per project rather than per package, tracking profit per project takes the same idea further.
Keeping product margins current
A margin check done once goes stale the next time a supplier, a carrier or a platform changes its prices. Keep the cost inputs in one dated table (landed cost per product, fee rates per channel, shipping rates, packaging cost) and rerun the analysis quarterly, or whenever one of those changes. A short prompt compares runs:
Compare this quarter's product contribution table with last
quarter's (both attached). List products whose contribution
per unit changed by more than 10%, and for each, say which
layer caused it (price, discount, landed cost, fees,
shipping, packaging or returns).
That "which layer" answer is what makes the rerun useful. A falling contribution caused by discounts is a sales decision; one caused by landed cost is a supplier conversation; one caused by returns is a product or description problem. And if a product has also stopped selling, the margin check and the search for dead stock and slow movers will usually point at the same lines.
Product margin questions
What's the difference between gross margin and contribution margin?
Gross margin is price minus the cost of the product itself. Contribution margin also subtracts the costs that rise and fall with each sale, such as payment fees, marketplace fees, shipping, packaging and returns. Contribution is what each sale adds towards rent, salaries and profit, so it's the better figure for deciding which products to push, reprice or drop.
Should I include overheads like rent and salaries per product?
Usually not in the first pass. Spreading fixed costs across products depends on arbitrary allocation rules and can make a useful product look loss-making. Compare products on contribution, then check that total contribution covers your fixed costs. Only allocate overheads when a product clearly uses a separate resource, such as a dedicated warehouse or a person who works on nothing else.
How often should I recheck margins by product?
Quarterly for most businesses, and straight away when a supplier raises prices, a platform changes its fees, or shipping rates change. Those three events move margins more than anything else. Keep the cost table as a separate sheet with dates, so a rerun takes minutes rather than a fresh project.
Further reads
- Break-Even Analysis With AI: A Worked Example for a New Product — Run the numbers on a new product before you launch it.
- How to Build a KPI Dashboard With AI When You Have No Data Team — Track margins alongside other KPIs without a data team.
- How to Use AI to Understand Your Profit and Loss Statement — Read the profit and loss statement your margins feed into.
- How to Compare Supplier Quotes Side by Side With AI — Cut landed costs by comparing suppliers properly.
- Can AI Analyse My Sales Spreadsheet? What to Upload and Check — What to upload and check when AI reads your sales data.
- How to Build a Job Costing Sheet in Excel With AI Help — Cost jobs and custom work, not just catalogue products.
- Can AI Help a Small Shop Set Prices and Promotions? — How a small shop can use AI to test promotions against its own margins before running them, with the break-even maths and a pharmacy example worked through.
- How Landscapers Use AI to Stop Underpricing Jobs — Find where your quotes leak money, price from your true cost per crew hour, fix the markup-versus-margin gap and let AI check each quote for forgotten items.
- Eight Practical AI Uses for an Independent Optician — Recalls, enquiries, plain-English prescriptions, lens reorders, frame copy, reviews, referral letters and stock: how each works in a small practice.
- Can a Small Online Shop Use AI to Compete With Bigger Brands? — Compete through clearer product choices and dependable service, with a practical AI trial and an honest margin calculation.
- How to Automate Monthly Management Reports With AI — Build a monthly pack that refreshes from your accounting exports, flags material variances by formula and gets a first-draft commentary from AI, with checks.
- Budget vs Actual: How to Explain Monthly Variances With AI — A materiality rule, price and volume splits, a context-notes template and an AI prompt, worked through a craft brewery's month line by line.
- How to Get Your Records Ready to Sell Your Business, With AI — Get your accounts, contracts, stock and staff records buyer-ready over 12 to 24 months, using AI to index, summarise and spot the gaps.
- AI Tools and AI Development: The Complete 2026 Guide — the AI hub, including every tutorial in the AI-for-business series.
Sources: Shopify help pages (profit reports, including Gross profit by product; profit reported only for products with a cost recorded at the time of sale; cost per item is static). All business figures are illustrative.