SfSkills Domains Docs GitHub

Home / admin / custom-notification-types

custom-notification-types

Custom Notification Types for desktop/mobile push alerts from Flow or Apex: type creation, target channels, Messaging.CustomNotification invocation, recipient limits, bulk notification patterns. NOT for choosing channels, consent, or notification-fatigue policy — use admin/custom-notification-type-design. NOT for email alerts — use admin/email-templates-and-alerts. Trigger keywords: notiftype, notificationtypes directory, customNotifTypeName, customNotificationAction, setNotificationTypeId, targetPageRef, NotificationTypeConfig.

Open the skill folder on GitHub


Custom Notification Types

Activate when designing push or desktop notifications triggered from Flow, Apex, or process automation. Custom Notification Types replaced the older Chatter-only notification path; they support both desktop and mobile push channels, can be invoked from Flow or Apex, and have specific recipient limits that bite at scale.

Before Starting

Questions to Ask Before Configuring

Ask these before creating the type; the answers decide the metadata, the send path, and the test. An LLM that skips them produces a type that deploys clean and delivers to nobody.

AskWhy it mattersWhat a good answer adds
"Which channels must this reach — desktop bell, mobile push, or both?"desktop and mobile are required booleans on the type and both default to false on the sObject; the send call cannot override themThe two flags on the .notiftype, and whether a real-device test is in scope
"Is the audience a list of people, or a membership?"The 500 cap counts Ids, not recipients — one Queue or Group Id covers thousands, a hand-built user set does notWhether a chunking loop is needed at all, or one group Id replaces it
"What does the recipient open when they tap it?"A target is mandatory: omitting both targetId and targetPageRef throws, and a target the recipient can't read lands them on Insufficient PrivilegesA record Id, a pageReference, or the documented dummy Id — decided, not defaulted
"How many notifications does the worst-hour burst produce?"Ten push notification method calls per Apex transaction, and an hourly org push allocation that fails open to the bellA fan-out sized in send calls, and a decision on suppressing bulk-load traffic
"Who is the running user when this fires — system context, or an end user?"Sending needs the Send Custom Notifications permission, and the type lookup runs in user mode; both fail as something other than a permission errorThe permission set that grants it, and a least-privileged test user
"Does this org already have a type that means the same thing?"Type names are unique org-wide and not namespaced, so the second team to want "case escalated" collides with the firstA reuse-or-create decision before the name is burned
"Which orgs will this deploy to, and what resolves the type Id in each?"The 0ML… Id is org-specific; the manifest can't wildcard the typeA run-time lookup by DeveloperName and an explicit package.xml member list

What a proper configuration adds over just clicking "New Custom Notification Type": the channels are asserted rather than assumed, the audience is expressed as the smallest set of Ids that describes it, the deploy carries the type and its delivery settings, and the failure modes that report as success are caught before a user does.


Core Concepts

Notification Type record

Created in Setup → Custom Notifications. Has a Name (label), API Name (DeveloperName), and channel checkboxes. DeveloperName is the handle used in Apex/Flow.

Messaging.CustomNotification (Apex)

Messaging.CustomNotification n = new Messaging.CustomNotification();
n.setTitle('Opportunity Closed');
n.setBody('Opportunity ' + oppName + ' was won.');
n.setNotificationTypeId(typeId);
n.setTargetId(oppId);
n.send(new Set<String>{ userId });

setNotificationTypeId takes the CustomNotificationType.Id; resolve via SOQL or describe.

Send Custom Notification (Flow Action)

Core action in Flow Builder. Accepts type API name, recipients (user ids, queue ids, group ids), title, body, target record id. Good for no-code paths.

Recipient resolution

Recipient IDs can be User, Group (queue or public group). Notifications deliver to active users in the group.

Common Patterns

Pattern: Owner notification on record change

Record-triggered Flow → Decision → Send Custom Notification with [$Record.OwnerId].

Pattern: Apex bulk fan-out

Aggregate target user IDs into sets of 500; loop n.send(batch) per batch. Do not exceed 500 per call.

Pattern: Type ID resolution via Custom Metadata

Store NotificationTypes__mdt with DeveloperName; Apex helper queries once per transaction and caches.

Decision Guidance

NeedMechanism
No-code notification on record changeFlow + Send Custom Notification action
Bulk programmatic send (dozens+)Apex Messaging.CustomNotification
Email + pushSeparate email alert + custom notification
Delivery guarantee with retryQueueable wrapper with retry; not built-in
Notifications only on desktopType with Desktop channel checked, Mobile unchecked
  1. Answer the questions above, then check whether the org already has a type that means the same thing: SELECT DeveloperName, MasterLabel, Desktop, Mobile FROM CustomNotificationType. Names are unique org-wide and not namespaced.
  2. Author the type, not just the checkbox. Write notificationtypes/<DevName>.notiftype-meta.xml from references/metadata-examples.md §1 — customNotifTypeName, masterLabel as customer copy, description, and both channel booleans set deliberately. If the org manages delivery settings as metadata, add the paired NotificationTypeConfig entry from §2.
  3. Pick the send path. Flow for record-triggered, single-audience sends (references/metadata-examples.md §3, and flow/flow-email-and-notifications for the Builder-side inputs); Apex when the audience is computed, the volume needs async placement, or you need try/catch around the send (§4, and apex/apex-custom-notifications-from-apex for the class). Either way the type Id is resolved at run time by DeveloperName — never pasted.
  4. Resolve the audience and the target using §5 and §6: the smallest set of Ids that describes the audience, and an explicit targetId, targetPageRef, or documented dummy Id.
  5. Lint before deploy. python3 scripts/check_custom_notification_types.py --manifest-dir force-app/main/default — it fails on a type with no channel enabled and on a hard-coded 0ML… Id in Apex or in a Flow's customNotificationAction, and reports types no Flow or class references.
  6. Deploy the type before its callers with the explicit package.xml from §7 (this type has no wildcard support), using the retrieve/validate/deploy commands in §8.
  7. Verify three separate things per §9: the row exists with a channel enabled, the bell lights up for a real recipient, and the tap lands on the target as that recipient — not as an admin. A green bell is not evidence that push works.

Review Checklist

Salesforce-Specific Gotchas

  1. send() throws for some failures and stays silent for others. It does throw when no target is set at all (apexrefguide.txt:166573) and can throw generally (apexrefguide.txt:166648) — but a recipient who is inactive is simply skipped, because delivery is documented as "sent to this user, if this user is active" (apexrefguide.txt:166770). A clean send() is not evidence anyone received it; monitor via debug log or platform events.
  2. Mobile push requires Connected App push credentials. Setup → Mobile → Notification Settings must be configured.
  3. Custom notifications do not respect user notification preferences for desktop. Users cannot opt out per-type from the bell.

Output Artifacts

ArtifactDescription
Notification Type catalogType × channel × recipients × business event
Apex helper classType ID resolver + bulk send wrapper
Flow action templateReusable subflow for record-owner notifications

Reference Files

FileRead it when
references/metadata-examples.mdWriting or reviewing the .notiftype XML, the NotificationTypeConfig pairing, the Flow customNotificationAction element, the Apex send, package.xml, the retrieve/deploy commands, or the post-deploy verification
references/gotchas.mdA notification deploys and delivers to nobody, the bell works but push doesn't, send() throws, the fan-out dies partway, or the type lookup fails for non-admins
references/examples.mdSizing a requirement: which shapes fit a Flow send, which need Apex, and when a custom notification is the wrong channel entirely
references/llm-anti-patterns.mdReviewing AI-generated notification code before you run it
references/well-architected.mdJustifying the channel choice against the pillars, or chasing the official source behind a claim here
templates/custom-notification-types-template.mdCapturing the decisions — channels, audience shape, target, volume — before any XML is written
scripts/check_custom_notification_types.pyLinting notificationtypes/, flows/, and classes/ in a DX tree before deploying

Package files