Skip to content
NewMy Claude Code sessions now say which project they are
Nov 4, 2026·4 MIN READ
Shipping per item on Shopify Basic, using weight as a price

Shipping per item on Shopify Basic, using weight as a price

Shopify Basic can't ask an app for live shipping rates, so I stored Printful's extra-item price in the variant weight and let weight brackets do the maths. A ten-row simulation showed where it breaks before any code was written.

A client sells print-on-demand merch inside artists' own Shopify stores. Printful prints and ships it, and Printful charges per item: a t-shirt to the US costs $4.95 for the first one and $2.20 for each extra one. The first artist store I set up charged one flat rate per order, so every cart with more than one shirt lost money.

The obvious fix is carrier-calculated shipping: at checkout Shopify asks our app, and we return Printful's live rate for the exact cart. The store is on the Basic plan, and Basic doesn't offer that at all, not even as a paid add-on. So checkout can't talk to us. Whatever we want has to be prepared before the fan opens the cart.

Weight is a free field

Shopify still calculates rates per shipping profile, and a profile can use weight brackets. Printful ships the goods, so the weight on these variants is never used for a real label. That makes it a free number field that Shopify adds up for us.

flowchart LR
    A["Printful rate<br/>first + extra item"] --> B["Variant weight<br/>= extra-item price"]
    B --> C["Cart weight<br/>= sum of extras"]
    C --> D["Bracket<br/>every 0.5 lb"]
    D --> E["Price<br/>top + surcharge"]

Each variant gets a weight equal to its extra-item price, so a t-shirt weighs 2.20 lb. The profile gets brackets every 0.5 lb, and each bracket costs its upper bound plus one fixed surcharge: first minus extra, $2.75 for a t-shirt. We always round up, so the store never charges less than Printful.

Only the merch goes into this separate profile. The artist's own products, like vinyl, keep their own shipping rules, and Shopify adds both prices into one line at checkout.

Ten rows of maths before any code

Before writing a line of code I put the idea in a spreadsheet, with Printful's real t-shirt rates and an estimate for hoodies (first $8.79, extra $2.70), plus the $0.40 holiday surcharge per item. The difference column is what the fan pays minus what Printful charges.

CartWeight lbFan paysPrintfulDifference
1 tee2.60$5.75$5.35+0.40
2 tees5.20$8.25$7.95+0.30
3 tees7.80$10.75$10.55+0.20
1 hoodie3.10$6.25$9.19-2.94
tee + hoodie5.70$8.75$11.79-3.04
2 hoodies6.20$9.25$12.29-3.04

T-shirt carts look great: a few cents over Printful's price. Every cart with a hoodie loses about $3. The reason is the single surcharge. A weight only carries one number per product, but Printful's price has two parts, and the gap between first and extra is $2.75 for a shirt and $6.09 for a hoodie. Raise the surcharge to cover hoodies and shirt carts pay about $3.30 too much.

Put the rule in a spreadsheet with formulas before you build it. Ten rows found the flaw that a happy-path test order would have hidden.

What comes next

The parts that don't depend on this choice can be built now: the app creates the separate profile and adds every synced variant to it, and a small job fetches Printful's real rates daily, so the estimates go away. The surcharge rule waits for a decision with the client. The options are a higher surcharge with some margin on shirts, or folding part of the hoodie's first-item cost into its weight.

The design took an afternoon, and most of the value came from the boring part: a table with formulas and real numbers. Next time I would build that table first, before drawing diagrams, because it answers whether the idea works before anyone falls in love with it.

Share
Mariusz Smenżyk
Written by

Mariusz Smenżyk

Builder for sport. Make. Test. Launch.

Related notes