Setting up push notifications by geofence 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
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • 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
    564
  • 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
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

Setting Up Geo-Zone Push Notifications in 1C-Bitrix

Push notifications by geo-zone are a specific case of geofencing focused on the delivery channel. The goal: when a user enters a set radius around a point, they receive a push notification on their phone. This article covers the server-side implementation in Bitrix.

Push Delivery Stack

Two channels exist for mobile push notifications:

  • FCM (Firebase Cloud Messaging) — Android and iOS (via Firebase APNs proxy)
  • APNs (Apple Push Notification service) — iOS directly

For websites without a mobile app, Web Push (W3C standard) exists, but it requires an open browser or Service Worker support and does not work in iOS Safari prior to iOS 16.4.

Bitrix has a built-in push.sender module — but it is intended for Bitrix24 and the Push & Pull server. For custom push notifications in a mobile app, FCM is used directly from PHP.

Registering and Storing Device Tokens

Before sending a push, you need to obtain the user's device token. The app requests permission on first launch, receives a token from FCM/APNs, and then sends it to the server.

Endpoint for token registration (/local/ajax/register-token.php):

$userId      = $USER->GetID();
$deviceToken = $data['token'];
$platform    = $data['platform']; // 'android' or 'ios'

// Save to HL-iblock DeviceTokens
\Local\Push\DeviceTokenTable::add([
    'UF_USER_ID'  => $userId,
    'UF_TOKEN'    => $deviceToken,
    'UF_PLATFORM' => $platform,
    'UF_UPDATED'  => new \Bitrix\Main\Type\DateTime(),
]);

One user may have multiple tokens (phone + tablet). Tokens expire — FCM returns a NotRegistered error, which should trigger deletion of the token from the database.

Geo-Zone Trigger

A geo-zone event arrives from the mobile app (for native geofencing logic, see the geofencing notifications article). The server-side receives the event and looks up all active tokens for the user:

$tokens = \Local\Push\DeviceTokenTable::getList([
    'filter' => ['=UF_USER_ID' => $userId, '=UF_ACTIVE' => true],
    'select' => ['UF_TOKEN', 'UF_PLATFORM'],
])->fetchAll();

foreach ($tokens as $token) {
    \Local\Push\Sender::send(
        $token['UF_TOKEN'],
        $token['UF_PLATFORM'],
        $zone['UF_PUSH_TITLE'],
        $zone['UF_PUSH_BODY'],
        ['zone_id' => $zoneId, 'action' => 'open_promo']
    );
}

Sending via FCM HTTP v1 API

Google is migrating from the legacy FCM API to HTTP v1 (OAuth2). Example of sending a single push:

namespace Local\Push;

class Sender {
    public static function send(
        string $token,
        string $platform,
        string $title,
        string $body,
        array $data = []
    ): bool {
        $accessToken = self::getOAuthToken(); // OAuth2 via Service Account JSON

        $message = [
            'message' => [
                'token' => $token,
                'notification' => [
                    'title' => $title,
                    'body'  => $body,
                ],
                'data' => array_map('strval', $data),
            ],
        ];

        $http = new \Bitrix\Main\Web\HttpClient();
        $http->setHeader('Authorization', 'Bearer ' . $accessToken);
        $http->setHeader('Content-Type', 'application/json');
        $response = $http->post(
            'https://fcm.googleapis.com/v1/projects/' . FCM_PROJECT_ID . '/messages:send',
            json_encode($message)
        );

        $result = json_decode($response, true);
        return isset($result['name']); // name is present on success
    }
}

For getOAuthToken(), use the Google Client Library or a custom JWT-signing implementation with a Service Account.

Custom Sound and Icon

For Android notifications, you can set a notification channel, sound, and icon via the android section in the FCM payload. For iOS — via the apns section. These parameters are defined during mobile app development; the server-side only passes the values.

Delivery Monitoring

FCM HTTP v1 returns a result immediately, but this is only confirmation that the message was accepted for processing, not proof of delivery. Tracking notification opens requires analytics on the app side (Firebase Analytics or a custom endpoint).

Stage Time
Token storage (HL-iblock + API) 3–4 h
FCM HTTP v1 integration 4–6 h
Geo-zone event handler 2–3 h
Deduplication / cooldown logic 2–3 h
Testing on real devices 3–5 h