Setting up a push notification for abandoned viewing 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
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1212
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    815
  • 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
    565
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    657
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    980

Setting up push notification for abandoned product view in 1C-Bitrix

15–20% of recipients open email about abandoned view — those who open email at all. Push notification in the browser appears immediately, without needing to open email. Push has higher click-through rate if the notification arrives 20–40 minutes after view, not in a day. Setting up this mechanics in Bitrix requires integrating the push.sender module with abandoned view logic.

Delivery architecture

Push notification path: Bitrix agent → MessageSender::send() method → queue in b_agent → POST request to browser push endpoint (FCM for Chrome, Mozilla Autopush for Firefox). Subscriptions are stored in b_push_sender_subscription with fields FUSER_ID, USER_ID, ENDPOINT, AUTH, P256DH.

Critical moment: b_push_sender_subscription contains records for both anonymous users (via FUSER_ID) and authorized users (via USER_ID). When working with abandoned views you need to search for subscription by FUSER_ID since the view could have been anonymous.

Linking view trigger with push subscription

The abandoned view agent (described in separate service) finds pair (fuser_id, product_id). Next step — find active push subscription:

$subscription = \Bitrix\PushSender\Model\SubscriptionTable::getList([
    'filter' => [
        'FUSER_ID' => $fuserID,
        '=STATUS' => 'ACTIVE',
    ],
    'order' => ['DATE_INSERT' => 'DESC'],
    'limit' => 1,
])->fetch();

if ($subscription) {
    // Subscription exists — send push
} else {
    // Fall back to email via b_subscribe_subscriber
}

The STATUS field in b_push_sender_subscription can be ACTIVE, UNSUBSCRIBED or EXPIRED. Before sending check exactly ACTIVE — otherwise we get 410 Gone from FCM and pollute logs.

Forming notification payload

Web Push payload is limited to 4 KB. For abandoned view sufficient: title, text, product URL, image URL. Product data taken from infoblock:

$product = \CIBlockElement::GetByID($productId)->GetNextElement();
$fields = $product->GetFields();
$props  = $product->GetProperties();

$imageId  = $fields['PREVIEW_PICTURE'] ?: $fields['DETAIL_PICTURE'];
$imageUrl = \CFile::GetPath($imageId);

\Bitrix\PushSender\MessageSender::send(
    \Bitrix\PushSender\MessageSender::TYPE_PUSH,
    [
        'FUSER_ID' => [$fuserID],
        'TITLE'    => 'You viewed: ' . $fields['NAME'],
        'MESSAGE'  => 'Item still in stock. Back to selection?',
        'URL'      => $fields['DETAIL_PAGE_URL'],
        'IMAGE'    => $imageUrl,
        'TAG'      => 'abandoned_view_' . $productId,
    ]
);

The TAG field is Web Push notification tag. If user viewed 5 products and didn't buy any, without tag they get 5 separate notifications. With one tag — each new notification replaces the previous, which is correct from UX perspective.

Sending time and relevance window

Push about abandoned view loses meaning in 3–4 hours. If user didn't open browser in that period, notification arrives later — and becomes inappropriate. Solution: set TTL (Time-To-Live) in FCM request. In Bitrix this is passed via additional options in MessageSender::send(), but standard method doesn't support TTL directly. You need to extend \Bitrix\PushSender\Transport\WebPush class and pass header TTL: 3600 in POST request to endpoint.

Alternatively — check in agent: if b_push_sender_subscription.DATE_INSERT is older than 30 days and no activity — subscription is likely stale, skip.

Mobile app scenario

If the store has mobile app on Bitrix Mobile Framework, push goes via APNs/FCM directly. Subscriptions in this case are stored in b_push_sender_device (not b_push_sender_subscription). Logic is similar but fields differ: DEVICE_ID, TOKEN, PLATFORM (ios/android).

What we configure

  • Finding push subscriptions by FUSER_ID in b_push_sender_subscription
  • Forming payload with product data from infoblock
  • Using TAG field to replace duplicate notifications
  • Setting TTL via extending WebPush transport class
  • Email fallback when push subscription doesn't exist
  • Deduplication table shared with abandoned view trigger