Some products can't have a price tag. A curtain made for a 285 cm window costs more than one made for a 200 cm window. A scoop of coffee beans costs whatever the customer weighs out. A banner costs what its area costs.
Shopify can sell all of these, but its normal tools expect a fixed price per variant. If you're wondering how to price a product by size in Shopify, this post shows how to let the customer type in their size or weight and get a calculated price instead. The worked example is a pair of made-to-measure curtains, built and tested in Live Product Options (LPO) so the numbers below are real outputs, not guesses.
The short answer
| If the price depends on | What you set up | In Live Product Options |
|---|---|---|
| Width and height (area) | The customer types both, a formula returns the price | A Dimension option with a Price formula |
| Weight or length (grams, metres) | The customer types one number, price is number times rate | A Number option with a price formula such as price * options.value('number'), the pattern shown in the docs |
| Several choices at once (size, fabric, lining) | One formula reads all the choices and returns the total | A price formula that reads other options, plus a Price summary |
Price formulas need the Formula extension on your LPO plan (price formula docs, checked 1 October 2026). The docs don't list which plans include it, so check the Plans page in the app.
You don't have to write the formula yourself. You can describe the pricing rule to the AI Assistant, hand it your pricing spreadsheet, or connect Claude or ChatGPT through MCP and ask for it. That is covered below.
What formula pricing is
Formula pricing means the price is calculated from what the customer enters, instead of picked from a list.
For a banner it can be as small as area * 2.50. For a curtain it can be fifteen lines that work out how many widths of fabric you need, how long each one is, and what the lining and labour add. The rule is the same either way: the customer types numbers, the store does the arithmetic, and the total updates on the page before they add to cart.
Why variants stop working
The usual first idea is to make a variant for every size. It breaks quickly.
Shopify raised the limit to 2,048 variants per product on 15 October 2025 (Shopify changelog), and each product can have up to three options (Shopify Help Center, checked 1 October 2026). That sounds like plenty until you do the sum.
A curtain that can be 60 to 600 cm wide and 50 to 350 cm long is 541 widths times 301 drops, which is 162,841 combinations at 1 cm steps. Even if you only allow 5 cm steps it is 109 times 61, which is 6,649 variants. That's more than three times the limit, and it is before you add fabric, lining or heading style.
Weight has the same problem. A "sold by the gram" product would need a variant for every gram someone might want.
How it helps your store
We don't have conversion or revenue numbers for formula pricing, and we won't make any up. What follows is how it changes the buying experience and your workload, and why those changes tend to matter. Read each point as a reason to test it on your own store, not as a measured result.
- The customer sees the price at the moment they decide. With "email us for a quote", the buyer has to wait for an answer, and some will go to a shop that shows a price straight away. A live price removes that wait. This is reasoning, not data.
- Less back and forth. Every quote request is an email thread: what size, which fabric, which lining, then a price, then a revision when they change their mind. A formula answers those questions on the page, in the customer's own time, so you stop being the calculator.
- Fewer wrong orders and returns. Minimum and maximum limits stop sizes you can't make from reaching the cart. The size the customer entered is saved with the option as readable text (the preview shows "285 cm wide x 220 cm drop"), so whoever makes the product reads the exact request instead of interpreting an email.
- No more under-quoting. The formula applies your cost rules every time: whole widths of fabric, a minimum charge, a setup fee. A quote done by hand at the end of a long day can miss the one step that costs you money.
- Customers can see what each choice costs. When velvet, blackout lining or a fuller heading changes the total as they click, they can make their own trade-offs and see where the extra money goes. That may make a higher option easier to choose. We haven't measured it.
- A bigger catalog. Made-to-measure, cut-to-length and by-weight products become normal product pages, so you can list more of what you can actually make.
Most of this is about two things: fewer steps between "interested" and "bought", and fewer hours spent answering the same questions. Whether that shows up as more sales depends on your store, so run it on one product first and compare against your own numbers.
Meet Live Product Options
Live Product Options adds option fields to a product page and can price them. These are the pieces this post uses, all checked in the app on 1 October 2026:
-
Dimension option. Two inputs, width and height, with your own labels and unit text (such as cm), minimum and maximum limits, and step buttons. Inside a price formula you can use
x,yandarea. - Price formula. JavaScript. It can read the other options on the page by name, so one formula can react to fabric, fullness, lining and anything else.
- Swatch options. Button swatches for short text choices and image swatches for choices that look different, like fabric.
- Price summary. Shows the total, and the line items behind it, to the customer.
LPO's reference notes one limit worth knowing early. A price formula runs on the product page and the price is locked in when the customer adds to cart. It does not recalculate if they change quantity in the cart.
Everything you can price in LPO
A formula is one tool of several. Most products need a mix, so here is the full set, checked against LPO's reference and docs on 1 October 2026.
| Pricing tool | What it does | Example |
|---|---|---|
| Fixed price | Adds a set amount when a choice is picked | Gift box, +$15 |
| Percentage | Adds a percentage of the product's base price | Premium material +25%, rush order +20% |
| Per character | Charges per letter typed. Text options can set a minimum character count before pricing starts, and leave some characters (such as spaces) out of the count | Engraving at $1.50 a letter |
| Upload price | Adds a price when a file is uploaded | A setup fee for customer artwork |
| Linked Shopify variant | Takes the price from a variant of another product and can add it to the cart with the main product: once per cart, in step with the quantity, or in a quantity the customer picks | Gift wrap, a protection plan |
| Price formula | JavaScript on an option value or a Dimension option. Reads other options, width, height and area, quantity, the Shopify variant and price lists | The curtains in this post |
| Price list | Looks the price up from a table, either by area (one column) or by width and height (a grid). Linked to a Dimension option, it applies by itself when the formula box is empty | A blinds price grid |
| Quantity discount | Tiered "buy more, save more" discounts. They run through a Shopify checkout function, so they update in the cart. Tiers can count area or pages instead of items | Wholesale tiers |
| Value formula | Calculates a value, not a price, from other options. Use it in conditions or to keep a number on the order | Area, to show an extra option on large sizes |
| Price summary | Shows base price, add-ons and total, with an optional line of text | "Base {base} + options {addon} = {total}" |
Price formulas, price lists and value formulas need the Formula extension. Quantity discounts need the Quantity extension, and a custom discount formula needs both. The other rows aren't listed as needing an extension.
What a formula can read and do
A price formula is plain JavaScript, so anything you can calculate with Math works: rounding up with Math.ceil, a minimum charge with Math.max, tiers with if. On top of that, LPO gives the formula these helpers (price formula docs):
-
Other options by name:
options.value('fabric')reads the current choice, andoptions.price('name')reads what another option currently costs. -
Size:
x,yandareainside a Dimension formula, oroptions.controller('size').areafrom another option. You can change how area is calculated, for example to turn cm into square metres withx/100 * y/100. -
Quantity:
options.quantity(). -
The Shopify variant:
options.variant()gives the selected variant's price and title. -
Price lists:
lookup(area)orlookup(x, y)on a linked list, andoptions.list()withoptions.lookup()to pick a different list for each material. - Your own data: a list can hold JSON, so a formula can read rates you keep in one place.
-
Messages and weight:
options.error('name', 'message')shows a validation message on an option, andoptions.weight()updates an option's weight. -
Debugging:
console.debug()prints values while you build.
Some examples straight from LPO's own library: the outdoor banner template uses area * 2.50, and the vehicle decal template uses Math.max(area * 11.52, 5), which is a rate per square foot with a $5 minimum.
There are also display settings. You can show the calculated price on the option or on its label, and change how it reads with a template such as +( {price}). A Deduct variant price setting subtracts the Shopify variant's price from the formula result, which helps when your variants already carry a base price.
Limits worth knowing
- A formula returns the price per unit. If it uses the quantity, divide the total by the quantity before you return it.
- It runs on the product page and locks in when the customer adds to cart. Changing quantity in the cart does not re-run it. For tiers that update in the cart, use the Quantity discount option.
- If a Dimension option has both a formula and a linked price list, the formula wins. Leave the formula empty to let the list apply.
- A price list must exist before you save a formula that uses it.
- Formulas calculate in your store's base currency. If you read a variant price, convert it, because the variant price comes back in the shopper's currency.
For a grid rather than a formula, such as a blinds price table with width down one side and height across the top, use a price list (price lists docs). The rest of this post sticks to formulas.
You don't have to write the formula yourself
All that JavaScript can sound like a job for a developer. It isn't one, because you don't have to write it. There are three easier routes.
1. Tell the AI Assistant what you want
Click the AI button in the bottom right corner of the app. The AI Assistant sets up product options from a plain description of what you sell, and it is available on all subscription plans (AI Assistant docs).
Describe the pricing rule the way you'd explain it to a new employee: what the customer enters, what each choice costs, and any minimum. Ask it for the price formula.
Already have the rules in a spreadsheet? Save it as a CSV and attach it. The assistant accepts .csv, .json and .txt files, which the docs describe as a way to import option data or show it an example of what you want. Tell it to turn your pricing sheet into a price formula.
2. Connect Claude or ChatGPT through MCP
If you already work with an AI tool, you can connect it to the app directly. Open Settings in LPO, find the MCP Server section, enable it, and follow the steps for your tool. Any up-to-date AI tool that supports MCP can connect, with Claude and ChatGPT the most common (MCP docs).
Once connected, you ask in plain language and the AI builds in your editor. LPO's MCP reference lists price formulas among the things it can set up, along with options, conditions and the live preview. It works on a draft. Switching a configuration to Active is something only you can do in the app, so nothing goes live until you say so.
A request can be as simple as this:
I sell made-to-measure curtains. The customer enters track width and drop in cm, then picks fullness (1.5x, 2x or 2.5x), a fabric, a heading style and a lining. Fabric comes on a 140 cm roll and is priced per metre: cotton linen $18, velvet $34, sheer voile $12. Each panel needs half the track width times the fullness, rounded up to whole widths, and a pair is two panels. Cut each width to the drop plus a heading allowance plus 20 cm for the hem. Add heading labour and lining per width, and a $45 making charge per pair. Build the options and the price formula.
That is the same rule set as the worked example below, written as a brief instead of code.
3. Start from a template
LPO's template library includes configurations that already use formulas, such as the outdoor banner and the vehicle decal. Copy one that is close to your product and change the numbers. You can also ask the AI to adapt it.
Check what the AI gives you
Whichever route you take, test the result before you trust it. AI tools make arithmetic mistakes and misread rules like "rounded up", which is exactly where made-to-measure pricing goes wrong.
Do what the tested prices table below does. Pick three or four cases, work each price out by hand, and compare. Include a case just above a rounding step and a case at your minimum size. If the numbers match, you can trust the formula. If they don't, tell the AI which case is wrong and what the answer should be.
Example: made-to-measure curtains
Curtain makers price curtains by how much fabric a window needs. The usual method multiplies the track width by a fullness factor, divides by the width of the fabric roll (140 cm in the example), and adds hem allowance to the drop. Lining is priced per width, and the making charge is a flat amount per pair (Custom Price Calculator's curtain guide).
That guide doesn't say how to treat a fraction of a width. You can't buy part of a width, so my formula rounds up. That "jumps in whole steps" behaviour is exactly what a simple rate times area can't do.

The product image was generated with ChatGPT.
The rules I priced
These rates are made-up demo values, not real market prices. Swap in your own.
- Each panel covers half the track width, multiplied by fullness (1.5x, 2x or 2.5x).
- Fabric comes on a 140 cm wide roll. Widths per panel are rounded up, then doubled for the pair.
- Each width is cut to drop + heading allowance + 20 cm hem. The heading allowance is 10 cm for eyelet, 15 cm for pencil pleat, 25 cm for pinch pleat.
- Fabric costs $18 per metre for cotton linen, $34 for velvet and $12 for sheer voile.
- Heading labour is $4, $6 or $9 per width. Lining is $0, $5 or $9 per width.
- A $45 making charge applies to every pair.

The three fabric swatches were also generated with ChatGPT.
How it is built in LPO
- Create the product in Shopify and set its price to $0. The formula supplies the whole price.
- In LPO click New Product Options and pick that product.
- Add a Dimension option named
window_size. Label the inputs "Track width" and "Drop", set the unit to cm, and set the limits to 60 to 600 wide and 50 to 350 long. - Add four swatch options named
fullness,fabric,headingandlining. Makefabrican Image swatches option with one image per fabric. The names matter, because the formula reads them. - Open the Dimension option's Advanced tab and paste the price formula below into Price formula.
- Add a Price summary option so the customer sees the total.
- Test in the preview, check the numbers by hand, and leave the configuration on Draft until you have tried it on your storefront.

The formula
// customer inputs: x = track width (cm), y = drop (cm)
var fullness = parseFloat(options.value('fullness')) || 2;
var fabric = options.value('fabric');
var heading = options.value('heading');
var lining = options.value('lining');
// fabric price per metre
var perMetre = 18;
if (fabric === 'velvet') perMetre = 34;
if (fabric === 'sheer_voile') perMetre = 12;
// heading style: extra fabric length (cm) and labour per width
var headingCm = 10;
var headingLabour = 4;
if (heading === 'pencil') { headingCm = 15; headingLabour = 6; }
if (heading === 'pinch') { headingCm = 25; headingLabour = 9; }
// lining cost per width
var liningPerWidth = 0;
if (lining === 'standard') liningPerWidth = 5;
if (lining === 'blackout') liningPerWidth = 9;
// widths of fabric needed for the pair (usable roll width 140 cm)
var rollWidth = 140;
var widths = Math.ceil((x / 2 * fullness) / rollWidth) * 2;
// cut length of one width in metres: drop + heading + 20 cm hem
var cutMetres = (y + headingCm + 20) / 100;
var fabricCost = widths * cutMetres * perMetre;
var labour = widths * (headingLabour + liningPerWidth);
var makingCharge = 45;
return Math.round((fabricCost + labour + makingCharge) * 100) / 100;
Two details. In a dimension formula, x, y and area are provided for you, so don't declare variables with those names (LPO's reference). And the formula's result shows in the preview as an add-on on top of the product's own price, which is why I set the product's base price to $0 and the total equals the formula result.

The tested prices
I ran four windows through the editor preview and checked each one against the formula by hand.
| Window | Choices | Widths | Cut length | Fabric | Labour | Making | Price |
|---|---|---|---|---|---|---|---|
| 200 x 220 cm | Cotton linen, 2x, pencil pleat, no lining | 4 | 2.55 m | $183.60 | $24.00 | $45 | $252.60 |
| 200 x 220 cm | Velvet, 2.5x, pinch pleat, blackout | 4 | 2.65 m | $360.40 | $72.00 | $45 | $477.40 |
| 280 x 220 cm | Velvet, 2x, pinch pleat, blackout | 4 | 2.65 m | $360.40 | $72.00 | $45 | $477.40 |
| 285 x 220 cm | Velvet, 2x, pinch pleat, blackout | 6 | 2.65 m | $540.60 | $108.00 | $45 | $693.60 |
The preview showed exactly these totals.

Watch the step
The last two rows are the interesting ones. Making the window 5 cm wider, from 280 to 285 cm, raised the price by $216.20.
That is not a bug. At 280 cm and 2x fullness, each panel needs exactly two widths of fabric. At 285 cm it needs a little over two, so you have to buy a third. A flat rate per square metre would have shown a tiny increase and left you out of pocket.

If you don't want customers surprised by the jump, say so in the help text under the size field, or round your allowed sizes to steps.
More products that fit the same pattern
I only built and tested the curtains. The rows below are patterns that use the same pieces, with the maths from each source. Treat them as starting points to test, not finished configurations.
| Product | The customer enters | The idea behind the price | Source for the method |
|---|---|---|---|
| Garden soil, mulch or gravel | Length, width, depth | Cubic yards are length x width x depth in feet, divided by 27. Add roughly 5 to 10% on top, then multiply by the price per yard | size.ly |
| Bulk goods and ingredients (coffee, spices, tea) | Weight | Weight times the price per kilo or pound | Custom Price Calculator lists weight pricing for bulk goods and ingredients |
| Screen-printed t-shirts | Quantity, number of print colours | A setup fee per colour spread across the quantity, plus a per-shirt price that falls at higher quantities | Printable Press |
| Banners and signs | Width, height, material | Area times a rate per square metre. LPO's outdoor banner template uses area * 2.50 with the area converted from cm to m² |
LPO template library |
For the t-shirt case, LPO's reference shows a formula that reads the quantity and spreads a setup fee across it. The same limit applies: the price is calculated on the product page and is not recalculated if the quantity changes in the cart.
Mistakes to avoid
- Hard-coding rates in the formula. It works, but every price change means editing code. Keep the rates at the top of the formula in clearly named variables, as in the curtain example, so the edit is one line.
- Trusting a formula you didn't test, whether you or an AI wrote it. Work two or three examples out by hand, like the table above, before you go live.
- Forgetting the limits. Set minimum and maximum sizes you can actually make.
- Going live before checking the storefront. The editor preview is not your theme. Add the LPO block to your product template, switch the configuration to Active only when you are happy, and test as a customer.
- Letting the base price confuse people. If the product's own price is $0, think about how it shows on collection pages and in search results.
Frequently asked questions
Do I need to write code? No. Describe your pricing rule to the AI Assistant, upload your pricing spreadsheet as a CSV, or connect Claude or ChatGPT through MCP and ask for it. If you'd rather write it yourself, the price formula is JavaScript in a text box, and the price formula docs include examples you can adapt, such as tiered pricing by area. Either way, check the result against a few prices you worked out by hand.
Can the customer see the price before they add to cart? Yes. Add a Price summary option and it shows the total and the line items as they choose. In the curtain example the total updated each time I changed the size or any swatch.
What if my prices come from a table, not a formula? Use a price list. LPO supports one-dimensional lists by area and two-dimensional tables by width and height (price lists docs).
Does it recalculate in the cart? No. A price formula is calculated on the product page and locked in when the customer adds to cart, so changing the quantity in the cart does not re-run it (LPO's reference).
Try it on your own product
Pick the one product in your store where you currently say "email us for a quote". Write its pricing rule down in plain words, or in the spreadsheet you already use. Then give it to the AI Assistant, or to Claude or ChatGPT over MCP, inside Live Product Options. Start with a Dimension option and one simple rule, test it against a few hand-worked prices, then add the choices one at a time.
Facts about Live Product Options in this post were checked in the app and its documentation on 1 October 2026. Rates, product images and prices in the curtain example are demonstration values.
