Developing a Custom 1C-Bitrix Shopping Cart

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1173
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    745
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

Custom Cart Development for 1C-Bitrix

The standard bitrix:sale.basket.basket component covers the basics but breaks down under non-standard business requirements: there is no cross-session cart persistence without authentication, it is impossible to add custom fields to a line item (such as engraving text or packaging colour), and the component's markup is a complex template with an outdated structure. In such cases, the cart is built from scratch or the standard component is heavily reworked.

How the Bitrix Cart Works

The cart is stored in the b_sale_basket table. Each line item is a row with the following fields: FUSER_ID (anonymous user identifier from the session), PRODUCT_ID, QUANTITY, PRICE, CUSTOM_PRICE (manual price flag), NOTES, PRODUCT_XML_ID, and a set of PROPS fields — serialised line-item properties stored in b_sale_basket_props.

Working with the cart via API:

// Adding a product
$basket = \Bitrix\Sale\Basket::loadItemsForFUser(
    \Bitrix\Sale\Fuser::getId(),
    \Bitrix\Main\Context::getCurrent()->getSite()
);

$item = $basket->createItem('catalog', $productId);
$item->setFields([
    'QUANTITY' => 2,
    'CURRENCY' => 'RUB',
    'LID' => 's1',
    'PRODUCT_PROVIDER_CLASS' => '\Bitrix\Catalog\Product\CatalogProvider',
]);
$basket->save();

For AJAX cart operations (add, change quantity, remove), either the \Bitrix\Sale\Compatible\DiscountCompatibility controller or a custom AJAX handler via \Bitrix\Main\Engine\Controller is used.

What Actually Requires Custom Development

Custom line-item properties. The standard cart does not allow adding arbitrary fields to a line item — such as engraving text, selected packaging size, or a specific delivery date for an item. Under the hood, this is the b_sale_basket_props table with NAME, VALUE, and CODE fields. For custom properties you need to:

  • Add UI to the product page template (modal window, form fields)
  • Pass properties in the AJAX request when adding to the cart
  • In the handler, add them via $item->getPropertyCollection()->createItem()
  • Display them in the cart template

Cart persistence without authentication. By default, FUSER_ID is a session ID, and the cart disappears when the browser or device changes. To persist it, store FUSER_ID in a cookie with a long TTL (30–90 days) and create a record in b_sale_fuser on the first visit, linked to that cookie. On login — merge the anonymous cart with the user's cart via \Bitrix\Sale\Basket::mergeBasket.

Mini-cart in the header with AJAX updates. The standard bitrix:sale.basket.small component queries the database on every request. On high-traffic stores this is noticeable: 200 RPS × N queries to b_sale_basket. Solution: store the cart counter in Redis (via \Bitrix\Main\Data\Cache with tagging) and update it only on changes, not on every page render.

Multi-currency cart. When selling in multiple currencies, prices must be correctly converted via CCurrencyRates::ConvertCurrency, storing both the original price in the foreign currency and its equivalent in the base currency. The standard component handles this, but without the ability to show "price in your currency" alongside the USD price.

Case Study: Cart with a Configurator for a Construction Supply Store

Client — an online store for construction materials. Problem: a customer selects tiles and needs to specify the laying area, breakage percentage, and laying pattern (straight/diagonal). The final number of boxes and the total price must be calculated in real time directly in the cart.

Solution: a cart component was developed in Vue.js that communicates with the backend via REST API (custom controller). The configurator is a separate component embedded in the cart line item row. Configuration data is stored in b_sale_basket_props with the codes AREA, BREAKAGE_PCT, and LAYOUT_TYPE. When parameters change — recalculation happens via AJAX without a page reload. The complexity: catalog prices are stored per unit, but purchases are made by the box — conversion in both directions had to be implemented.

Result: cart conversion increased because the customer sees the final price before placing the order, rather than receiving clarification by phone.

Architectural Decisions During Development

The choice of approach depends on requirements:

Approach When to use Effort
Custom component template Visual changes only 1–2 days
Component override Logic changes without third-party data 3–5 days
Custom component + REST API Complex logic, Vue/React frontend 2–4 weeks
Headless (Next.js + Bitrix API) Full frontend control 4+ weeks

When developing a custom cart, always account for:

  • Maintaining compatibility with the sale module — discounts, coupons, and cart rules must continue to work
  • Correct recalculation on quantity change via OnSaleBasketBeforeSaved
  • Server-side validation: never trust a price coming from the client
  • Handling the scenario where a product sold out while sitting in the cart

Timeline and Phases

Custom cart development from analysis to delivery takes 5 working days to 6 weeks depending on complexity:

  • Cart audit and requirements specification — 1–2 days
  • Server-side development (API, event handlers) — 3–10 days
  • Frontend development — 2–15 days
  • Integration with sale, catalog, and currency modules — 1–5 days
  • Testing (unit, integration, load) — 1–3 days