Web configuration

Two files touch your site — a script tag and a service worker — and nothing else. Everything a visitor sees (when the prompt appears, what it says, whether a welcome notification follows) lives in the console, so changing it never means a redeploy.

Console path: Settings → Push platforms → Web push.

1 · Choose your integration

PathPick it when
Typical siteYou can add a script tag and upload a file to the site root.
WordPress, Shopify or another CMSYou edit a theme, and the site root is not yours to write to.
Custom codeYou want to decide exactly when the prompt appears, from your own button.

The choice only changes the steps the console shows you and whether the snippet passes autoPrompt: false. Switching later costs nothing — subscribers are bound to your VAPID keys, not to this setting.

2 · Add the snippet

<script src="https://api.notibase.com/sdk/notibase.js" defer></script>
<script>
  window.notibaseDeferred = window.notibaseDeferred || [];
  notibaseDeferred.push(function (nb) {
    nb.init({ clientKey: "ck_live_...", apiUrl: "https://api.notibase.com" });
  });
</script>

The script is deferred, so the queue exists before the SDK does — push a callback and it runs the moment the SDK loads. init() fetches your site configuration, registers the service worker, restores an existing subscription, and (unless you turned it off) asks for permission the way you configured it.

It is safe to call on every page load and it never throws into your page. A site with no VAPID keys yet simply ends up with a registered worker and no prompt.

3 · Serve the service worker

Download it from the console — or write one line yourself:

// public/sw.js
importScripts("https://api.notibase.com/sdk/sw.js");
Path matters more than anything else here. A service worker can only control pages at or below its own location, so /assets/sw.js can never receive push for /. Serve it from the site root unless you have set a different path under Advanced push settings.

On a CMS that will not let you write to the root, a redirect or rewrite from /sw.js to our hosted copy works just as well — the file only has to answer at that path with a JavaScript content type.

HTTPS is required. localhost is treated as secure for development; a plain http:// host is not.

4 · Permission prompt

Three styles:

StyleWhat happens
Slide prompt (default)Our own prompt appears first. The browser is only asked once the visitor clicks Allow.
Browser dialogThe native dialog fires directly, after your delay.
NeverNothing is asked. You call nb.promptForPush().

The slide prompt is the default for a blunt reason: a browser-level Block is permanent and cannot be undone from your site. A visitor who dismisses a soft prompt can be asked again next week; a visitor who blocks the browser dialog is gone for good. Chrome and Firefox also auto-block sites whose prompts are ignored repeatedly.

Safari refuses a permission request that is not tied to a user gesture, so the browser dialog style will not fire there at all. The slide prompt requests permission from inside its own Allow click, which Safari accepts.

Timing is two conditions, both of which must pass: a delay in seconds, and a page-view number counted in that browser's localStorage. A dismissal is remembered for seven days.

Asking from your own button

await nb.init({ clientKey: "ck_live_...", apiUrl: "https://api.notibase.com", autoPrompt: false });

document.querySelector("#enable-push").addEventListener("click", async () => {
  const result = await window.notibase.promptForPush();
  if (result) console.log("subscribed", result.deviceId);
});

promptForPush() resolves to { deviceId } on success and null if the visitor or the browser said no. It never throws. Copy and timing still come from the console, so marketing can change the wording without touching your code.

await nb.isSubscribed();   // reflect the real state in your own UI

5 · Welcome notification

Sent once, to the browser that just subscribed — not on every page load, and not when a returning visitor's subscription is silently restored. It goes through the normal send pipeline, so it appears in the delivery log like any other message and a failure is visible instead of silent.

An empty title means off, even with the toggle on: there is nothing worth showing.

Advanced push settings

SettingEffect
Service worker path / filename / scopeWhere the file lives. Change only if your hosting forces you to.
Auto-resubscribeBrowsers occasionally drop a push subscription while keeping permission granted. With this on, a return visit restores it silently instead of losing the subscriber.
Focus an existing tabA click focuses an already-open tab on the same path instead of opening a second copy. Matching is by origin and path — query strings differ per campaign and would defeat every match.
PersistenceNotifications wait for a dismissal instead of fading. Ignored on macOS, where the system always auto-hides banners.

Changing your VAPID keys

Two operations that look alike and are opposites:

Browser support

BrowserStatus
Chrome, Edge, Firefox, Opera (desktop + Android)✅ Full support
Safari macOS 16+✅ Standard web push
Safari iOS/iPadOS 16.4+for web apps added to the Home Screen — prompt visitors to “Add to Home Screen” first

Nothing is subscribing — what to check

The console's Check for subscribed devices button answers the same question from our side.

API reference for the SDK itself: @notibase/web.