Skip to content
BuildBase

Item options

Sizes, colours and other option axes on an item - the seller defines the values once and each combination is its own variant, with its own price and stock.

An item's options are its axes, such as Size (S, M, L) and Colour (Red, Blue). The seller defines each axis and its values once; every combination is a variant with its own prices and stock, labelled from its values ("M / Red"). The buyer picks a value per axis instead of a variant.

Note

Arrives with selling. Options arrive with selling and run on the same Stripe keys: test keys in Staging for test sales, live keys in Production once live selling is open for your app.

Requires @buildbase/sdk 1.2.0 or later. The options section of <ItemEditor>, <OptionPicker>, useOptionSelection and the optionValues prop of <BuyButton> arrive with it.

Walkthrough

New to selling? Zero to first sale: marketplace and Zero to first sale: storefront walk the whole flow once, from Stripe keys to a refund and going live.

When to use it

A T-shirt in sizes and colours, a print in sizes and finishes: anything where the buyer picks a value per axis and each combination has its own price and stock.

Before you start

An item type with Option axes on and at least two variants per item (the Physical starter has it on).

Set it up in the console

Billing, Item types, the type's version, Variants and stock: turn on Option axes and allow two or more variants, then publish. Each item's axes and values show on its page under Billing, Selling, Items.

Marketplace and storefront

No difference: options choose a variant, and the variant's price is charged as the shape charges.

What the seller sees

The options section of <ItemEditor>: axes, values, and a price and stock per combination.

What the buyer sees

<OptionPicker>, one choice per axis, with a combination that cannot be bought disabled and the reason.

An item page at 1280 pixels wide: Size and Colour pickers with M and Red chosen, S marked sold out, the price and Buy

Emails and webhooks

None of their own. The order line keeps its options, and the sales export has an options column.

Limits

Up to 3 axes and 20 values each; retire a sold value rather than remove it.

Staging and Production

Nothing of its own.

Turning options on

Options are switched on per item type: in the console, Billing > Item types, the type's version, Option axes under Variants (optionAxes: true). An item's axes and values, retired ones badged, show on its page under Billing > Selling > Items. The type must allow at least two variants. The "Physical product" starter has it on.

The item

{
  "options": [
    {
      "id": "size",
      "name": "Size",
      "values": [
        { "id": "s", "label": "S" },
        { "id": "m", "label": "M" }
      ]
    },
    {
      "id": "colour",
      "name": "Colour",
      "values": [
        { "id": "red", "label": "Red" },
        { "id": "blue", "label": "Blue" }
      ]
    }
  ],
  "variants": [
    {
      "id": "m-red",
      "optionValues": { "size": "m", "colour": "red" },
      "prices": [
        { "id": "p-m-red", "currency": "usd", "mode": "fixed", "amount": 2500 }
      ],
      "stock": { "mode": "counted", "available": 10 }
    }
  ]
}
  • Up to 3 axes, 20 values each, and no more variants than the type allows. Axis and value ids are up to 16 letters, digits, - or _.
  • Each variant names one value per axis; each combination appears once. The grid may be partial: a combination the seller does not make is left out.
  • The server writes each variant's label from its values, in axis order.
  • Each price has its own id across the item (duplicate_price_id otherwise), because a sale is recorded by price id.

Changing options after a sale

A value or an axis that sold variants use stays. Removing a sold value is refused (option_value_in_use): retire it instead (retired: true), which stops new sales of its combinations and keeps the orders as sold. Removing an axis that tells sold variants apart is refused (option_axis_in_use). Renaming a value relabels the item; orders keep the label they were sold with.

CodeMeans
options_not_allowedThe item type has no option axes
too_many_optionsMore than 3 axes
duplicate_option_nameTwo axes with one name
no_option_valuesAn axis with no values
duplicate_option_valueTwo values of an axis with one label or id
missing_option_valueA variant without a value for an axis
unknown_optionA variant names an axis the item does not have
unknown_option_valueA variant names a value its axis does not have
duplicate_option_combinationTwo variants on one combination
duplicate_price_idOne price id on two variants
option_value_in_useRemoving a value sold variants use; retire it instead
option_axis_in_useRemoving an axis that tells sold variants apart

Buying by options

Checkout, a cart line and a guest checkout take optionValues (axis id to value id) instead of variantId; priceId may be left out when the combination has one live price.

{
  "optionValues": { "size": "m", "colour": "red" },
  "successUrl": "https://example.com/thanks",
  "cancelUrl": "https://example.com/tee"
}

A combination that does not exist is refused with CHECKOUT_REFUSED, problem unknown_option_combination; one on a retired value, or with no live price, with option_combination_unavailable; one sold out with OUT_OF_STOCK. The order line keeps the options it was bought with (options), and the sales export has an options column.

import {
  BuyButton,
  OptionPicker,
  useOptionSelection,
} from '@buildbase/sdk/react';

function Tee({ item }) {
  const choice = useOptionSelection(item);
  return (
    <>
      <OptionPicker
        item={item}
        selection={choice.selection}
        onSelect={choice.select}
      />
      {choice.variant && choice.price && !choice.problem && (
        <BuyButton
          itemId={item._id}
          variantId={choice.variant.id}
          priceId={choice.price.id}
          optionValues={choice.selection}
        />
      )}
    </>
  );
}

<OptionPicker> disables a value that cannot be bought with the other choices and says why: sold out, or unavailable.

Errors

A refused request answers { error, message, code }, with problems naming the axis, value or variant. The console shows the message; the SDK shows each code in the reader's language.

codeWhat the person seesWhat to do
ITEM_INVALIDThe options problem, such as a variant without a value for an axis (codes in the table above)Fix each entry in problems; retire a sold value rather than removing it
ITEM_TYPE_INVALIDOptions make variants: allow at least 2 per item (options_need_variants)Raise the type's variants to 2 or more before turning Option axes on
CHECKOUT_REFUSEDThe combination does not exist, or cannot be bought now (problems[0].code)Pick another combination; the seller adds a live price or un-retires the value
OUT_OF_STOCKNot enough left for this orderPick another combination, or wait for the seller to restock
ITEM_STATE_CONFLICTThis item changed meanwhile. Reload it and try againReload the item and try again