Custom checkout fields

Let merchants add their own questions to checkout — gift message, delivery note, VAT number, preferred delivery time — whose answers persist on the order and surface in the admin order detail, the printable invoice, the CSV export, and (optionally) the order-confirmation page. Fields flagged "send to courier" also feed the courier's delivery note.

This is separate from the page builders: it mints real order data, not layout.

How it works end-to-end

  1. Define — the merchant adds fields in the dashboard (Online Shop → Checkout settings). A theme can ship defaults (see the theme kit at 10-theme-preset-kit/src/themes/custom/checkout-fields/).
  2. Collect — the storefront fetches the shop's active fields and renders them at checkout. Answers are submitted with the order.
  3. Persist — saved on the order as a self-describing snapshot { key, label, type, value }[]. When no fields are entered, the order payload is byte-identical to before (the known-field contract is preserved).
  4. Surface — admin order detail card, invoice block, CSV "Custom Fields" column, and the order-confirmation.details section.

Field definition

{
  "key": "gift_message",
  "label": "Gift message",
  "type": "textarea",
  "required": false,
  "placeholder": "Write a message for the gift…",
  "options": [{ "label": "Morning", "value": "morning" }],
  "sortOrder": 0,
  "active": true,
  "flowToCourier": false
}
Field Meaning
key Stable slug, immutable once orders carry it.
label Shown to the shopper and stored on the order.
type text | textarea | select | checkbox | date.
required Enforced server-side; never weakens the core order contract.
options For select only: { label, value }[].
sortOrder Order on the checkout form.
active Whether it shows at checkout.
flowToCourier Include the answer in the courier delivery note.

API

Per shop, JWT-scoped (merchant):

  • GET v1/checkout-field — list definitions
  • POST v1/checkout-field — create
  • PATCH v1/checkout-field/:id — update (key is immutable)
  • DELETE v1/checkout-field/:id — delete

Storefront (resolved from the shop API key):

  • GET v1/checkout-field/storefront — active fields to render at checkout

The order carries the values on order.custom_fields (JSON snapshot).

Guidance

  • Keep the list short — every extra field is checkout friction.
  • Prefer curated field types; use select with options over free text where it fits.
  • Never rename or reuse a key. Required is server-authoritative; products, phone and address remain the order's hard contract.

See also: Default page builder, Header / Footer Builder.