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.
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
- 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).
- A bridge notices. The
PushDatabaseNotificationslistener reacts to theNotificationSentevent — only for notifications that went to the database channel. - A payload is built.
PushServicedecides whether the notification has a linked entity and builds the payload, including a deep link in the formcrm://{entity_type}/{entity_id}. - A job is queued.
SendPushToUserruns 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. - The phone receives it. The Android app's
LeadHubMessagingServicemaps the payload to the correctcrm://deep link and shows the notification. - Tapping navigates. The deep link opens the right screen — lead, call, appointment or task.
What deep-links to what
| 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:
- The workspace's own Firebase service account (
settings.push.firebase_service_account_json) — bring-your-own-Firebase. - The platform's configured service account (platform settings row).
- 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\PushDatabaseNotificationsreacts toNotificationSent(database channel) →PushService::buildPayload()→SendPushToUserjob →FcmPushProvider(FCM v1, data-only payload). - Token resolution: the user's registered devices (
devices.push_token), populated by the app'sPushRegistration. - Entity map (
PushService::ENTITY_LINKS):lead_id→ lead,call_id/lead_call_id→ call,appointment_id→ appointment,task_id/followup_id→ followup; deep link formatcrm://{entity_type}/{entity_id}. - Service account precedence: tenant
settings.push.firebase_service_account_json→ platform settings →services.fcm.service_account_jsonenv.
Related guides
Was this page helpful?
Thanks — noted. ✦