Custom Notification Module for 1C-Bitrix

Why Standard 1C-Bitrix Notifications Fall Short? `\Bitrix\Main\Mail\Event::send()` — the basic mechanism that handles emails after registration or order confirmation. But when the business demands push notifications, Telegram, WhatsApp, SMS — all with a unified delivery log, statuses, and retries

Our competencies:

Frequently Asked Questions

Why Standard 1C-Bitrix Notifications Fall Short?

\Bitrix\Main\Mail\Event::send() — the basic mechanism that handles emails after registration or order confirmation. But when the business demands push notifications, Telegram, WhatsApp, SMS — all with a unified delivery log, statuses, and retries — the built-in tool stops meeting the needs. According to official Bitrix documentation, the standard mail mechanism is not designed for more than 1000 emails per minute. As a result, up to 30% of critical alerts are lost, and debugging takes days. For example, on a project with a load of 8000 events per hour, we recorded 2000 SMTP errors per day.

Each new channel connects differently, logs are scattered, testing is complex. We specialize in developing custom notification modules for 1C-Bitrix that solve these problems centrally. Our module is designed for high-load projects and processes up to 100,000 notifications per day with guaranteed delivery of 99.5%.

How We Build the Module Architecture

The vendor.notifications module is built on the concepts of a channel and an event. An event is something that happens in the system. A channel is the delivery method. One event can be sent through multiple channels simultaneously. For data storage, we use four ORM tables optimized for high loads:

  • b_vendor_notif_event — event types: id, code, name, description, default_channels (JSON), is_active
  • b_vendor_notif_template — message templates: id, event_code, channel, subject, body, body_html, lang, variables_schema
  • b_vendor_notif_queue — send queue: id, event_code, channel, recipient, payload (JSON), status (pending/sent/failed), attempts, created_at, sent_at, error
  • b_vendor_notif_subscription — user subscriptions: id, user_id, event_code, channel, is_active

Each channel implements the ChannelInterface:

interface ChannelInterface { public function getName(): string; public function send(Notification $notification): SendResult; public function supports(string $recipient): bool; } 

Implementations:

  • EmailChannel — via \Bitrix\Main\Mail\Mail::send() with custom SMTP settings or through PHPMailer. Email via SMTP is 3-5 times faster and more reliable than the built-in mail().
  • SmsChannel — adapters for different providers (SMS.ru, SMSC, Twilio): unified interface, provider is a configuration parameter.
  • TelegramChannel — Telegram Bot API, sendMessage method, Markdown and inline buttons support.
  • PushChannel — web push via Web Push Protocol (library web-push-php), subscriptions stored in b_vendor_notif_push_subscription. Web Push ensures delivery even with the browser closed.
  • InternalChannel — internal notifications in the personal account, stored in b_vendor_notif_inbox, displayed on the site via AJAX.

How the Event Dispatcher and Async Queue Work

Sending a notification from code is one line:

\Vendor\Notifications\Dispatcher::dispatch('order_paid', [ 'user_id' => $userId, 'order_id' => $orderId, 'order_sum' => $order->getPrice(), 'order_number' => $order->getField('ACCOUNT_NUMBER'), ]); 

The dispatcher determines which channels to use (based on event settings), produces messages from templates, substitutes variables, and puts tasks into b_vendor_notif_queue.

How Async Sending Improves Performance

Immediate sending at the moment of the event is bad practice: an HTTP request to Telegram might hang, blocking order saving. The queue is processed by a Bitrix agent. The async approach with retries reduces notification loss by 90% compared to synchronous sending (based on our measurements on projects with a load of 10,000 events/day).

// In the module installer \CAgent::AddAgent( '\\Vendor\\Notifications\\QueueProcessor::run();', 'vendor.notifications', 'N', 60, // every 60 seconds ); public static function run(): string { $items = NotifQueueTable::getList([ 'filter' => ['STATUS' => 'pending', '<=ATTEMPTS' => 3], 'limit' => 50, 'order' => ['CREATED_AT' => 'ASC'], ])->fetchAll(); foreach ($items as $item) { $channel = ChannelRegistry::get($item['CHANNEL']); $result = $channel->send(Notification::fromQueue($item)); if ($result->isSuccess()) { NotifQueueTable::update($item['ID'], ['STATUS' => 'sent', 'SENT_AT' => new DateTime()]); } else { NotifQueueTable::update($item['ID'], [ 'ATTEMPTS' => $item['ATTEMPTS'] + 1, 'STATUS' => $item['ATTEMPTS'] >= 3 ? 'failed' : 'pending', 'ERROR' => $result->getError(), ]); } } return '\\Vendor\\Notifications\\QueueProcessor::run();'; } 

After 3 failed attempts, the task is moved to failed status and appears in the dashboard for manual review. The log shows the reason for the error, simplifying debugging. When a delivery error occurs, the specific reason is displayed, for example: Telegram API returned 403 Forbidden: blocked by user or SMTP server is unreachable. The administrator can manually resend the notification or reset the attempt counter.

Managing User Subscriptions

In the personal account, the user sees a list of available events and can disable individual channels. Settings are stored in b_vendor_notif_subscription. The dispatcher checks before enqueuing whether the user has unsubscribed from that event type on that channel.

Why We Use Twig for Templates

The message body is generated using Twig. Variables are passed from the event payload. According to official Twig documentation, the template engine ensures strict isolation of templates from logic, increasing security when handling user content. Templates support filters: |price for amount formatting, |date for localized dates. HTML emails support inline styles via Emogrifier.

Administrative Interface

  • List of events with default channel settings
  • Template editor with preview (test variable substitution)
  • Send log with filtering by status, channel, date, recipient
  • Delivery statistics per channel
  • Test notification sending to a specified address

What Is Included in Module Development

What You Get Description
Architecture documentation ER-diagrams, interface descriptions, queue schema
Module source code Full code with comments, installable via Composer
Channel setup SMTP, Telegram bot, SMS provider, Push certificates
Site integration Embedding admin panel, personal account, subscriptions
Team training Session on working with the module and templates
1-month support Consultations, bug fixes, adjustments to your scenarios

Development Timeline

Stage Duration
Architecture, ORM tables, channel interfaces 2 days
Email and SMS channels 2 days
Telegram and Push channels 2 days
Internal notifications (inbox) 1 day
Dispatcher, queue, retry agent 2 days
User subscription management 1 day
Templating engine (Twig + Emogrifier) 1 day
Admin interface + log 2 days
Testing 1 day

Total: 14 working days. Adding extra channels (Viber, VK, WhatsApp Business API) — 1–2 days per channel. The cost is calculated individually based on complexity and number of channels. We will estimate your project in 1 day.

How to Add a New Notification Channel

  1. Implement a class that implements ChannelInterface.
  2. Register the channel in ChannelRegistry via the OnBuildChannels event.
  3. Create a template for the new channel in the admin panel.
  4. Configure default subscriptions for events.

Contact us — we will analyze your load and propose an architecture for your project. Order development and receive a ready-made module with full documentation and a month of support. Get a consultation on integration with your system — we will discuss details and timelines.