Weight for Craft CMS

Carriers & Postie

Carrier rate presets

Weight ships importable starting points for the rate structures the common carriers actually use:

php craft weight/presets                       # list them
php craft weight/presets/show royal-mail-uk    # print one without importing
php craft weight/presets/import royal-mail-uk  # create its methods, disabled
PresetStructure it encodes
royal-mail-ukSize class, then flat price per weight band. The clearest example of bands that replace each other rather than accumulate
ups-ground-usZoned base rate plus a continuous per-pound charge, dimensional weight at divisor 139, residential fee, fuel as a percentage
fedex-home-usThe same family, with FedEx's breakpoints
usps-priority-usBoth USPS structures: flat-rate boxes, where the price comes from the box and weight is irrelevant, and retail Priority in whole pounds
dhl-express-intlMetric and stepped — half-kilo increments, divisor 5000, priced by destination zone rather than by country
australia-post-auZone and band, with a flat-rate satchel tier and a continuous tier on the same method

Every amount in them is a placeholder

They are not published rates, they are not quotes, and they are not maintained against anybody's price list. Shipping real carrier pricing would be republishing someone else's copyrighted rate card, and it would be wrong within a quarter — a stale table undercharges at checkout, which costs the merchant real money on every order.

What is worth having is the shape: where the breakpoints fall, whether the carrier bills continuously or in whole steps, whether there is a free allowance, which surcharge is a flat fee and which is a percentage, and what the dimensional divisor is. That part is tedious to work out and changes rarely. The numbers are the part you already have, on your own contract.

So every preset method is created disabled, with a description saying so, and an accidental import cannot start quoting invented prices at checkout.

Units are not converted

A preset is written in one carrier's units — royal-mail-uk in kilograms and centimetres, ups-ground-us in pounds and inches. Commerce stores weights in whatever weightUnits says, and the importer does not convert.

Importing a kilogram preset into a store configured in grams produces a rate table that is wrong by a factor of a thousand and looks entirely plausible: every band is populated, every number is round, and only the unit in the ladder's column header gives it away. The importer therefore checks the store's units against the preset's and says so before it writes anything.

To retarget one, print it, edit it, and import it as an ordinary config file:

php craft weight/presets/show ups-ground-us > mine.json
# ...convert the numbers, put your contract rates in...
php craft weight/methods/import --file=mine.json

Importing twice replaces rules

presets/import matches on handle, exactly as methods/import does, so a second import updates the method and replaces its rules. Export first if you have edited them:

php craft weight/methods/export --file=before.json

Running alongside Postie

Postie fetches live rates from carrier APIs. Weight computes a table. They solve adjacent problems, and a store running both hits two things neither plugin can fix alone. Weight fixes both, automatically, as soon as it sees Postie installed — there is nothing to switch on.

They no longer disagree about parcels

Postie packs from a box list configured per provider. Weight packs from its own library, which has tare weights and packaging costs Postie has no field for. Two libraries drift, and the drift is invisible: the simulator shows you three parcels while the carrier is being asked to price two.

Where Weight has boxes in its library, they drive Postie's packing. Postie still does the packing, with its own packer and the same algorithm — it just takes its boxes from one library instead of two. A store with no Weight boxes is left exactly as Postie found it.

A table rate can be a backstop instead of a competitor

When a carrier API is down, or the credentials expired, or the address is unserviceable, Postie registers no shipping methods — and a checkout with no shipping options cannot complete. Weight's methods are always there, which makes a fine safety net and a poor default: a table rate should not sit next to a live rate all day competing with it.

A rule can now ask what the carriers said. On the rule screen, under Carrier rates:

This rule applies
Don't askThe default. Behaves exactly as it did before
Only when no carrier rate came backA real backstop — offered only during an outage
Only when a carrier rate came backThe opposite: a handling surcharge that rides along with a live rate

The section only appears when Postie is installed.

Before the cart has an address, the carriers have not answered. That is not the same as an outage, and Weight distinguishes the two — but it treats it as "no rate", so a backstop is offered rather than hidden. This is deliberately the opposite of how a condition-builder rule that throws is handled: an erroring rule fails closed, because a wrong price is worse than no price, while a backstop whose state is unknown fails open, because a checkout with one shipping option too many is recoverable and a checkout with none is not.

The simulator shows which of the three states applied, in the rule's trace, alongside every other condition.

What it does not do

Weight does not edit Postie's prices. A carrierRates rule changes whether Weight's own method is offered; it never adds to, discounts, or overrides what a carrier quoted. If a total looks wrong, exactly one plugin computed it, and the simulator will tell you whether that was this one.

Trademarks

Carrier and service names are used here and in the presets only to identify the rate structure each one mirrors. Weight is an independent plugin and is not affiliated with, endorsed by, or sponsored by any carrier, or by Verbb. See the note in the footer.