200 articles accumulated, but you can't find the one you need — no full-text search, articles not categorized. Users go to Yandex without finding an answer. We solve this problem by creating a structured knowledge base on 1C-Bitrix with a configured infoblock, search, and automatic import. Our experience — 7 years of development, over 50 successful projects.
Why a standard blog isn't suitable for technical documentation?
Technical documentation is about search and depth, not chronology. A blog is about relevance and traffic; articles are about expertise and conversion. Typical tasks: product knowledge base, technical descriptions reference, "Help" or "Training" section. Here, what matters is not publication frequency, but navigation through a large volume of content. For sections with 500+ articles, a standard blog becomes ineffective.
Infoblock architecture for articles
A separate infoblock is created for the articles section. The section structure (b_iblock_section) corresponds to the topic hierarchy — up to 3 nesting levels. Deeper nesting in Bitrix is technically possible, but worsens navigation and SEO (long URL, diluted weight).
Mandatory infoblock properties:
- DIFFICULTY — material complexity level (list: "Beginner", "Advanced", "Expert")
- READING_TIME — reading time in minutes
- LAST_UPDATED — date of last article update (important for technical materials)
- RELATED_LINKS — multiple property of type "String" for external sources
- VIDEO_EMBED — video instruction embed code
Publication date (ACTIVE_FROM) and update date (LAST_UPDATED) are different fields. In the detail page template, we output: "Last updated: recently."
How to configure search only within the articles section?
Standard Bitrix search (bitrix:search.page) works across the entire site. For the articles section, we often need search only within the infoblock. This is solved in two ways.
Through the standard search module with a filter. Infoblock indexing for articles is configured via CSearch::Index(). Search limited by IBLOCK_ID parameter:
$obSearch = new CSearch();
$obSearch->Search([
'QUERY' => $searchQuery,
'MODULE_ID' => 'iblock',
'PARAM2' => IBLOCK_ARTICLES_ID,
]);
Via Elasticsearch for large sections (1000+ articles). Standard MySQL full-text search is slow for complex queries. An external search engine is connected through a custom component; data is synchronized via a Bitrix agent. For 3000 articles, the speed difference is tenfold: 4 seconds vs 0.1 seconds.
| Parameter |
Standard search |
Elasticsearch |
| Speed for 1000+ articles |
2–5 sec |
0.1–0.2 sec |
| Setup |
Built-in module |
Requires installation |
| Ranking |
By date/relevance |
Customizable |
Cross-linking and navigation
Navigation within the articles section is critical. The user came for an answer, found an article, and should easily navigate to related topics.
Breadcrumbs — standard bitrix:breadcrumb component, works automatically with correct infoblock section structure.
Side category menu — bitrix:menu component with MENU_TYPE parameter or a custom component using CIBlockSection::GetList():
$sections = CIBlockSection::GetList(
['SORT' => 'ASC'],
['IBLOCK_ID' => IBLOCK_ARTICLES_ID, 'DEPTH_LEVEL' => 1, 'ACTIVE' => 'Y'],
false,
['ID', 'NAME', 'CODE', 'SECTION_PAGE_URL']
);
Related articles block — by matching section or tags:
$related = CIBlockElement::GetList(
['RAND' => 'ASC'],
['IBLOCK_ID' => IBLOCK_ARTICLES_ID, 'SECTION_ID' => $arResult['IBLOCK_SECTION_ID'], '!ID' => $arResult['ID'], 'ACTIVE' => 'Y'],
false, ['nTopCount' => 4],
['ID', 'NAME', 'PREVIEW_PICTURE', 'PREVIEW_TEXT', 'DETAIL_PAGE_URL']
);
Structured data (Schema.org)
For articles, we attach Article or HowTo markup depending on content type. This improves search snippet display:
// in template.php of detail page
$schema = [
'@context' => 'https://schema.org',
'@type' => 'Article',
'headline' => $arResult['NAME'],
'datePublished' => $arResult['ACTIVE_FROM'],
'dateModified' => $arResult['PROPERTIES']['LAST_UPDATED']['VALUE'],
'author' => ['@type' => 'Organization', 'name' => 'Company name'],
];
echo '<script type="application/ld+json">' . json_encode($schema, JSON_UNESCAPED_UNICODE) . '</script>';
How does content import work?
- Source preparation. We collect all files (Word, PDF, Excel) into one folder. We check the structure.
- Conversion. For DOCX we use PHPWord, for PDF — pdftohtml. We get HTML.
- Cleaning. We remove extra styles, align headings, fix encoding.
- Loading. A script goes through each file, creates an infoblock element via CIBlockElement::Add().
- Categorization. We assign sections based on file name or a separate map.
- Verification. We visually check 10% of articles. We fix errors.
The entire process takes from 2 days to 2 weeks depending on volume. In one agent run, up to 100 articles are imported.
Mass content filling and import
A large articles section is often filled from external sources: Word documents, PDF instructions, Google Docs. Manual entry of each article into Bitrix's visual editor is inefficient.
Import from Excel. Bitrix's standard tool allows importing infoblock elements from CSV. Columns: NAME, PREVIEW_TEXT, DETAIL_TEXT, SECTION_ID, properties. But HTML markup in CSV is problematic: quotes and line breaks break the format. Solution — a custom PHP script with CIBlockElement::Add().
Conversion from Word/PDF. The PHPWord library (via Composer) reads DOCX and converts to HTML. PDF is converted via pdftohtml (system utility) or via an external API (Adobe PDF Services). The result is cleaned with regular expressions and saved into DETAIL_TEXT.
Content versioning. For technical documentation, it's important to track changes. Bitrix has no built-in versioning for article content (only for site pages via the landing module). Custom solution: before updating an article, the old DETAIL_TEXT version is saved in a separate table b_custom_article_versions with fields ELEMENT_ID, VERSION_DATE, CONTENT, USER_ID. Over a year, such a system allows rolling back up to 15 edits.
Automatic update of outdated articles
Technical articles become obsolete. A notification system is needed: 6–12 months after publication, the content manager receives a reminder to check relevance. Implementation via a Bitrix agent (CAgent::Add()) that checks the last update date once a month and sends an email via CEvent::Send().
What is included in the work
When ordering the filling of an articles section, we provide:
- Designing the infoblock and properties
- Configuring search (standard or Elasticsearch)
- Importing content from external sources (Word, PDF, Excel)
- Developing templates for detail page and list
- Setting up cross-links and navigation
- Connecting structured data
- Setting up an agent for updating outdated articles
- Training content managers
We estimate the project in 1 day. Warranty on all work — 12 months. Get a consultation: write to us and we will evaluate your project.
Timelines and volumes
| Volume |
Scope of work |
Timeline |
| Up to 50 articles |
Manual filling + basic SEO |
2–3 weeks |
| 50–200 articles |
+ import, categorization, cross-linking |
3–6 weeks |
| 200+ articles |
+ section search, versioning |
6–12 weeks |
The articles section pays off slowly but steadily: technical materials retain search positions for years with proper structure and periodic updates.
Contact us to discuss your project. Order the filling of your articles section — and your clients will find answers faster.
1C-Bitrix Module Development and Setup
The main trap of Bitrix is init.php. You add an OnBeforeIBlockElementUpdate handler there, then another one — a year later the file is 2000 lines, and on every hit all that code executes. We move business logic into full-fledged modules with D7 ORM, custom tables, and administrative interface. The module can be disabled, transferred to another project, covered with tests — none of that is possible with init.php. Our team has 10+ years of Bitrix experience, certified specialists, and a 6-month code guarantee. Request a consultation — we'll explain how to migrate legacy code to a modular architecture.
Why is init.php the worst place for business logic?
Init.php does not support class autoloading, lacks an isolated namespace, cannot be unit tested, and cannot be disabled without editing the file itself. Every handler written there runs on every request, even if not needed. In a module, you register handlers through EventManager, and they only execute when the event occurs. Performance difference: up to 3x with 10+ handlers.
Standard Modules: Typical Problems and Solutions
Information blocks. IBlock architecture is the first thing we review on any project. A classic mistake: one catalog infoblock with 80 properties, 30 of which are multiple. The b_iblock_element_property table swells to millions of rows, and CIBlockElement::GetList with filtering on three properties does a full scan. We move reference data to Highload-blocks, eliminate multiple properties where possible, and design the structure for 5x growth.
e-Store (sale). Cart business rules are a separate story. We set discount priorities to prevent two campaigns from giving 60% instead of 30%, connect payment handlers, and write custom validation via OnSaleOrderBeforeSaved.
Search. The built-in search module with morphology works up to 10–15 thousand elements. Beyond that — Elasticsearch. We configure it via the Bitrix search module API, indexing through CSearchFullText or custom indexers.
Highload-blocks for dictionaries, logs, user data — instead of bloated IBlocks. Direct queries via Bitrix\Highloadblock\HighloadBlockTable, custom tables instead of the EAV structure of standard infoblocks. A million records — no degradation.
Mail events. Configuration is not just templates in b_event_message. The key is SPF, DKIM, DMARC on the DNS, otherwise transactional emails go to spam. We check deliverability and set up bounce handling.
How to Design Infoblocks for Performance?
We use Highload-blocks for reference data (colors, sizes, manufacturers) that are not involved in complex queries. For SKUs — a separate infoblock with linking via IBLOCK_ELEMENT_PROPERTY. Enable INDEX_PROPERTY for frequently filtered properties. Tagged caching: when an element changes, only the related cache is cleared. Highload-blocks process up to 10x faster than infoblocks with multiple properties on volumes of 100,000 records.
Custom Module Development
Each module follows the structure /local/modules/vendor.modulename/:
-
install/index.php — setup class, create tables via $DB->RunSQLBatch()
-
lib/ — D7 ORM classes, extending Bitrix\Main\ORM\Data\DataManager
-
admin/ — administrative pages using CAdminList, CAdminForm
-
include.php — autoloading, event handler registration via EventManager::getInstance()->registerEventHandler()
- REST API endpoints via
\Bitrix\Rest\RestManager
The module registers in the system, appears in the "Installed Solutions" list, and has its own settings at /bitrix/admin/settings.php?mid=vendor.modulename. It can be enabled, disabled, and updated through UpdateSystem or custom migration mechanics.
Examples of implemented tasks:
- Campaign management — visual condition builder via
CAdminCalendar, timers via agents (CAgent::AddAgent), analytics linked to the sale module
- Cost calculator — React widget on the frontend, REST API in the module, formulas stored in a Highload-block
- Booking system — real-time calendar, locking via
$DB->StartTransaction() / $DB->Commit() on concurrent requests, integration with channel manager via webhook
Components and Composite Cache
Component customization via result_modifier.php and component_epilog.php, not by editing template.php of the standard template. This way core updates are painless.
Composite cache ("Composite Site" technology) — the server sends ready HTML, bypassing PHP routing. Dynamic areas (cart, authorization) are loaded via CBitrixComponent::setFrameMode(true) and AJAX. TTFB drops to 30–50 ms. But there are caveats: not all components are compatible, $APPLICATION->ShowPanel() breaks composite, and careful markup of <div id="bx-composite-..."> is required.
What to Check Before Installing a Marketplace Module?
Before installing a module from the marketplace, an audit is mandatory. We check: SQL queries without prepared statements (hello SQL injection), direct use of $_REQUEST without filtering, use of outdated kernel API instead of D7, conflicts with the composite cache module. A module with no updates for over a year and a few dozen installations is likely a problem on the next PHP update. A typical case: a module calls CIBlockElement::GetList with no cache reset — the site crashes with 5000 elements.
Migration to D7
When upgrading PHP or switching to a new edition — refactor outdated calls:
-
CIBlockElement::GetList() → Bitrix\Iblock\Elements\ElementTable::getList()
-
CSaleOrder::GetList() → Bitrix\Sale\Order::getList()
-
CModule::IncludeModule() → Bitrix\Main\Loader::includeModule()
Testing on staging, rollback via git on issues.
According to official 1C-Bitrix documentation, D7 ORM is the recommended tool for working with data, providing type safety and automatic query generation.
Comparison: Init.php vs Module
| Criterion |
Init.php |
Module with D7 ORM |
| Performance |
Executes on every hit |
Executes only on event |
| Testability |
No autoloading, tests impossible |
Full PHPUnit support |
| Maintainability |
Codebase grows uncontrollably |
Isolated structure, versioning |
| Migrations |
None |
Custom tables, managed via install |
| Caching |
Does not support auto-invalidation |
Tagged caching, event-based clearing |
Module Development Scope and Cost
What is included in module development?
- Technical specification and architectural plan
- Code following PSR-4 and Bitrix code style
- Unit tests (PHPUnit) for business logic
- Integration tests for events and REST API
- Installation, configuration, and API documentation
- Repository and documentation access
- Administrator training for module usage
- 6-month warranty support
Estimated timelines and complexity:
| Complexity |
Examples |
Timeline |
| Simple |
Callback widget, banner system, simple calculator |
3–5 days |
| Medium |
Booking system, product configurator, review module with moderation |
1–2 weeks |
| Complex |
Multi-regionality, custom loyalty program, ERP integration |
2–4 weeks |
| Enterprise |
Marketplace platform, complex business processes with multiple roles |
1–3 months |
Cost is calculated individually — contact us for a project estimate.
Module Testing
Unit tests via PHPUnit cover business logic: discount calculation, validation, document generation. Mocks for Bitrix\Main\Application::getConnection() allow tests to be DB-independent. Integration tests verify event handlers on a real database — OnAfterIBlockElementAdd, OnSaleOrderSaved, etc. REST API endpoints are tested via curl or PHPUnit HTTP client. Critical for modules working with b_sale_order, b_catalog_price — where errors cost money.
Compatibility is checked on PHP 7.4, 8.0, 8.1, 8.2 and editions: Standard, Small Business, Business. We check conflicts with popular marketplace modules — they often intercept the same events. Load testing: measurements on 10K, 100K, 1M records, profiling via Xdebug for memory leaks and N+1 queries.
Practical Examples
Campaign module for an electronics chain. The built-in sale module discounts did not cover scenarios like "2+1", a gift with purchase over a certain amount, or combined conditions. We built a visual builder: marketers create rules via drag-and-drop without development tickets. Campaign calendar, auto-deactivation via agents, analytics linked to b_sale_order — conversion, average check, usage count. Time to launch a new campaign dropped from two days to half an hour.
Calculator for builders. Parameters (area, materials, number of floors) → formula → preliminary estimate → lead to CRM via CRest::call('crm.lead.add'). Regional coefficients and seasonal markups from a Highload-block, material prices from 1C exchange. The number of target leads increased by a third: clients see a breakdown before calling a manager.
Booking for a hotel chain. Real-time availability via AJAX requests to a custom table vendor_booking_slots, seasonal tariff calculation, synchronization with Booking.com via channel manager API. Room locking on concurrent booking via SELECT ... FOR UPDATE in transactions. Timezones handled via \DateTimeZone — a guest from Vladivostok and a manager from Moscow see the same picture.
We will evaluate your project within one day. Write to us — we'll tell you what is included in turnkey development. Contact us for a consultation on your project. Order a custom module development — get a ready solution with documentation and support.