Configuration
Methods
A method is one shipping option at checkout. Create them under Weight → Methods; each store keeps its own.
| Field | What it does |
|---|---|
| Name | Internal, for the control panel |
| Handle | Unique per store. Commerce sees it as weight-<handle>, prefixed so it can never collide with a Commerce-managed method |
| Customer label | What shoppers see. Falls back to the name |
| Description | Optional supporting line |
| Enabled | A disabled method is never registered with Commerce |
| Sites | Restrict the method to certain sites. Empty means all |
| Rating mode | Rate the cart as a whole, or rate each package and add the results up |
| Packing strategy | How the cart becomes packages — see below |
| Minimum / maximum cost | Clamps the finished price for the whole method |
Rating per package only means something once packing produces more than one package, which is how a per-parcel carrier price gets modelled honestly: two parcels, two base rates.
The rule model
This is the part worth reading twice, because it is the part people assume works the other way.
Rules do not OR. Every matching charge rule contributes to the price. They are evaluated in
sortOrder — the order they appear on the method's screen, which you can drag — and each one is
judged against the package being rated:
disable + matched → method unavailable, stop
required + missed → method unavailable, stop
free + matched → this package costs 0, stop
charge + matched → add the charges, clamp, keep going
stop + matched → stop here
nothing matched → method unavailable
That last line is the hideWhenNoRuleMatches setting, on by default because it is what WooCommerce
does. Turn it off and a method with nothing to charge for is offered at zero instead.
A worked example — four rules on one method:
Handling flat 3.50
First 2kg ≤ 2kg flat 4.50
Above 2kg > 2kg flat 4.50 + 1.20 per 0.5kg over the first 2kg
Free over 75 subtotal ≥ 75 → free
A 6 kg order costs 17.60: 3.50 (handling, always) + 4.50 (the above-2kg band's base)
+ 9.60 (4 kg over the allowance, in eight 0.5 kg steps at 1.20). The First 2kg rule does not
match a 6 kg package, so it contributes nothing — and Free over 75 short-circuits the lot if the
subtotal is high enough.
Note the independent inclusivity on the two weight bands: ≤ 2kg and > 2kg. Exactly 2 kg
lands in the first band and not both, which is the bug every hand-rolled rate table ships with.
What a rule can charge
All four components are added together, then clamped by the rule's own minimum and maximum:
| Component | Notes |
|---|---|
| Flat cost | Charged once whenever the rule matches |
| Cost per unit of weight | See below |
| Cost per item | Times the quantity in the package |
| Percentage of subtotal | Of the package's share of the order subtotal |
The weight component
Only one thing computes it, and it works in this order:
- Subtract the free allowance (
weightFree) from the billable weight. Never below zero. - If step is zero, charge
remaining × cost— continuous. - If step is set, charge
ceil(remaining ÷ step) × cost— whole steps, so a 2.1 kg overage at a 0.5 kg step is five steps, not 4.2.
"Billable weight" is the weight actually being charged for: the packed weight, including the box's own tare weight and any dimensional uplift. Non-shippable line items and items already carrying free shipping are excluded from packing entirely, so they never appear in it.
What a rule can do instead of charging
- Make shipping free — this package costs nothing, and no rule below it runs.
- Make this method unavailable — how "we don't ship anything over 30 kg" is expressed.
- Required — the method is not offered at all unless this rule matches. Use it for "UK addresses only".
- Stop — nothing below this rule is considered once it has matched.
Required and Stop are checkboxes on any rule, so a charge rule can also be the gate.
Conditions a rule can carry
A rule with no conditions matches everything, which is what makes a flat handling fee a one-field job.
| Condition | Detail |
|---|---|
| Weight | A range, with independent inclusivity at each end |
| Subtotal | A range. Optionally after discounts (default) and optionally including tax |
| Quantity | A range, in items |
| Destination | Only these places or everywhere except these — US, GB, US:NC, CA:ON |
| Postal codes | Exact codes, 902* wildcards, and 10000-19999 numeric ranges |
| Shipping categories | Contains any of / only / none of |
| Carrier rates | What Postie's carriers said — see Carriers & Postie. Only shown when Postie is installed |
| Anything else | Craft's condition builder, on the order |
Destination is judged against the order's shipping address — or, while the cart still has none,
against the customer's estimated address if useEstimatedAddress is on.
Condition-builder rules
Everything Craft and Commerce can already ask an order, plus two rule types Weight adds: largest item dimension and distinct item count.
A condition that throws does not take checkout down. It is caught, logged, and fails closed — the rule does not match, and the reason appears in the simulator's trace.
Per-category charges
A charge rule can override its own charge components per shipping category — frozen goods at a higher rate per kilo than dry goods, on the same rule.
A blank override field means "same as the rule". Zero means zero. They are not the same thing, and this is the field where the difference bites.
Packing
| Strategy | What happens |
|---|---|
| Don't pack | One notional package for the whole cart. The default, and what WooCommerce does |
| Split by maximum package weight | No package over the limit you set |
| Pack into boxes | First-fit-decreasing into your box library |
Splitting by weight needs a maximum package weight; the method will not save without one.
Unpackable behaviour decides what happens when an item fits no box: ignore it, or make the method unavailable. Unavailable is the honest setting for a carrier that genuinely cannot take it.
Boxes
Weight → Boxes, one library per store:
| Field | Notes |
|---|---|
| Inner length / width / height | The usable space. All three are required and must be non-zero |
| Maximum contents weight | Blank means no limit |
| Box weight | The empty box's own weight, added to every package that uses it |
| Cost | A packaging surcharge added to the quote per box used |
Dimensional weight
Give a method a divisor and each package is billed on the heavier of its real weight and
length × width × height ÷ divisor. Typical carrier divisors are 5000 (cm/kg) or 139 (in/lb).
Carrier rates
Only present when Postie is installed. It lets a method be a backstop — offered only when every carrier came back with nothing, which is what an API outage looks like from inside a checkout — rather than a table rate permanently competing with a live one. The reverse is available too, for a handling surcharge that rides along with a carrier rate. Full detail in Carriers & Postie.
Plugin settings
Settings → Plugins → Weight, or Weight → Settings:
| Setting | Default | What it does |
|---|---|---|
| Use estimated addresses | On | Judge destination conditions against the customer's estimated address while the cart has no real one |
| Hide a method when no rule matches | On | Off, the method is offered at zero instead |
| Log quotes | Off | Write every quote to the log. Verbose, and worth it the afternoon somebody disputes a shipping charge |
| Amount / quantity / weight remaining message | — | The free-shipping progress strings, with {remaining} |
| Qualifying message | — | Shown once the cart already qualifies |
Where the configuration lives
Methods, rules and boxes are stored in the database, not project config — the same call Commerce makes for its own shipping methods. Moving them between environments is an explicit export and import:
php craft weight/methods/export --file=weight.json
php craft weight/methods/import --file=weight.json # matches on handle
docs/example-config.json in the repository is a working file to start from, and
weight/presets lists importable structures shaped like the common carriers' own — see
Carriers & Postie.