WebPush SDK

This package provides a convenient interface to subscribe to browser/web push notifications using MagicBell.

If you're upgrading from v1, you might be interested in our migration guide.

Installation

Install the package using your package manager:

npm install @magicbell/webpush --save

Usage

WebPush Subscription methods are accessed through the WebPushClient instance. The client is initialized using the user credentials in the form of the userExternalId or userEmail. Provide the userHmac when your project has hmac-authentication enabled.

Alternatively, an JWT based authToken can be used for authentication, but note that this for advanced use-cases only.

ts
import { WebPushClient } from '@magicbell/webpush';

const client = new WebPushClient({
  apiKey: '024…0bd',
  userEmail: 'person@example.com',
  userHmac: 'NCI…I6M',
});

// obtain current subscription status
client.isSubscribed();
// subscribe to push notifications
client.subscribe();
// unsubscribe from push notifications
client.unsubscribe();

Options

apiKey String

Your MagicBell API key. You can find it in the MagicBell dashboard.

userEmail String

The email address of the user you want to authenticate. Required if no userExternalId or authToken is provided.

userExternalId String

The external ID of the user you want to authenticate. Required if no userEmail or authToken is provided.

userHmac String

The HMAC signature of the user you want to authenticate. Required if you want to use HMAC authentication. Not required when authenticating using the authToken.

authToken String

The authentication token of the user, as alternative to using the userEmail or userExternalId. Note that in most cases, you should authenticate using userExternalId or userEmail.

Verify browser support

One of the first things you'd want to do, is to make sure that the user's browser supports service workers and push notifications. You can do so using the isSupported utility. It returns true if the browser supports push notifications, and false otherwise.

ts
import { isSupported } from '@magicbell/webpush';
isSupported();

Service worker registration

The service worker is lazily obtained or registered when calling methods on the WebPushClient. Providing the service worker script path to the client constructor allows us to register your service worker for you.

ts
import { WebPushClient } from '@magicbell/webpush';

const client = new WebPushClient({
  // ...
  serviceWorkerPath: '/sw.js',
});

If you wish to register the service worker using our utility, you can do so. It's a simple utility, that only registers the service worker if it's not already registered. Providing a small benefit over using navigator.serviceWorker.register directly.

ts
import { registerServiceWorker } from '@magicbell/webpush';
registerServiceWorker('/sw.js');

For completeness, your service worker file should include:

ts
importScripts('https://assets.magicbell.io/web-push-notifications/sw.js');

Subscribe to push notifications

Subscribe the user to push notifications. This method will register a service worker if it isn't already registered. The service worker will be registered using the path provided in the serviceWorkerPath option. If the service worker is already registered, it will be used to subscribe the user.

ts
import { WebPushClient } from '@magicbell/webpush';

const client = new WebPushClient({ ... });
await client.subscribe();

This call will:

  • get the service worker registration
  • unsubscribe from active push subscriptions
  • open the browser dialog to enable push notifications
  • create a new push subscription
  • send the webpush token to our backend

Unsubscribe from push notifications

Unsubscribing and resubscribing is trivial, giving your users the option to "pause" push notifications.

ts
import { WebPushClient } from '@magicbell/webpush';

const client = new WebPushClient({ ... });
await client.unsubscribe();

This call will:

  • get the service worker registration
  • unsubscribe from active push subscriptions
  • delete the webpush token on our backend

Get subscription status

Obtaining the subscription status is done using client.isSubscribed()

ts
import { WebPushClient } from '@magicbell/webpush';

const client = new WebPushClient({ ... });
const subscribed = await client.isSubscribed();

This call will:

  • get the service worker registration
  • get the active push subscription
  • check if the webpush token is used by our backend

Subscribing via new browser window / popup

A popular pattern to subscribe to push notifications, is using a new browser window, on a different (sub)domain, so that notifications come from a different domain than the one your site is running on.

As the user email and hmac are sensitive data, you don't want to transfer them to the popup via the url, as it will then end up in the browser history, leaking sensitive data.

To support this flow, we offer a way to obtain an auth token, and use that short-lived token in a second client instance.

On your main page:

ts
import { WebPushClient } from '@magicbell/webpush';

const client = new WebPushClient({
  apiKey: '024…0bd',
  userEmail: 'person@example.com',
  userHmac: 'NCI…I6M',
});

// get the auth token and open the new window
const url = new URL('https://example.com')
url.searchParams.set('auth-token', await client.getAuthToken());
window.open(url.toString());

And then inside that popup:

ts
import { WebPushClient } from '@magicbell/webpush';

const searchParams = new URLSearchParams(location.search);
const authToken = searchParams.get('auth-token');

const client = new WebPushClient({
  apiKey: 'NCI…I6M',
  authToken: authToken,
});

await client.subscribe();

Api Methods

The SDK also exports a couple convenient api methods around our integrations API for the web_push channel. For most use-cases, the functions above should be sufficient, but when you need that raw data, these methods are ready to be used.

All the examples below work with the following client instance:

ts
import { WebPushClient } from '@magicbell/webpush';

const client = new WebPushClient({
  apiKey: '024…0bd',
  userEmail: 'person@example.com',
  userHmac: 'NCI…I6M',
});

startInstallation

The client.startInstallation() method can be called to obtain the project public_key (also known as 'application server key') and json based auth_token, which can be used as user authentication.

ts
type Installation = {
  public_key: string;
  auth_token: string;
};

await client.startInstallation(): Promise;

getToken

Use this method to get a specific token from our backend:

ts
type Token = {
  id: string;
  created_at: string;
  updated_at: string;
  discarded_at: string | null;
  endpoint?: string;
  keys?: Record;
};

await client.getToken(id: string): Promise

getTokens

Use this method to get all webpush tokens for this user, from our backend:

ts
type Token = {
  id: string;
  created_at: string;
  updated_at: string;
  discarded_at: string | null;
  endpoint?: string;
  keys?: Record;
};

await client.getTokens(): Promise>

createToken

Use this method to create a webpush token in our backend. Note: PushSubscriptionJSON is a native web type, not exported from our packages.

ts
interface PushSubscriptionJSON {
  endpoint?: string;
  expirationTime?: EpochTimeStamp | null;
  keys?: Record;
}

const registration = await navigator.serviceWorker.ready;
const activeSubscription = await registration?.pushManager?.getSubscription();
const token: PushSubscriptionJSON = activeSubscription.toJSON()

await client.createToken(token): Promise>

deleteToken

Use this method to delete a webpush token from our backend.

ts
await client.createToken(tokenId: string): Promise