Carrier for Craft CMS

Configuration

Carrier splits its settings in two. Anything that belongs to one carrier account lives on its connection — see Connections. What is left is on the plugin's settings screen, because it should be true of every carrier you ship with.

Carrier → Settings (or Settings → Plugins → Carrier). Plugin settings hold no credentials, so they go through project config like any other plugin's.

Packing

SettingDefault
packingStrategyboxesHow line items become parcels: boxes, single (everything in one parcel) or perItem (one parcel per unit). A checkout method can override it
boxesnoneYour cartons: name, length, width, height, empty weight and max weight, in the store's own units. The packer tries the smallest that fits first
defaultItemWeight0Weight assumed for a product with none, in store weight units. 0 sends what the product says, even if that is nothing

With boxes chosen and no boxes defined, Carrier packs everything into one parcel. See Checkout methods for how each strategy works and where it falls short.

Addresses

SettingDefault
phoneFieldblankHandle of a custom field on the address layout that holds a phone number
houseNumberFieldblankHandle of a separate house-number field, if your address form collects one
defaultCallingCodeblankCompletes local numbers: 385 turns 091 234 5678 into +385912345678

Commerce 5 addresses have no phone number. Most carriers need one for delivery texts, and GLS refuses parcel-shop and locker parcels without one. Add a plain text field to the address field layout (Settings → Addresses), make sure your checkout fills it in, and put its handle here.

Several European carriers want the house number apart from the street. Without houseNumberField, Carrier splits it off the street line: "Ilica 242a" becomes "Ilica" and "242a", and "12 Main Street" becomes "Main Street" and "12".

Customs

SettingDefault
hsCodeFieldblankHandle of a field holding an HS tariff code
originCountryFieldblankHandle of a field holding the country of origin
defaultOriginCountryblankTwo-letter fallback country of origin

Used only for international shipments. Carrier reads each field from the variant first and falls back to its product, so put the field on whichever you prefer.

Checkout

SettingDefault
rateCacheMinutes15How long a live rate is reused for an unchanged cart. 0 asks the carrier every time
requirePointOnPaymentonRefuse payment on a pickup-point method until the customer has chosen a point
codGatewaysnonePayment gateways that mean "the customer pays the courier"

Every cart page view would otherwise be a paid API call; USPS allows about 60 an hour by default. The cache is keyed on everything that can change a price — every line's quantity, weight and dimensions, the destination, the currency and the method's own settings — so a changed cart is always re-priced.

An order paid through a gateway in codGateways ships with cash on delivery for its outstanding balance, on carriers that support COD. A Commerce Manual gateway named "Cash on delivery" is the usual way to offer it. See Labels.

After the order

SettingDefault
autoLabelOnCompleteoffBuy the label as soon as an order is completed, for orders on a Carrier method
orderStatusOnLabelblankOrder status to move an order to when its label is bought. Blank leaves it alone
orderStatusOnDeliveredblankOrder status to move an order to when every shipment on it has been delivered

Automatic labelling is always queued, never done inside the checkout request: a carrier having a slow afternoon must not delay a customer's confirmation, and one being down must not fail a sale.

autoLabelOnComplete is off by default because a label costs money, and that should be a decision.

A status change writes a message to the order history ("Label created with GLS.", "Delivered.") and sends whatever emails that status is set up to send. A status email that fails never undoes a label.

Tracking

SettingDefault
trackingEnabledonPoll carriers for tracking
trackingIntervalHours4Hours between polls for a shipment in motion. Slows down as a shipment ages
trackingMaxDays45Stop polling a shipment this many days after its label, delivered or not
pointsSyncHours24Re-sync list-mode pickup points after this many hours

See Tracking for the schedule.

Housekeeping

SettingDefault
labelRetentionDays120Delete label files after this many days. The shipment record and its tracking are kept. 0 keeps them forever
logRequestsonRecord carrier requests in the log at all
logErrorsOnlyoffOnly record failures
logBodiesonRecord request and response bodies. Bodies are the useful part, and also the large part
logRetentionDays30

Labels carry a customer's name, address and phone number, so they are not kept forever by default. Both kinds of pruning run with Craft's garbage collection.

A log write never causes a purchase or a poll to fail. Secrets are removed before anything reaches the log.

Overriding settings from config/carrier.php

Craft merges a plugin's config file over its saved settings, and Carrier's settings work that way. Create config/carrier.php and return any of the settings above. Values in the file win over the settings screen, and Craft's multi-environment syntax works:

<?php

use craft\helpers\App;

return [
    '*' => [
        'packingStrategy' => 'boxes',
        'boxes' => [
            ['name' => 'Small', 'length' => 30, 'width' => 20, 'height' => 10, 'tare' => 0.1, 'maxWeight' => 5],
            ['name' => 'Large', 'length' => 60, 'width' => 40, 'height' => 40, 'tare' => 0.4, 'maxWeight' => 20],
        ],
        'phoneField' => 'phone',
        'defaultCallingCode' => '385',
        'codGateways' => ['cashOnDelivery'],
        'orderStatusOnLabel' => 'shipped',
        'orderStatusOnDelivered' => 'delivered',
    ],
    'dev' => [
        // Never buy a label because a test order was completed locally.
        'autoLabelOnComplete' => false,
        'trackingEnabled' => false,
    ],
    'production' => [
        'autoLabelOnComplete' => App::parseBooleanEnv('$CARRIER_AUTO_LABEL') ?? false,
    ],
];

Box dimensions and weights are in the store's own units, as set in Commerce, the same as on the settings screen.

Connections and checkout methods cannot be set here. They are stored in the database on purpose — see Connections.

Permissions

Carrier registers its own permissions, so a packing-bench user can print labels without being able to see credentials:

  • View shipments and labels — the Shipments screen, the order panel, printing
    • Buy labels — buy, retry, record a shipment made elsewhere, Create shipping labels
    • Void labels and resolve problems — void, mark voided, settle uncertain purchases
    • Request collections and close the day
  • Manage checkout methods
  • Manage carrier connections and pickup points — includes syncing and importing points
  • View the carrier log

The settings screen needs an admin, and allowAdminChanges on.