Zodiac Tech CRM Docs

How push notifications work

From a CRM event to a notification on a sales agent's phone — the database notification bridge, FCM delivery, and the crm:// deep link that opens the right screen.

everyone Medium ⏱ 8 min Updated 2026-10-05

How push notifications work

When something happens in the CRM that a person must know about — a lead is assigned, a call is logged, an appointment approaches — the CRM sends them a notification. In the browser it appears in the notification bell. On the Android app, the same notification also arrives as a push, and tapping it opens the exact screen the notification is about.

Push is optional per workspace: it works out of the box through the platform's Firebase configuration, and a workspace can bring its own Firebase project for full control.

sequenceDiagram
    autonumber
    participant E as CRM event (lead, call, task…)
    participant N as Database notification
    participant L as PushDatabaseNotifications listener
    participant J as SendPushToUser job
    participant F as FCM (v1)
    participant A as Android app

    E->>N: e.g. LeadAssigned notification
    N->>L: NotificationSent (database channel)
    L->>L: PushService builds payload + deep link
    L->>J: dispatch SendPushToUser
    J->>F: data-only push message
    F-->>A: delivered to device
    A->>A: crm://{entity_type}/{entity_id} → opens screen

The trace in plain language

  1. An event happens. The CRM creates a database notification for a user (this is the same notification you see under the bell in the web app).
  2. A bridge notices. The PushDatabaseNotifications listener reacts to the NotificationSent event — only for notifications that went to the database channel.
  3. A payload is built. PushService decides whether the notification has a linked entity and builds the payload, including a deep link in the form crm://{entity_type}/{entity_id}.
  4. A job is queued. SendPushToUser runs on the queue and hands the message to the FCM provider (FcmPushProvider, Firebase Cloud Messaging v1 API), as a data-only message — the app, not Google, decides how to present it.
  5. The phone receives it. The Android app's LeadHubMessagingService maps the payload to the correct crm:// deep link and shows the notification.
  6. Tapping navigates. The deep link opens the right screen — lead, call, appointment or task.
Entity key in the payload Opens
lead_id The lead's record (Lead 360)
call_id / lead_call_id The call record
appointment_id The appointment
task_id / followup_id The follow-up task

Notifications without an entity still arrive Notifications that are not tied to a record (for example a general announcement) are still pushed — they just open the app's notifications screen instead of a record.

Where Firebase credentials come from

Push resolution is layered — the first configured source wins:

  1. The workspace's own Firebase service account (settings.push.firebase_service_account_json) — bring-your-own-Firebase.
  2. The platform's configured service account (platform settings row).
  3. The server's environment (services.fcm.service_account_json).

If none is configured, pushes are simply not sent; in-app notifications continue to work. Nothing breaks.

BYO-Firebase is mobile-team work Connecting a workspace's own Firebase project is a technical step (service account JSON, project access). Most workspaces use the platform configuration and never touch this. See Push notifications (FCM).

Troubleshooting notes

Symptom Likely cause Fix
In-app bell works, phone silent No Firebase service account configured, or notification permission denied on the phone Check the push settings; on the phone: Settings → Notifications → allow LeadHub
Pushes worked, then stopped Android battery optimisation killed the app's background process Exclude LeadHub from battery optimisation
Push arrives but tap opens the wrong screen The record was deleted, or the app is outdated Update the app; deep links fall back to the app home when the entity is unknown
Only some users get pushes Their device never registered (app not installed / not logged in) Check the team status table in Mobile app setup
Push delayed by minutes Device in Doze mode / poor connectivity Normal Android behaviour; critical in-app notifications are always instant

Technical details

  • Listener: App\Listeners\PushDatabaseNotifications reacts to NotificationSent (database channel) → PushService::buildPayload() → SendPushToUser job → FcmPushProvider (FCM v1, data-only payload).
  • Token resolution: the user's registered devices (devices.push_token), populated by the app's PushRegistration.
  • Entity map (PushService::ENTITY_LINKS): lead_id → lead, call_id / lead_call_id → call, appointment_id → appointment, task_id / followup_id → followup; deep link format crm://{entity_type}/{entity_id}.
  • Service account precedence: tenant settings.push.firebase_service_account_json → platform settings → services.fcm.service_account_json env.

Was this page helpful?