Browser SDK
The SDK ships as a single IIFE at https://litepush.dev/sdk.js. No build step on your side.
Script tag
<script
src="https://litepush.dev/sdk.js"
data-project="prj_xxxxxxxx"
data-vapid-key="xxxxxxxx"
async
></script>
| Attribute | Required | Description |
|---|---|---|
data-project | yes | Your project ID from the dashboard. |
data-vapid-key | yes | The project's VAPID public key. If you rotate VAPID keys from the dashboard, update this attribute — existing subscribers stop receiving pushes until they re-opt in with the new key. |
async | recommended | Lets the script load without blocking page render. |
Methods
The SDK exposes window.litepush once it's loaded. Calls made before load go onto window.litepushQ as functions and run when the SDK initialises.
litepush.subscribe(options?)
Prompts the user for notification permission (if not already granted), registers the service worker, creates a PushSubscription, and registers it with LitePush.
const result = await litepush.subscribe({
userId: "user_42", // optional — your own user id, stored as external_id
});
Returns:
type SubscribeResult =
| { id: string } // LitePush subscriber id
| null; // user denied permission
Throws if the browser doesn't support web push (use canSubscribe() to check first) or if the page's <script> tag is missing required data-* attributes.
Must be called from a user gesture (click, tap, key press). Browsers reject silent permission prompts.
The SDK's
subscribe()does not take group IDs by design — group membership is managed server-side. Oncesubscribe()returns the subscriber's ID, callPOST /v1/groups/:id/subscribersfrom your server to assign the user's groups. This keeps membership tamper-proof from the client. See/v1/groups.
litepush.unsubscribe()
Cancels the subscription on the browser AND beacons our /v1/unsubscribe so the dashboard updates immediately rather than waiting for the next broadcast to discover the dead endpoint. Returns true if a subscription was actually removed.
await litepush.unsubscribe();
litepush.isSubscribed()
Returns true if the browser currently has an active subscription for your project. Asynchronous because it has to look up the service worker registration.
if (await litepush.isSubscribed()) {
document.getElementById("subscribe-btn").style.display = "none";
}
litepush.canSubscribe()
Synchronous capability check — returns true on browsers that support web push. Safe to call from any context (no permission prompt, no async work). Use it to hide the subscribe button on browsers that won't deliver pushes anyway.
if (!litepush.canSubscribe()) {
document.getElementById("subscribe-btn").remove();
}
litepush.version
Read-only string. Useful when filing support tickets.
The deferred-call queue
If you call into the SDK before sdk.js has loaded, push a function onto window.litepushQ. The SDK replays the queue in order once it boots:
<button id="subscribe-btn">Enable notifications</button>
<script>
// Safe — runs before sdk.js loads. Queued and replayed.
document.getElementById("subscribe-btn").addEventListener("click", () => {
(window.litepushQ = window.litepushQ || []).push((lp) => {
lp.subscribe({ userId: currentUser.id });
});
});
</script>
<script src="https://litepush.dev/sdk.js" data-project="..." data-vapid-key="..." async></script>
The callback receives the SDK object — call any method on it.
Browser support
- Chrome / Edge desktop + mobile
- Firefox desktop + Android
- Safari macOS 16+ — any site, no install required
- Safari iOS / iPadOS 16.4+ — only when your site is installed to the Home Screen as a PWA. Web Push does not deliver in a regular Safari tab on iOS; the APIs exist but
subscribe()will fail.
canSubscribe() accounts for the iOS PWA-install requirement automatically — it returns false for an iOS visitor who hasn't added your site to their Home Screen yet, even though the underlying Push APIs are present. To give those visitors a path to subscribing, detect the same condition yourself and surface an "Add to Home Screen" prompt:
const isIOSorIPadOS =
/iPad|iPhone|iPod/.test(navigator.userAgent) ||
(navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
const isStandalone =
navigator.standalone === true ||
window.matchMedia("(display-mode: standalone)").matches;
if (!litepush.canSubscribe()) {
if (isIOSorIPadOS && !isStandalone) {
showAddToHomeScreenHint();
} else {
hideSubscribeButton();
}
}
subscribe() throws on any browser where canSubscribe() is false, so always gate the button on the capability check first.