Normalising a unit price means converting every offer to the same base unit, price per litre, per kilogram, per metre, per tablet or per 1,000 pieces, before comparing anything. The formula is trivial. Extracting the pack size and pack count from a page that was not written for you is the actual work.
A second rule matters just as much: some pairs cannot be normalised into comparability at all, and forcing them produces a number that looks rigorous and is wrong.
The formula, and four worked examples
Unit price equals total price divided by pack count multiplied by content per pack, with content expressed in the base unit.
- Wine: a case of six 0.75 litre bottles at 89.40 euro. Six times 0.75 is 4.5 litres, so 89.40 divided by 4.5 is 19.87 per litre, and 89.40 divided by six is 14.90 per bottle. Both are useful and they answer different questions.
- Household goods: 1.5 litres at 4.49 euro is 2.99 per litre. A competitor's 2 litre pack at 5.79 euro is 2.90 per litre. The larger pack is about 3 per cent cheaper per litre, which is invisible if you compare 4.49 against 5.79.
- Pharmacy: 100 tablets at 12.90 euro is 0.129 per tablet. A 30 tablet pack at 4.95 euro is 0.165 per tablet, roughly 28 per cent dearer per tablet. They still remain separate products, because a customer who wants thirty will not buy a hundred.
- Construction: a box of tiles covering 1.44 square metres at 38.90 euro is 27.01 per square metre. Against a competitor quoting 25.50 per square metre, they are cheaper by about 6 per cent, not by 13.40.
Where the pack size hides
Ranked by how often the source is reliable, worst last.
- Structured data on the page: JSON-LD, microdata or a supplied product feed. Trust this first and still validate it.
- An attribute table with an explicit content or net quantity row.
- The variant selector, which often holds the only correct size for the option currently selected.
- The title, where most parsers start and most errors begin. 12x0,33l, 12 x 330 ml, 0,33l Dose 12er and 3.96l all describe the same case.
- The description, buried in a sentence, possibly in a language you are not parsing.
- The packshot image, where the size is printed on the label and nowhere else. That is not extractable at scale and belongs in review.
Write the parser to return a value and a source, and never let a title-derived size overrule a structured one.
Units that do not convert cleanly
- Mass against volume. Paint sold by the kilogram and paint sold by the litre need a density to convert, and the density is per product. Do not assume 1.0.
- Net weight against drained weight in food. A 400 gram tin with 240 grams drained is not comparable to a 250 gram pouch on either basis alone.
- Concentrate against ready to use. A one litre concentrate at 1:20 makes 21 litres of working solution, so comparing it to a one litre spray bottle means nothing until you state the basis.
- Coverage claims. Paint quoted at 12 square metres per litre and paint quoted at 8 are not the same product, and both figures come from marketing.
- Fasteners and small parts sold per piece, per 100 and per 1,000, sometimes inside the same catalogue.
- Cable, rope and hose sold per metre against sold per drum, where the drum length varies by production run.
For these, store the raw quantity and the basis, then mark the pair as not comparable rather than inventing a conversion. A blank is honest. A wrong number is not.
Rounding, and where the money leaks
- Hold money in integer minor units, cents or pence, never in floating point.
- Compute the unit price to four decimal places or more and round only at display. Rounding 2.9933 to 2.99 before comparing costs real precision in thin margin categories.
- Keep the base unit per category in one table rather than scattered through the code: litres for liquids, kilograms for solids, pieces for countables, square metres for coverings.
- Store the conversion factor alongside the result. When a pack size is corrected six months later, you want to know what the old number was built on.
The shop's own unit price is a cross-check, not a source
European sellers are generally required to show a unit price next to the selling price for goods sold by quantity, under the Price Indication Directive as implemented nationally. In Germany that is the Preisangabenverordnung. The prescribed base unit varies, and small packs are often shown per 100 grams or per 100 millilitres rather than per kilogram or per litre.
That displayed figure is useful and it is not authoritative. Shops get it wrong, they forget to update it after a pack change, and they pick a base unit different from yours. Parse it, compare it against your own calculation, and raise a flag when the two disagree by more than a few per cent. Disagreement usually means your pack size is wrong, which is worth finding out.
A checklist before you compare two prices
- Same base unit, recorded rather than assumed.
- Pack count and content per pack stored as separate numbers.
- Same tax basis, net or gross, on both sides.
- Same currency, with the conversion date recorded.
- Delivery handled consistently, included on both sides or excluded on both.
- Minimum order quantity captured, because a per unit price at 500 units is a different offer.
- A flag on pairs that cannot be normalised, so nobody quietly compares them anyway.
Why this is worth the effort
Unit price normalisation is unglamorous and it is where a surprising amount of margin gets defended. Most of the time the competitor who looks cheaper is selling a different quantity, and the discount you were about to give was never needed. Checking the arithmetic first is cheaper than finding it in the quarter's gross margin.