Skip to main content
With the free fields at split item level, you offer the buyer input fields and checkboxes that do not belong to the product but to the order: gift wrapping, a preferred date, a greeting text. Additional costs can be attached to each of these fields. Unlike the free input fields of the basket item (BASKET-PR-AdditionalUserInput_1…20), everything here is defined in the shop configuration shop.config in the <BasketProductOptions> section: which fields exist, where they appear, what they cost and how the input is validated. The tags with the prefix BPO- output this configuration in the template. Guide: Free fields at split item level · Reference: Section <BasketProductOptions>

The structure in the template

All tags in this group are nested inside each other, and the order of nesting is fixed.
The range tag in the middle is the reason why the same code block works on three templates. The shop knows only one active level of usage, and BPO-LevelOfUsage_XXX ensures that the block only outputs something on the matching template.
Only one level of usage is ever active per shop. So you cannot offer a field per order and a field per basket item at the same time.

The complete example

Without the BT-BPO_Refresh button, the entries are lost. It writes the values back to the basket. The only exception is the product detail view: there, the fields are inside ~FORM-Product~ and are transferred to the basket together with the product.
Reference: BT-BPO_Refresh

The level of usage

Which of the three levels applies is defined by the LevelOfUsage parameter in the <BasketProductOptions> section. Each level has its own range tag and its own place in the template.

BPO-UseOnce

Encloses the entire block for the Once level. It sits one level above BPO-Data and is the only tag in this group that stands outside the loop.
At first glance, the two tags seem redundant. However, BPO-UseOnce belongs to the basket page and keeps the block out of the item loop, while BPO-LevelOfUsage_Once checks the setting of the individual field block. For the other two levels, BPO-UseOnce is omitted.

BPO-LevelOfUsage_BasketPositionAddress

Applies when the fields apply per delivery address within a basket item. This requires the split order function, that is, splitting an item across multiple delivery addresses.
The block must appear twice on the order overview page: once in {@BASKET-PR-D-MultiData} and once in {BASKET-PR-D-SingleData}. Even with split order active, the buyer can choose only one delivery address for an item, and then the second range applies.
Guide: Splitting a basket item and sending it to multiple delivery addresses · Reference: BASKET-PR-D-MultiData, BASKET-PR-D-SingleData

The loop over the field blocks

BPO-Data

Loop over the field blocks configured in <BasketProductOptions>. In each iteration, the fields and cost calculations of one block are available.
All other tags in this group except BPO-UseOnce and BPO-AllCosts_Sum are only permitted inside this loop. Outside it, they return nothing because they lack the reference to the field block.

BPO-ID

Outputs the identifier of the field block, that is, the value of BasketProductOptionID from the shop configuration.
The identifier has no meaning for the buyer. It is useful as a hook for CSS and JavaScript when several field blocks should look different.

The input fields

BPO-Input

Loop over the fields of the block. As a single tag, it outputs the number of configured fields.

BPO-Input_Type_Input and BPO-Input_Type_Checkbox

The two range tags distinguish the field type. BPO-Input_Type_Input applies to the text input field, BPO-Input_Type_Checkbox to the checkbox.
The second, hidden field for the checkbox is not a typo. An unchecked checkbox submits nothing at all, so the shop could not distinguish between “deselected” and “form never submitted”. The field with the suffix _hidden is always set and reports that this checkbox was in the form at all. Without this field, a checkbox that has been checked once cannot be unchecked again.

BPO-Input_ID and BPO-Input_input

BPO-Input_ID outputs the identifier of the field from the shop configuration, BPO-Input_input the technical field name for the name attribute.
The name attribute must come from BPO-Input_input. A name you assign yourself is not recognized on submission, and the entry is lost.

BPO-Input_value

Returns what the buyer entered. For the text input field, this is the text; for the checkbox, the value on. As a range tag, it applies as soon as the field is filled in or checked.
On the order overview page, output without an input field makes sense so that the buyer sees their entries once more before submitting. For this, BPO-Data, BPO-Input and BPO-Input_value without the LevelOfUsage enclosure are sufficient.

BPO-Input_error

Outputs the error message stored in the shop configuration for the input validation of this field. As a range tag, it only applies if the validation actually failed.
The message comes from the <GenericInputChecks> section, linked via the field’s +UseGenericInputCheck parameter. It belongs directly next to the field and not at the top of the page, otherwise the buyer will look at the wrong one when there are several fields.
Reference: Section <GenericInputChecks>

BPO-Input_costs

Outputs the additional costs attached to this one field.
This is the output at the field, not the billing. The amount actually charged is provided by BPO-Costs_Sum, and the total across all field blocks by BPO-AllCosts_Sum.

The additional costs

Costs are not attached to the field but to the field block. A block can have several cost calculations, and each calculation has its own conditions. That is why there is a second loop alongside the field loop.

BPO-Costs

Loop over the cost calculations of the block. As a single tag, it outputs their number.

BPO-Costs_Valid and BPO-Costs_Sum

BPO-Costs_Valid applies when the configured conditions of this cost calculation are met. BPO-Costs_Sum outputs the calculated amount and applies as a range tag when an amount is incurred.
The costs are incurred as soon as the conditions of the calculation are met, not only when the buyer fills in the field. The only exception is a condition that checks exactly that (Proof = BasketProductOptionInputID with Type = filled). A cost calculation without a condition therefore always applies, even if the field is empty.
Only display the costs inside {BPO-Costs_Valid}. The loop runs over all configured calculations, including those whose conditions do not currently apply.

BPO-Costs_ID, BPO-Costs_Name and BPO-Costs_Value

BPO-Costs_Value is the value from the configuration, not the result. For percentualSum, it contains the percentage, and for multiplyWithQuantity, the amount per piece. What the buyer pays is in BPO-Costs_Sum.

The type of calculation

Three range tags indicate which rule is used for the calculation. Exactly one of them always applies.
The three tags are mainly useful during setup to see which rule applies. For the buyer, the final amount from BPO-Costs_Sum is usually sufficient.

BPO-AllCosts_Sum

Outputs the sum of all additional costs across all field blocks. As a range tag, it applies if any costs are incurred at all.
This tag stands outside the BPO-Data loop and belongs in the invoice footer next to shipping and payment. It is the only value in this group that visibly explains the order total.

The tags at a glance

The tags are permitted on the product detail view (ws_product.htm), the basket page (ws_basket.htm) and the order overview page (ws_place_order.htm), with these exceptions: In addition, all tags except BPO-UseOnce and BPO-AllCosts_Sum are only available inside the BPO-Data loop.
  • Guide: Free fields at split item level
  • Reference: Section <BasketProductOptions>
  • Reference: Section <GenericInputChecks>
  • Reference: BT-BPO_Refresh
  • Reference: Items in the basket