Web SDK
Integrating Notify Partners push notifications into a web application — installation via npm, Service Worker setup, SDK initialization, and full API reference.
Requirements
- Modern browser with Service Worker and Push API support (Chrome, Firefox, Edge, Safari 16+)
- Site served over HTTPS (or localhost for development)
- VAPID key from the Notify Partners dashboard
app_idfrom the Notify Partners dashboard
1. Installation
npm
npm install @notify.partners/web-sdkCDN
<script src="https://cdn.jsdelivr.net/npm/@notify.partners/web-sdk/dist/notify-partners-sdk.umd.js"></script>When loaded via CDN, access the SDK as NotifyPartners.NotifyPartnersSDK.
2. Service Worker Setup
Copy the service worker file to the root of your site:
cp node_modules/@notify.partners/web-sdk/dist/notify-partners-sw.js public/The file must be accessible at /notify-partners-sw.js. To use a different path, set serviceWorkerPath in the config.
your-project/
├── index.html
├── notify-partners-sw.js ← Service Worker
└── ...3. SDK Initialization
Basic
import { NotifyPartnersSDK } from '@notify.partners/web-sdk';
NotifyPartnersSDK.initialize({
appId: 'YOUR_APP_ID',
vapidKey: 'YOUR_VAPID_KEY',
});That's it. The SDK automatically handles:
- Notification permission request
- Service Worker registration and Web Push subscription
- Lifecycle tracking (page visible / hidden / closed)
- Periodic device info updates
With Listener
import { NotifyPartnersSDK } from '@notify.partners/web-sdk';
NotifyPartnersSDK.initialize({
appId: 'YOUR_APP_ID',
vapidKey: 'YOUR_VAPID_KEY',
externalId: 'user-123',
debug: true,
listener: {
onInitialized(instanceId) {
console.log('SDK ready:', instanceId);
},
onInitializationFailed(error) {
console.error('Init failed:', error.type, error.message);
},
onMessageReceived(msgId, title, body, data) {
console.log('Push received:', title);
},
},
});CDN / Script Tag
<script src="https://cdn.jsdelivr.net/npm/@notify.partners/web-sdk/dist/notify-partners-sdk.umd.js"></script>
<script>
NotifyPartners.NotifyPartnersSDK.initialize({
appId: 'YOUR_APP_ID',
vapidKey: 'YOUR_VAPID_KEY',
});
</script>What Happens During Initialization
- A unique device token is generated (or restored from localStorage) and the device is registered on the server
- Notification permission is requested and the Service Worker is registered
- A Web Push subscription is created with your VAPID key
- Device info is sent to the server and periodic updates begin
- Automatic lifecycle tracking and push event handling start
4. Everything is Automatic
The SDK automatically tracks lifecycle and handles notification events. No manual code needed.
- Lifecycle tracking — Page Visibility API sends
onscreen/backgroundevents when the tab becomes visible or hidden.beforeunloadsendsclosedviasendBeacon. - Push handling — the Service Worker receives pushes, shows notifications, and reports
delivered/clickedevents directly via fetch (with retry). Falls back topostMessageif fetch fails. - Click handling — notification taps open the target URL automatically.
5. Tags and Segmentation
NotifyPartnersSDK.setTags({
plan: 'premium',
city: 'moscow',
interests: 'sports',
});
NotifyPartnersSDK.setExternalId('user-456');Validation limits:
- Maximum 50 tags per call
- Tag key: maximum 128 characters
- Tag value: maximum 256 characters
externalId: maximum 256 characters- Violations throw
SdkErrorwith typeConfigurationError
Persistence: tags and externalId are saved to localStorage and survive page reloads.
Debouncing: rapid consecutive calls are coalesced (500ms window) — only the last value is sent to the server.
6. Push Notification Handling
The Service Worker handles push notifications automatically — it receives pushes, shows notifications, reports delivered/clicked events to the server, and opens the target URL on click. If a listener is set, onMessageReceived is called on the main thread.
Push payload format from the server:
{
"msg_id": "message-uuid",
"title": "Title",
"body": "Notification body",
"icon": "https://example.com/icon.png",
"image": "https://example.com/image.png",
"url": "https://example.com/action"
}7. Cleanup
When deinitializing (e.g., in an SPA on route change):
NotifyPartnersSDK.shutdown();After shutdown, initialize() can be called again with new config.
API Reference
NotifyPartnersSDK
Static class (singleton). The main entry point.
class NotifyPartnersSDK {
static initialize(config: NotifyPartnersConfig): void;
static shutdown(): void;
static setExternalId(externalId: string): void;
static setTags(tags: Record<string, string>): void;
static isInitialized(): boolean;
static getInstanceId(): string | null;
static setListener(listener: NotifyPartnersListener | undefined): void;
}initialize
Initialize the SDK. Fire-and-forget — errors are routed to listener.onInitializationFailed, not thrown.
static initialize(config: NotifyPartnersConfig): voidProtected against double initialization — subsequent calls are ignored. Call shutdown() first to re-initialize.
shutdown
Release all resources: stops periodic updates, removes visibility and message listeners, cancels pending debounced calls.
static shutdown(): voidAfter shutdown, initialize() can be called again.
setExternalId
Set the external user ID for segmentation.
static setExternalId(externalId: string): void- Throws
SdkError(ConfigurationError) if blank or exceeds 256 characters - If SDK is not initialized, logs a warning and returns
- Saved to localStorage (persists across reloads)
- Debounced — rapid calls are coalesced
setTags
Set tags for user segmentation.
static setTags(tags: Record<string, string>): void- Throws
SdkError(ConfigurationError) on validation failure - If SDK is not initialized, logs a warning and returns
- Tags are replaced in full (not merged)
- Saved to localStorage (persists across reloads)
- Debounced — rapid calls are coalesced
isInitialized
static isInitialized(): booleanReturns true if the SDK has been successfully initialized.
getInstanceId
static getInstanceId(): string | nullReturns the server-assigned instance ID, or null before initialization.
setListener
static setListener(listener: NotifyPartnersListener | undefined): voidReplace the lifecycle listener. Pass undefined to remove. Can also be set via config.listener.
NotifyPartnersConfig
interface NotifyPartnersConfig {
readonly appId: string;
readonly vapidKey: string;
readonly externalId?: string;
readonly tags?: Readonly<Record<string, string>>;
readonly serviceWorkerPath?: string;
readonly listener?: NotifyPartnersListener;
readonly debug?: boolean;
}| Field | Type | Default | Description |
|---|---|---|---|
appId | string | — | Application ID (required) |
vapidKey | string | — | VAPID public key for Web Push (required) |
externalId | string? | undefined | External user identifier (max 256) |
tags | Record<string, string>? | undefined | Tags for segmentation (max 50, key ≤128, value ≤256) |
serviceWorkerPath | string? | "/notify-partners-sw.js" | Path to the Service Worker file |
listener | NotifyPartnersListener? | undefined | Lifecycle callbacks |
debug | boolean? | false | Enable debug logging to console |
NotifyPartnersListener
All methods are optional — implement only what you need.
interface NotifyPartnersListener {
onInitialized?(instanceId: string): void;
onInitializationFailed?(error: SdkError): void;
onMessageReceived?(msgId: string, title: string, body: string, data: Record<string, string>): void;
}| Callback | When it fires |
|---|---|
onInitialized(instanceId) | SDK registered with server successfully |
onInitializationFailed(error) | All retry attempts failed |
onMessageReceived(msgId, title, body, data) | Push message received while page is open |
SdkError
Structured error with a type discriminant for switch-based handling.
class SdkError extends Error {
readonly type: SdkErrorType;
readonly httpCode?: number;
readonly body?: string;
}
type SdkErrorType =
| 'NetworkError'
| 'ServerError'
| 'ClientError'
| 'TimeoutError'
| 'ConfigurationError';| Type | Retryable | Description |
|---|---|---|
NetworkError | Yes | DNS, offline, CORS failure |
ServerError | Yes | HTTP 5xx |
TimeoutError | Yes | Request timed out |
ClientError | No | HTTP 4xx |
ConfigurationError | No | Invalid config (blank appId, bad VAPID key, etc.) |
onInitializationFailed(error) {
switch (error.type) {
case 'ConfigurationError':
console.error('Bad config:', error.message);
break;
case 'NetworkError':
case 'TimeoutError':
console.error('Network issue, will retry');
break;
case 'ServerError':
console.error('Server error:', error.httpCode);
break;
case 'ClientError':
console.error('Client error:', error.httpCode, error.body);
break;
}
}NotifyPartnersConstants
const NotifyPartnersConstants = {
LIFECYCLE_ONSCREEN: 'onscreen',
LIFECYCLE_BACKGROUND: 'background',
LIFECYCLE_CLOSED: 'closed',
};Lifecycle event constants used by the SDK. Other internal constants (Service Worker message types) are not part of the public API.
Server Registration (alternative to SDK)
If you cannot use the JavaScript SDK (e.g., for headless browsers or server-side environments), use the server device registration API directly. See SDK — Overview.
SDK — Overview
Notify Partners provides client SDKs for three platforms — Web, Android, and iOS. All SDKs implement a unified server communication protocol.
Android SDK
Integrating Notify Partners push notifications into an Android application — installation via Maven Central, Firebase setup, SDK initialization, and full API reference.