Setting up segmented push notifications in 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

Segmented Push Notification Setup in 1C-Bitrix

Mass push notifications with a 0.5% CTR and growing unsubscribe rates result from lack of segmentation. Push with relevant offer (discount on a category the user was browsing) achieves 4–8% CTR. This is the difference in approach: not "everyone about everything," but specific message to specific segment.

Push Notification Infrastructure in Bitrix

The standard 1C-Bitrix module does not include push notifications for an online store. Infrastructure is built on:

  • Firebase Cloud Messaging (FCM) — for web push and Android
  • Apple Push Notification Service (APNs) — for iOS (if there's a mobile app)
  • Third-party platforms: OneSignal, Pushwoosh, SendPulse — with built-in segmentation

For Bitrix integration, the most practical option is OneSignal or custom token storage + FCM API.

Storing Tokens and User Attributes

Push subscription tokens are stored in a custom table:

CREATE TABLE custom_push_tokens (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT,
    token TEXT NOT NULL,
    platform ENUM('web', 'android', 'ios') DEFAULT 'web',
    created_at DATETIME,
    last_active DATETIME,
    INDEX idx_user (user_id),
    INDEX idx_platform (platform)
);

Attributes for segmentation are stored separately:

CREATE TABLE custom_push_user_attrs (
    user_id INT,
    attr_key VARCHAR(100),
    attr_value VARCHAR(255),
    updated_at DATETIME,
    PRIMARY KEY (user_id, attr_key)
);

Attributes are updated by Bitrix events: category view → last_category_viewed, purchase → last_purchase_date and total_orders, cart amount → cart_value.

Segmentation: What and How to Divide

Typical segments for an online store:

Segment Criteria Example Notification
Abandoned Cart cart_value > 0, last_cart_update > 2h "Your cart is waiting. Checkout now"
Active Customers total_orders >= 3 in 90 days Exclusive offer for loyal customers
New Users registration_date < 7 days Promo code for first order
Category Interest last_category_viewed = 'electronics' Electronics discount today
Inactive last_purchase_date > 60 days "We miss you" + special offer

Sending via FCM

Wrapper class for sending:

class PushSender {
    private const FCM_URL = 'https://fcm.googleapis.com/fcm/send';

    public function sendToSegment(array $filter, string $title, string $body, array $data = []): void {
        $tokens = $this->getTokensByFilter($filter);

        // FCM accepts max 500 tokens per request
        foreach (array_chunk($tokens, 500) as $chunk) {
            $this->sendBatch($chunk, $title, $body, $data);
        }
    }

    private function sendBatch(array $tokens, string $title, string $body, array $data): void {
        $payload = [
            'registration_ids' => $tokens,
            'notification' => [
                'title' => $title,
                'body' => $body,
                'icon' => '/favicon-192.png',
                'click_action' => $data['url'] ?? '/',
            ],
            'data' => $data,
        ];

        $http = new \Bitrix\Main\Web\HttpClient();
        $http->setHeader('Authorization', 'key=' . FCM_SERVER_KEY);
        $http->setHeader('Content-Type', 'application/json');
        $http->post(self::FCM_URL, json_encode($payload));
    }
}

Attribute Update Triggers

Segmentation attributes must update in real time. Implemented via Bitrix event handlers:

  • OnSaleOrderSaved → update total_orders, last_purchase_date
  • OnSaleBasketItemSaved → update cart_value
  • Custom event on catalog section view → last_category_viewed

Attribute updates — simple REPLACE INTO custom_push_user_attrs.

Browser Push Subscription

JavaScript to request permission and save token:

async function subscribeToPush() {
    const registration = await navigator.serviceWorker.register('/sw.js');
    const subscription = await registration.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: VAPID_PUBLIC_KEY
    });

    await fetch('/api/push/subscribe/', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(subscription)
    });
}

Execution Timeline

Scope Timeline
Token storage + basic sending 1–2 days
Attributes + 5–7 segments 2–3 days
Management UI + delivery analytics +2 days

Segmented push is a retention tool that pays for itself with a subscriber base of 5,000+.