NPNotify Partners Docs

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_id from the Notify Partners dashboard

1. Installation

npm

npm install @notify.partners/web-sdk

CDN

<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

  1. A unique device token is generated (or restored from localStorage) and the device is registered on the server
  2. Notification permission is requested and the Service Worker is registered
  3. A Web Push subscription is created with your VAPID key
  4. Device info is sent to the server and periodic updates begin
  5. 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/background events when the tab becomes visible or hidden. beforeunload sends closed via sendBeacon.
  • Push handling — the Service Worker receives pushes, shows notifications, and reports delivered/clicked events directly via fetch (with retry). Falls back to postMessage if 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 SdkError with type ConfigurationError

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): void

Protected 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(): void

After 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(): boolean

Returns true if the SDK has been successfully initialized.


getInstanceId

static getInstanceId(): string | null

Returns the server-assigned instance ID, or null before initialization.


setListener

static setListener(listener: NotifyPartnersListener | undefined): void

Replace 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;
}
FieldTypeDefaultDescription
appIdstringApplication ID (required)
vapidKeystringVAPID public key for Web Push (required)
externalIdstring?undefinedExternal user identifier (max 256)
tagsRecord<string, string>?undefinedTags for segmentation (max 50, key ≤128, value ≤256)
serviceWorkerPathstring?"/notify-partners-sw.js"Path to the Service Worker file
listenerNotifyPartnersListener?undefinedLifecycle callbacks
debugboolean?falseEnable 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;
}
CallbackWhen 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';
TypeRetryableDescription
NetworkErrorYesDNS, offline, CORS failure
ServerErrorYesHTTP 5xx
TimeoutErrorYesRequest timed out
ClientErrorNoHTTP 4xx
ConfigurationErrorNoInvalid 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.