Settings — Notifications
Audience: Support · QA · Sales · Engineering · Management · Where in app: Settings → Notifications (/settings/notifications) · Plan availability: All plans (no permission gate on this user screen)
This is the personal Notification Settings screen. It controls a per-user new-visitor notification sound, the user's mobile push preferences (user.push_preferences), and — on the desktop app only — whether the app launches when you sign in to your computer. It is not where the broad set of company event notifications (email transcripts, Slack, missed-call emails, reports email) are configured; those live elsewhere (see How channels relate and the Notifications module).
What it does
- New Visitor Notification — toggles a sound that plays when a new visitor lands on the website. Saved on the user record (
notification_tune). - Push preferences — category toggles + quiet hours for mobile push, saved on
user.push_preferences(see Push notifications). - Launch on startup (desktop only) — toggles whether the Electron desktop app auto-starts at OS login. Saved at the OS level via Electron IPC, not in the database.
- A collapsible Learn panel explains the feature and tips.
How it works
The view (settings/Notifications.vue) loads the current user and reads user.notification_tune. Each toggle saves immediately (no separate Save button):
New visitor sound
- Toggling calls
PUT /user/<id>with{ notification_tune: <bool> }, then updates the app store with the returned user. - On failure it reverts the toggle and shows an error.
- Backend default for
notification_tuneistrue(UserModel).
Launch on startup (desktop)
- Only rendered when running in the desktop app (
isElectron()) and the platform reports support (launchAtLoginSupported). - On mount,
launch-at-login-getIPC reads the current OS setting. - Toggling calls
launch-at-login-setIPC; if the platform doesn't support it, the toggle is hidden and an error toast is shown. - This is a machine-local OS preference (macOS/Windows) — it is not stored on the user/company record and does not sync across devices.
Configuration & options
| Setting | Scope | Persisted to | Default | Visibility |
|---|---|---|---|---|
| New Visitor Notification (sound) | Per user | user.notification_tune via PUT /user/<id> | true | Always |
| Push category toggles + quiet hours | Per user | user.push_preferences via GET/PUT /user/push-preferences (partial $set merge; the generic PUT /user/<id> clobbers the whole subdoc, which is why the dedicated endpoint exists — declared above /user/:_id) | all on; quiet 21→7 | Always |
| Launch on startup | Per machine | OS (Electron app.setLoginItemSettings) via IPC | OS-dependent | Desktop app only, where supported |
Push notifications (FCM)
Server-side push gating is centralized in NotificationHelper.sendNotification
(backend/app/helpers/NotificationHelper.js); delivery via FcmService to
UserDeviceModel tokens (stale tokens are forgotten on FCM error).
- Per-user preferences —
user.push_preferences(UserModel): category togglesleads,live_calls,funnel_returns,agent_k,morning_nudge,other(all defaulttrue);leads_24_7(defaultfalse) exempts tier-1 lead pushes from quiet hours;quiet_hours_start/quiet_hours_end(hours 0–23, user-local timezone, defaults 21 / 7). The 21/7 defaults must matchNotificationHelper._pushDecision's fallbacks — change both together. - Rules —
NotificationHelper.PUSH_RULESmaps notification type →{ tier, group }: tier 1 always pushes (cap-exempt, quiet-hours gated), tier 2 capped atDAILY_PUSH_CAP = 3/user/day (overflow lands in the in-app feed), tier 3 scheduled digests. Unmapped types default to tier 2, groupother. Per-entity collapse: one push per lead/session/contact per 15 min (DEDUP_TTL_SECONDS = 900), regardless of event types. - Dispatch endpoint —
POST /internal/knox/notifications/dispatch(KnoxNotificationsController@dispatch,internalKnoxRoutes.js, x-api-key via the sharedapiKeyAuth) lets other services fan out pushes; a caller-supplieddedup_keycollapses repeat fires within 15 min via Redis SETNX. - Trigger sites —
ChatController,GoHighLevelController,UserSessionController,DailyBriefEmailJob,AgentKTrickleJob,NoxFunnelInterceptService; ms-communication live-call events arrive via the dispatch endpoint. - Test —
backend/test/notification-push-gating.spec.jscovers the gating matrix. Super-admins have a live tester at/admin/push-test(dry run, skip-dedupe, pipeline trace).
How channels relate
The broader notification system (in-app bell, desktop toast, push/FCM, email, Slack, webhooks) is company-configured and event-driven — it is not controlled from this screen. Per the data model and the Notifications module:
| Channel | Backed by |
|---|---|
| In-app | Notification bell/drawer (NotificationModel) |
| Desktop toast | Native OS notification (desktop app) |
| Push | Firebase Cloud Messaging (mobile + desktop) |
SMTP via MailService | |
| Slack | SlackService to a chosen channel |
| Webhook | Outbound HTTP when enabled and subscribed |
Company-level event toggles live on company.notifications.* (e.g. chat_transcript, call, missed_call, reports_email, daily_recap_email, slack_new_visitor, slack_hot_lead) and are managed on the Organization Notifications screen (/settings/organization/notifications, gated by settings.organization), not here.
Company-vs-user precedence
Per the notifications knowledge base, user-level preferences only fire if the company-level toggle allows it — the company toggle is the outer gate, the user preference the inner one. The new-visitor sound (notification_tune) is a personal client-side sound and is independent of the company event toggles. Per-user push gating is fully defined by user.push_preferences + NotificationHelper.PUSH_RULES (see Push notifications).
Behaviors & edge cases
- Immediate save, optimistic UI: the sound toggle updates instantly and rolls back on API error (with a toast).
- No permission gate: the route has no
permissionmeta — any signed-in user can set their own sound. - Desktop-only startup toggle: hidden entirely in the browser, and also hidden if the OS doesn't support login items.
- Web vs desktop notification delivery differs (toasts/ringtone/dock count are desktop-only); see the Notifications module for desktop specifics.
- Don't confuse screens: "Settings → Notifications" (this page) is personal and minimal; "Settings → Organization → Notifications" is the company event configuration.
Plan & limits
Available on all plans with no permission gate on this personal screen. The company event channels it relates to (Slack, email templates, reports email) may depend on integrations being connected and on plan tier — verify with the Notifications module and pricing.
Technical implementation
- View:
frontend/src/views/settings/Notifications.vue - Route: name
settings-notifications, path/settings/notifications, meta{ title: 'Notification Settings' }(no permission) —frontend/src/router/index.js - User field:
notification_tune(backend/app/models/UserModel.js, defaulttrue), updated viaPUT /user/<id> - Desktop IPC:
launch-at-login-get/launch-at-login-set(@/utils/platform→ Electron main process) - Company-side config (separate screen):
frontend/src/views/settings/organization/Notifications.vue,company.notifications.*, delivered byNotificationHelper/MailService/SlackService. See services/backend.
Related
- Notifications (events) — the full event/channel system this screen plugs into.
- Settings — Working Hours — gates after-hours pushes and missed-call emails.
- Settings — Nox — Nox's visitor alerts include a "quiet push outside business hours" option.
- Desktop Overview — desktop toasts, ringtone, and the launch-on-startup behavior.