Configuring Order Properties in 1C-Bitrix
Order properties are additional fields that a buyer fills in during checkout. The standard 1C-Bitrix installation includes a basic set: name, phone, email, and delivery address. Most projects eventually run into specific requirements: legal details for B2B buyers, a promo code field, gift wrapping selection, consent to specific contract terms, or document upload. All of this is implemented through the order properties mechanism.
Where Order Properties Are Stored
Order properties in D7 (the sale module) are separate entities managed via Bitrix\Sale\Internals\OrderPropsTable. Admin path: "Online Store → Settings → Order Properties".
Each property is linked to a property group (ORDER_PROPS_GROUP), which corresponds to the person type (individual / legal entity) and delivery method. Properties are shown or hidden depending on these selections — this is the key conditional visibility logic.
Property Types
| Type | Code | Usage |
|---|---|---|
| String | TEXT |
Name, comment, tax ID |
| List | SELECT |
Fixed selection options |
| Flag | CHECKBOX |
Agreement to terms |
| Date | DATE |
Desired delivery date |
| Location | LOCATION |
Geo-widget integration |
| File | FILE |
Document upload |
Adding a Property via API
For migration scripts or automated deployment:
use Bitrix\Sale\Internals\OrderPropsTable;
$result = OrderPropsTable::add([
'PERSON_TYPE_ID' => 1, // 1 - individual, 2 - legal entity
'NAME' => 'Company Tax ID',
'CODE' => 'INN',
'TYPE' => 'TEXT',
'REQUIRED' => 'Y',
'SORT' => 100,
'GROUP_ID' => 1,
'PROPS_GROUP_ID' => 2,
]);
if ($result->isSuccess()) {
$newId = $result->getId();
}
Conditional Property Visibility
Binding a property to a person type provides basic conditional visibility. For more flexible logic — for example, showing the "Floor" field only for courier delivery — JavaScript handling is required:
BX.addCustomEvent('onDeliveryChanged', function(deliveryId) {
const floorField = document.querySelector('[data-prop-code="FLOOR"]');
const courierIds = [5, 7, 12]; // IDs of courier services
if (floorField) {
floorField.closest('.sale-field-wrap').style.display =
courierIds.includes(parseInt(deliveryId)) ? '' : 'none';
}
});
Server-Side Validation
Custom validation via the OnSaleOrderBeforeSaved event handler:
AddEventHandler('sale', 'OnSaleOrderBeforeSaved', 'validateOrderProps');
function validateOrderProps(\Bitrix\Main\Event $event) {
$order = $event->getParameter('ENTITY');
$propCollection = $order->getPropertyCollection();
$inn = $propCollection->getItemByOrderPropertyCode('INN');
if ($inn && !empty($inn->getValue())) {
$innValue = preg_replace('/\D/', '', $inn->getValue());
if (strlen($innValue) !== 10 && strlen($innValue) !== 12) {
return new \Bitrix\Main\EventResult(
\Bitrix\Main\EventResult::ERROR,
new \Bitrix\Sale\ResultError('Invalid Tax ID'),
'sale'
);
}
}
return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS);
}
Retrieving Property Values in Code
$order = \Bitrix\Sale\Order::load($orderId);
$propCollection = $order->getPropertyCollection();
$phone = $propCollection->getPhone();
$email = $propCollection->getUserEmail();
// Arbitrary property by code
$innProp = $propCollection->getItemByOrderPropertyCode('INN');
$innValue = $innProp ? $innProp->getValue() : null;
Timeline
Adding 3–5 simple properties with visibility configuration by person type — 2–4 hours. Complex configuration with custom validation, conditional JavaScript visibility, and external system integration — 1–2 business days.







