Notifications & FCM Token
Bridges for requesting push notification permission and retrieving the Firebase Cloud Messaging (FCM) token.
Android
Bridge object: AndroidNotification
Methods
Method | Return | Description |
|---|
requestNotificationPermission()
| void
| Prompts the user for notification permission (Android 13+) |
setNotifyOnStartup(enabled)
| void
| Persists whether to request notification on app start |
getNotifyOnStartup()
| boolean
| Returns the persisted notify-on-startup setting (default false) |
getFirebaseToken()
| string
| Returns the FCM token synchronously (may be empty) |
requestFirebaseToken()
| void
| Requests a fresh token; result dispatched via event |
sendLocalNotification(payload)
| void
| Schedules/displays a local notification from website payload |
Events
Listen for these CustomEvents on window:
Event name | event.detail shape
| Description |
|---|
mobiweb:notificationPermission
| { granted: boolean }
| Result of permission request |
mobiweb:fcmToken
| { token: string, oldtoken?: string }
| New or refreshed FCM token |
mobiweb:cookiesCleared
| { success: boolean }
| Result of cookie clearing |
Example
// Request permission
AndroidNotification.requestNotificationPermission();
// Listen for result
window.addEventListener('mobiweb:notificationPermission', (e) => {
console.log('Granted:', e.detail.granted);
});
// Get token synchronously
const token = AndroidNotification.getFirebaseToken();
// Request token, listen for event
AndroidNotification.requestFirebaseToken();
window.addEventListener('mobiweb:fcmToken', (e) => {
console.log('FCM token:', e.detail.token);
});
iOS
Bridge object: AppleNotification (injected shim)
The iOS shim exposes the same intent as Android but communicates via WKScriptMessageHandler.
Methods
Method | Return | Description |
|---|
AppleNotification.requestNotificationPermission()
| void
| Prompts the user for notification permission |
AppleNotification.requestToken()
| void
| Requests an FCM token |
AppleNotification.getToken()
| string
| Returns the cached FCM token synchronously |
AppleNotification.isTokenValid()
| boolean
| Returns whether the cached token is valid |
AppleNotification.sendLocalNotification(payload)
| void
| Schedules/displays a local notification from website payload |
Events
Event name | event.detail shape
| Description |
|---|
mobiweb:appleNotificationPermissionResult
| { granted: boolean }
| Result of permission request |
mobiweb:appleNotificationToken
| { token: string, oldtoken?: string }
| New or refreshed FCM/APNs token |
Example
// Request permission (iOS)
AppleNotification.requestNotificationPermission();
window.addEventListener('mobiweb:appleNotificationPermissionResult', (e) => {
console.log('Granted:', e.detail.granted);
});
// Get token synchronously
const token = AppleNotification.getToken();
// Request token via event
AppleNotification.requestToken();
window.addEventListener('mobiweb:appleNotificationToken', (e) => {
console.log('Token:', e.detail.token);
});
Local Notification Payload
sendLocalNotification(payload) accepts notification configuration at the root level (same keys currently used by push data payloads) plus optional custom data and trigger settings.
{
title: 'Payment Reminder',
body: 'Tap to complete your payment',
// Existing notification config keys still work (sound, silent, badge, color, group, etc.)
sound: 'default',
data: {
url: 'https://example.com/pay/123',
orderId: '123'
},
trigger: {
// 'immediate' | 'delay' | 'time' | 'exit' | 'home'
type: 'delay',
delayMs: 10_000
// delayMs also works with 'home' and 'exit'
// For specific time use: at: Date.now() + 60_000
}
}
Trigger options:
Trigger | Payload example |
|---|
Immediate | { trigger: { type: 'immediate' } } or omit trigger
|
Delay | { trigger: { type: 'delay', delayMs: 5000 } }
|
Specific time | { trigger: { type: 'time', at: Date.now() + 60000 } }
|
On home screen | { trigger: { type: 'home' } }
|
On home screen + delay | { trigger: { type: 'home', delayMs: 5000 } }
|
On app exit | { trigger: { type: 'exit' } }
|
On app exit + delay | { trigger: { type: 'exit', delayMs: 5000 } }
|
Behavior notes:
function requestNotificationPermission() {
if (typeof AndroidNotification !== 'undefined') {
AndroidNotification.requestNotificationPermission();
window.addEventListener('mobiweb:notificationPermission', (e) => {
console.log('Android granted:', e.detail.granted);
}, { once: true });
} else if (typeof AppleNotification !== 'undefined') {
AppleNotification.requestNotificationPermission();
window.addEventListener('mobiweb:appleNotificationPermissionResult', (e) => {
console.log('iOS granted:', e.detail.granted);
}, { once: true });
}
}
function sendLocalNotification(payload) {
if (typeof AndroidNotification !== 'undefined') {
AndroidNotification.sendLocalNotification(payload);
} else if (typeof AppleNotification !== 'undefined') {
AppleNotification.sendLocalNotification(payload);
}
}
03 May 2026