What this example is
Everything here is synthetic. The products, costs, prices and rates are invented, and the example shows how the arithmetic works. It is not a pricing recommendation and does not show what any real product should cost.
The script and its output
The script uses whole pence only, a payment fee of 2.5 percent plus 20 pence, a returns allowance of 3 percent and a minimum margin of 20 percent. It was run on Node.js on 12 October 2026 and printed exactly what is shown. Two rows are below their floor: a cushion cover priced 19 pence under, and a gift bundle priced when its parts cost less.
If the matrix is wider than the box, scroll horizontally to read every column. Keyboard: focus the matrix and use Left/Right.
// Synthetic example. All names, costs and prices are invented. Money is in pence (whole numbers).
const FEE_PCT = 25; // 2.5% payment fee, in tenths of a percent
const FIXED_FEE = 20; // 20p fixed fee per order
const RETURNS_PCT = 30; // 3.0% returns allowance, in tenths of a percent
const MARGIN_PCT = 200; // 20.0% minimum margin, in tenths of a percent
const KEEP = 1000 - FEE_PCT - RETURNS_PCT - MARGIN_PCT; // 745 out of every 1000
// floor = (landed cost + fixed fee) / 0.745, rounded up to the next penny, using whole numbers only
const floor = cost => Math.floor(((cost + FIXED_FEE) * 1000 + KEEP - 1) / KEEP);
const gbp = p => (p / 100).toFixed(2).padStart(7);
const products = [
['T100', 'Canvas tote', 410, 1299],
['M101', 'Enamel mug', 520, 1099],
['C102', 'Linen cushion cover', 880, 1190],
['W103', 'Wool throw', 2150, 3995],
['S104', 'Candle, small', 310, 650],
['S105', 'Candle, large', 690, 995],
['N106', 'Notebook A5', 180, 450],
['P107', 'Pen set', 340, 599],
['L108', 'Clay planter', 760, 1099],
];
// A bundle's cost is the sum of its parts' costs. Its price was set before the parts' costs rose.
const bundle = ['B109', 'Gift bundle (tote, mug, notebook)', 410 + 520 + 180, 1499];
products.push(bundle);
let below = 0;
console.log('sku name cost price floor gap status');
for (const [sku, name, cost, price] of products) {
const f = floor(cost), gap = price - f, bad = gap < 0;
if (bad) below++;
console.log(`${sku} ${name.padEnd(34)} ${gbp(cost)} ${gbp(price)} ${gbp(f)} ${((gap < 0 ? '-' : '+') + (Math.abs(gap) / 100).toFixed(2)).padStart(6)} ${bad ? 'BELOW FLOOR' : 'ok'}`);
}
console.log(`rows read ${products.length} = below floor ${below} + clear ${products.length - below} + unchecked 0`);
// Printed on 12 October 2026:
// sku name cost price floor gap status
// T100 Canvas tote 4.10 12.99 5.78 +7.21 ok
// M101 Enamel mug 5.20 10.99 7.25 +3.74 ok
// C102 Linen cushion cover 8.80 11.90 12.09 -0.19 BELOW FLOOR
// W103 Wool throw 21.50 39.95 29.13 +10.82 ok
// S104 Candle, small 3.10 6.50 4.43 +2.07 ok
// S105 Candle, large 6.90 9.95 9.54 +0.41 ok
// N106 Notebook A5 1.80 4.50 2.69 +1.81 ok
// P107 Pen set 3.40 5.99 4.84 +1.15 ok
// L108 Clay planter 7.60 10.99 10.47 +0.52 ok
// B109 Gift bundle (tote, mug, notebook) 11.10 14.99 15.17 -0.18 BELOW FLOOR
// rows read 10 = below floor 2 + clear 8 + unchecked 0What was and was not exercised
Exercised: the floor arithmetic, the rounding up, the check against a price and the reconciliation of rows read, below floor and clear, by running the script. Not exercised: real costs, real fees, marketplace rules, taxes or any price change in a store. Your own rates, rounding and bundle rule may differ.
Sources and limits
- Shopify Community: how do you handle it when a competitor undercuts your price Checked 2026-10-12.
- A poster on 15 Aug 2026 says to set a floor from landed cost plus the minimum margin you will accept; another on 17 Aug adds payment fees and expected returns.
- Shopify Community: Shopify bundles will silently sell at the wrong price Checked 2026-10-12.
- A poster on 5 Sep 2026 says that if a bundle is missed in the manual updates, the bundle will be sold at an incorrect price.