Push Notifications
Send real-time notifications to users via the LoadSites Cloud relay. Handle notifications both as system alerts and in-app events.
Push notifications require a LoadSites license (Basic tier or higher). The notification relay infrastructure is managed by LoadSites Cloud. See Licensing below for tier details.
Architecture
Your Server LoadSites Cloud User's Device
┌──────────┐ HTTP POST ┌──────────────────┐ APNS ┌──────────────────┐
│ │ ─────────────► │ │ / FCM │ LoadSites App │
│ Backend │ │ Notification │ ───────► │ ┌────────────┐ │
│ Server │ device_key │ Relay Service │ │ │ Your CWA │ │
│ │ + license_key │ │ │ │ App │ │
└──────────┘ └──────────────────┘ │ └────────────┘ │
└──────────────────┘
- Your app requests a device key via the bridge.
- You send the device key to your backend server.
- Your server sends notifications to the LoadSites Cloud API using the device key + your license key.
- LoadSites Cloud delivers via APNS (iOS) or FCM (Android) — the standard platform push channels.
- The LoadSites container shows a system notification or forwards it to the open app.
All push notifications flow through Apple's APNS and Google's FCM — the same infrastructure used by all native apps. The LoadSites container does not implement custom background networking, persistent sockets, or polling. This ensures compliance with platform battery and background execution policies.
Client-Side Setup
Three steps to enable notifications in your CWA app:
Step 1: Declare the Permission
Add "notifications" to your manifest's permissions array:
{
"permissions": ["notifications", "haptics", "storage"]
}
Step 2: Request Permission & Get Device Key
async function setupNotifications() {
// Request OS-level notification permission
const perm = await LoadSites.notifications.requestPermission();
if (!perm.granted) {
console.log('User declined notifications');
return;
}
// Get the unique device key for this installation
const result = await LoadSites.notifications.getDeviceKey();
const deviceKey = result.deviceKey;
// Send the device key to your server
await fetch('https://your-api.com/register-device', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ deviceKey: deviceKey })
});
console.log('Notifications registered with key:', deviceKey);
}
Step 3: Handle In-App Notifications
When a notification arrives while the app is open, the container forwards it to your app instead of showing a system notification. Register a handler:
// Listen for notifications received while app is in foreground
LoadSites.notifications.onNotification(function(notification) {
// notification = {
// title: 'New Message',
// body: 'You have a message from Alice',
// data: { messageId: '123', sender: 'alice' }
// }
// Option A: Show an in-app toast
showToast(notification.title, notification.body);
// Option B: Update a badge count
updateBadgeCount(notification.data);
// Option C: Navigate to the relevant content
if (notification.data.messageId) {
navigateToMessage(notification.data.messageId);
}
});
When the app is in the foreground, the notification is delivered to your
onNotification callback and no system notification is shown.
When the app is in the background or closed, a system notification
is shown and tapping it opens the app.
Sending Notifications (Server-Side)
Send notifications from your backend server by POSTing to the LoadSites Cloud API:
Single Device
// Node.js example
const response = await fetch('https://cloud.loadsites.app/api/v1/notify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_LICENSE_KEY'
},
body: JSON.stringify({
device_key: 'target-device-key-here',
domain: 'yourdomain.com',
notification: {
title: 'Order Shipped',
body: 'Your order #1234 has shipped!',
data: {
orderId: '1234',
status: 'shipped'
}
}
})
});
Batch Sending
Send to multiple devices in a single request:
const response = await fetch('https://cloud.loadsites.app/api/v1/notify/batch', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_LICENSE_KEY'
},
body: JSON.stringify({
domain: 'yourdomain.com',
device_keys: [
'device-key-1',
'device-key-2',
'device-key-3'
],
notification: {
title: 'System Update',
body: 'Version 2.0 is now available',
data: { version: '2.0.0' }
}
})
});
API Response
{
"success": true,
"delivered": 3,
"failed": 0,
"errors": []
}
Notification Object
| Field | Type | Status | Description |
|---|---|---|---|
title |
string | Required | Notification title displayed to the user. |
body |
string | Required | Notification body text. |
data |
object | Optional | Custom key-value data payload. Delivered to onNotification callback and available when the user taps the notification. |
Handling Notifications in Your App
In-App (Foreground)
Use onNotification to handle notifications when the user is actively using your app.
Common patterns include:
- Toast / snackbar — Show a brief popup with the notification content
- Badge update — Increment an unread counter on a tab or icon
- Live update — Refresh the current view with new data from
notification.data - Sound / haptic — Play a chime or trigger
LoadSites.haptics.notification('success')
// Complete example: in-app notification handling
LoadSites.notifications.onNotification(function(notification) {
// Play haptic feedback
LoadSites.haptics.notification('success');
// Show a toast
const toast = document.createElement('div');
toast.className = 'in-app-toast';
toast.innerHTML = '<strong>' + notification.title + '</strong><p>' + notification.body + '</p>';
document.body.appendChild(toast);
// Auto-dismiss after 4 seconds
setTimeout(function() { toast.remove(); }, 4000);
// Handle the data payload
if (notification.data && notification.data.type === 'message') {
updateMessageBadge();
}
});
Background & Tap-to-Open
When the user taps a system notification to open the app, the notification data is available
through the normal app launch flow. The container stores the most recent notification and
delivers it via onNotification when the app initializes.
Unsubscribing
// Remove a specific callback
function myHandler(notification) { /* ... */ }
LoadSites.notifications.onNotification(myHandler);
// Later...
LoadSites.notifications.offNotification(myHandler);
Security Model
Push notifications are delivered through the platform's standard push infrastructure — Apple Push Notification Service (APNS) on iOS and Firebase Cloud Messaging (FCM) on Android. The LoadSites Cloud relay forwards notifications through these official channels; no custom background networking or persistent connections are used. This architecture complies with Apple and Google platform policies for push notification delivery.
- Notifications are scoped to your domain — you can only send to devices that installed your app
- The
device_keyis unique per device + domain combination - Your
license_keyauthenticates requests to the Cloud API - The
datapayload is encrypted in transit (HTTPS/TLS) - Users can disable notifications per-app from the LoadSites home screen
- CWA apps cannot send notifications without the user granting OS-level permission
- The
notificationspermission must be declared in the manifest and accepted at install time
Best Practices
- Request permission at the right time — Don't ask immediately on first load. Wait until the user takes an action that makes notifications relevant (e.g., enabling alerts for an order).
- Keep payloads small — The
dataobject should be lightweight. Use it to reference content, not to carry it. - Handle foreground gracefully — Always register an
onNotificationhandler. A system notification when the app is already open feels jarring. - Respect the toggle — Users can disable notifications via the toggle on their home screen card. Check
isAllowed()before prompting. - Batch when possible — Use the batch API for broadcasts to reduce API calls and improve delivery speed.
Licensing
Push notifications are the only CWA feature that requires a paid license. The license key
is included in your manifest (license_key field) and used to authenticate
Cloud API calls.
| Tier | Monthly Price | Notifications / Month | Features |
|---|---|---|---|
| Free | $0 | 0 | All bridge APIs except notifications |
| Basic | $9 | 10,000 | Push notifications, email support |
| Pro | $29 | 100,000 | Push notifications, priority support, analytics dashboard |
| Enterprise | Custom | Unlimited | Custom SLA, dedicated infrastructure, white-label option |
Camera, haptics, biometrics, geolocation, storage, share, clipboard, network, device info, and navigation — all available at no cost, no license needed.
Troubleshooting
Notifications not arriving
- Verify the
license_keyin your manifest is valid and active - Check that the user has enabled notifications (use
isAllowed()) - Ensure the
device_keyis correct and the device is reachable - Check the Cloud API response for error details
onNotification not firing
- Make sure you register the callback early (before any notifications could arrive)
- Verify the app is actually in the foreground — background notifications show as system alerts
- Check the browser console for errors in your callback function