Developing a catalog website without a shopping cart using 1C-Bitrix

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

Catalog Website Development Without Shopping Cart on 1C-Bitrix

A catalog without a shopping cart serves a specific purpose: products are displayed, described, and filtered, but there is no checkout. Instead of "Add to Cart," the visitor sees "Request a Quote," "Get Pricing," or "Download Spec Sheet." This model fits B2B companies — industrial equipment manufacturers, building material suppliers, auto parts distributors, commercial real estate agencies. The price depends on order volume, contract terms, or currency fluctuations. Publishing a fixed number makes no sense. The transaction requires negotiation, not a click.

From the Bitrix architecture standpoint, this is not "an online store minus the cart." It is a distinct project type with its own decisions at every layer — licensing, data structure, filtering, SEO, and user interaction patterns.

License Editions: Start vs Standard

The edition determines what modules are available. "Start" does not include the sale or catalog modules. No shopping cart, no orders, no trade offers (SKU), no price types. For a catalog-only site, this is sufficient and cheaper.

"Standard" includes the catalog module but allows selective use. You can enable catalog properties for an information block without activating the sale module. This unlocks trade offers (product variants) and multiple price types — without any cart functionality.

Scenario Recommended Edition Reason
Catalog under 5K items, single price or no prices Start No need for catalog module, lower license cost
Catalog with product variations (color, size) Standard Trade offers require catalog module
B2B with multiple price types (retail, wholesale, dealer) Standard Price types are a catalog module feature
Catalog with likely future cart addition Standard Migrating from Start to Standard involves data restructuring

Information Block Structure Without SKU

Without trade offers, the data model simplifies considerably. One information block equals one catalog. No parent-child link via PROPERTY_CML2_LINK. No b_catalog_product table. No b_catalog_price table.

A typical structure for an industrial equipment catalog:

Information block "Equipment Catalog" (type catalog, API code equipment):

  • Sections = categories (Pumps → Centrifugal → Horizontal)
  • Elements = product items
  • Properties:
    • MANUFACTURER (directory, linked to Highload block) — brand
    • ARTICLE (string, indexed) — part number
    • POWER (number) — power rating, kW
    • WEIGHT (number) — mass, kg
    • MATERIAL (list) — housing material
    • DOCS (file, multiple) — PDF documentation
    • GALLERY (file, multiple) — photographs
    • PRICE_ON_REQUEST (checkbox) — price available on request
    • IN_STOCK (list: "In Stock," "Made to Order," "Discontinued")

Reference data goes into Highload blocks. Manufacturers, units of measurement, countries of origin. A HLBlock for "Manufacturers" creates table b_hlbd_manufacturers with fields UF_NAME, UF_LOGO, UF_COUNTRY, UF_WEBSITE. The information block property links to it via a "Directory" type property.

Why this matters for performance: without SKU, each product generates one row per property in the EAV table b_iblock_element_property. A product with 15 properties = 15 rows. Add 5 SKU variants and it becomes 75 rows per product. At 10K products, the difference between 150K and 750K rows is measurable during filtering.

Filtering: catalog.smart.filter Without the catalog Module

The component bitrix:catalog.smart.filter operates on information blocks and functions without the catalog module. However, faceted indexes (b_catalog_sm_* tables) are only available when catalog is active. On the "Start" edition, faceted indexing is unavailable.

Without facets, filtering queries run directly against b_iblock_element_property. For catalogs up to 10-15K items with 10 filterable properties, response times stay at 100-300ms — acceptable. Beyond 50K items, queries can take 2-5 seconds.

Alternatives when facets are unavailable:

  1. Custom filter using D7 ORMBitrix\Iblock\Elements\ElementXxxTable (where Xxx is the information block API code). Auto-generated ORM classes support ::getList() with filter, select, and runtime fields. You control the SQL and can layer caching on filtered result sets

  2. Elasticsearch or Sphinx — for catalogs exceeding 50K items. Index on write via an event handler on OnAfterIBlockElementUpdate. Filtering drops to 5-20ms regardless of catalog size. Tradeoff: additional infrastructure to maintain

  3. Highload block-based catalog — if the catalog is stored in an HLBlock, filtering runs against a flat table with proper indexes. Fast, but you lose the built-in SEO components that depend on information blocks

For most catalog-without-cart projects under 30K products, the standard catalog.smart.filter with database indexes on frequently filtered properties is sufficient.

Deep Dive: CIBlockElement::GetList vs D7 ORM

The legacy API — CIBlockElement::GetList($arOrder, $arFilter, $arGroupBy, $arNavStartParams, $arSelectFields) — remains functional and widely documented. Filters use array conventions: ">=PROPERTY_POWER" => 100 means "power greater than or equal to 100." No type safety, no IDE autocompletion on filter keys, no compile-time validation.

The D7 API — \Bitrix\Iblock\Elements\ElementEquipmentTable::getList([...]) — provides strict typing, a fluent interface, runtime fields for computed columns, and registerRuntimeField() for on-the-fly aggregation. The IDE understands the class structure. Refactoring is safe.

Practical rule: write new code with D7, leave working legacy code alone. CIBlockElement::GetList is not deprecated and Bitrix maintains backward compatibility across major versions. But if you are building a filter, an aggregation query, or a data export from scratch, D7 produces predictable SQL that you can profile with \Bitrix\Main\Diag\SqlTracker.

Example — fetching catalog items with a runtime field:

ElementEquipmentTable::getList([
    'select' => ['ID', 'NAME', 'MANUFACTURER_' => 'MANUFACTURER'],
    'filter' => ['ACTIVE' => 'Y', '>=POWER.VALUE' => 50],
    'order' => ['NAME' => 'ASC'],
    'cache' => ['ttl' => 3600, 'cache_joins' => true],
]);

The cache parameter enables built-in managed cache — no manual CPHPCache wrapping needed.

SEO for Catalog Pages

The iblock module includes built-in SEO templates. Configure them at the information block level: "SEO" tab → templates for sections and elements. Template variables:

  • {=this.Name} — element/section name
  • {=this.PreviewText} — preview text
  • {=this.property.MANUFACTURER} — property value
  • {=parent.Name} — parent section name

A <title> template for a catalog item: {=this.Name} — {=parent.Name} specifications from {=this.property.MANUFACTURER}. Avoid "buy" in titles when there is no purchase option — search engines and users both notice the mismatch.

Human-readable URLs are configured through component parameters in catalog.section / catalog.element:

  • Section: /catalog/#SECTION_CODE#/
  • Element: /catalog/#SECTION_CODE#/#ELEMENT_CODE#/

Enable "Transliterate symbolic code on element add" in the information block settings. Codes generate automatically from the element name.

Structured data — Schema.org Product markup without Offer (no purchasable price). Include name, description, image, brand, sku (part number). For "price on request" items, omit the offers property entirely or use priceSpecification without a price value.

Product Comparison Without the sale Module

The built-in comparison component (bitrix:catalog.compare.list) depends on the catalog module. On "Start," it does not function. The solution: a custom comparison component.

Storage: an array of selected product IDs in $_SESSION['COMPARE_LIST'][IBLOCK_ID] or in a cookie for anonymous visitors. Output: CIBlockElement::GetList by the array of IDs, selecting all properties, rendering into a property-value matrix across products. Implementation effort: 8-12 development hours, including JavaScript for add/remove without page reload.

For React-based frontends or headless setups, comparison state lives in component state or localStorage. Product data is fetched via REST API (/rest/iblock.element.get) or a custom controller endpoint.

"Request a Quote" Instead of "Add to Cart"

This is the central UX pattern of a catalog without a cart. Implementation uses the webform module or a custom form handler.

The form passes the ELEMENT_ID and ELEMENT_NAME in hidden fields. The manager receives an email: "Price request for [product name], part number [XXX], from [name, phone, email]." Submissions are stored in a dedicated information block or Highload block for conversion tracking.

CTA button variants by industry:

  • Equipment: "Request Commercial Offer"
  • Real estate: "Schedule a Viewing"
  • Auto parts: "Check Availability and Price"
  • Custom furniture: "Calculate Cost"

1C Integration Without the sale Module

The catalog module supports CommerceML exchange via /bitrix/admin/1c_exchange.php. On "Start," this is unavailable. The alternative: custom import via CSV, XML, or REST API.

For catalog-without-cart projects, data exchange is typically one-directional: 1C → website. Product nomenclature, stock status, specifications. Implementation options:

  • A Bitrix agent (CAgent) on a schedule, parsing an XML export from 1C
  • A cron job calling a CLI import script
  • REST API calls if 1C is configured to send HTTP requests via HTTPConnection

With the "Standard" edition and the catalog module enabled, the built-in CommerceML exchange works fully — simply do not activate the sale module.

Stages and Timeline

  1. Planning (3-5 days) — information block structure, filterable properties map, Figma wireframes
  2. Design (1-2 weeks) — catalog listing, product detail page, filter UI, comparison, inquiry forms
  3. Development (2-5 weeks) — markup, Bitrix integration, filter setup, forms, SEO configuration
  4. Content and import (3-7 days) — product data upload, 1C exchange setup if needed
  5. Testing and launch (3-5 days) — cross-browser, mobile, PageSpeed audit, handover
Scale Timeline
Catalog under 500 items, no integrations 3-5 weeks
Catalog 1-10K items, filter, comparison 5-8 weeks
Catalog 10-50K, 1C sync, user accounts 8-12 weeks

When a Catalog Is the Right Choice — and When You Need a Store

A catalog without a cart is justified when at least two of these apply:

  • Prices are non-public or context-dependent (volume, region, contract)
  • The deal requires negotiation — it cannot close in two clicks
  • The product range is complex: 15+ attributes per item, selection by specification
  • There is no warehouse logistics managed through the website

If a cart becomes necessary later, the transition from catalog to store — with properly architected information blocks and separated logic — takes 2-4 weeks: activating the sale module, adding price types, configuring payment systems and delivery services. The catalog data remains untouched.