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:
-
Custom filter using D7 ORM —
Bitrix\Iblock\Elements\ElementXxxTable(whereXxxis the information block API code). Auto-generated ORM classes support::getList()withfilter,select, andruntimefields. You control the SQL and can layer caching on filtered result sets -
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 -
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
- Planning (3-5 days) — information block structure, filterable properties map, Figma wireframes
- Design (1-2 weeks) — catalog listing, product detail page, filter UI, comparison, inquiry forms
- Development (2-5 weeks) — markup, Bitrix integration, filter setup, forms, SEO configuration
- Content and import (3-7 days) — product data upload, 1C exchange setup if needed
- 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.







