ReachBellDocs

JavaScript integration

This guide walks you through wiring ReachBell into a plain HTML or JavaScript site — no framework, no build step. By the end you'll have an opt-in prompt, a registered subscriber, and a working prompt()/identify()/tag() flow.

What you'll need

  • An HTTPS site. Service workers refuse to register on plain HTTP, so localhost is fine for development but production must be served over TLS.
  • Your project's API key from the dashboard's integration page (it looks like rb_live_…).
  • The reachbell-sw.js service worker file, downloadable from the same integration page.

1. Add the SDK script

Drop the loader into the <head> of every page you want push enabled on. The defer attribute keeps it from blocking render.

<script src="https://app.reachbell.com/reachbell.js" defer></script>

The script registers a global ReachBell object once it parses. Anything you call before DOMContentLoaded should be queued inside a listener so the global is guaranteed to exist.

2. Initialize the SDK

ReachBell.init() configures the SDK and registers the service worker. Call it once per page load, as early as you can after DOMContentLoaded.

<script>
  window.addEventListener('DOMContentLoaded', async () => {
    const result = await ReachBell.init({
      apiKey:     'rb_live_yourkey',
      apiUrl:     'https://api.reachbell.com',
      autoPrompt: true,
    });

    if (!result.ok) {
      console.warn('ReachBell init failed:', result.reason);
    }
  });
</script>

Init options

  • apiKey — required. Identifies your project.
  • apiUrl — optional. Defaults to https://api.reachbell.com. Override only if you're on a self-hosted or regional deployment.
  • autoPrompt — optional boolean. When true, the SDK arms a one-shot user-gesture listener and triggers the soft prompt on the user's first click, tap, or keypress. Chrome 80+ and other Chromium browsers refuse to show the native permission dialog without a user gesture, so this is the safest default.

Init returns a result, not throws. Every public SDK method resolves with a structured { ok, reason } or { success, reason } shape rather than throwing. That keeps your integration code clean — no try/catch wrappers required — but you should still inspect reason and log failures so they don't disappear silently.

3. Drop the service worker at the root

Download reachbell-sw.js from the dashboard's integration page and place it at the root of your site:

https://yoursite.com/reachbell-sw.js

This is non-negotiable. A service worker's scope is bound to the path it's served from. Serving the file from /static/sw/reachbell-sw.js would scope it to that subfolder, and push subscriptions registered under that scope would not fire for pages outside it. Root placement gives the SW scope over your entire origin.

Confirm it's reachable by visiting the URL directly in your browser before going further.

4. Trigger the prompt manually

If autoPrompt is too aggressive for your UX, set it to false and trigger the prompt yourself — typically from a "Get notified" button.

document.querySelector('#enable-push').addEventListener('click', async () => {
  const result = await ReachBell.prompt();

  if (result.ok) {
    console.log('Subscribed:', result.reason);
  } else {
    console.warn('Prompt declined or failed:', result.reason);
  }
});

ReachBell.prompt() shows the soft prompt configured in the dashboard, then escalates to the browser's native permission dialog if the user accepts. The reason field tells you why a prompt failed — common values include permission-denied, unsupported-browser, and already-subscribed.

You can also check the current permission state directly off the Notification API before calling prompt():

if (Notification.permission === 'granted') {
  // Already subscribed — skip the soft prompt.
} else if (Notification.permission === 'denied') {
  // User blocked us. The native dialog will not re-prompt.
} else {
  await ReachBell.prompt();
}

5. Identify the subscriber

When a user logs in, link their device subscription to your internal user ID. This lets you target sends by user ID instead of by raw subscription endpoint.

const result = await ReachBell.identify('user_4827');
if (!result.ok) {
  console.warn('identify failed:', result.reason);
}

Calling identify() is idempotent. The same external ID across multiple devices links them all to one logical subscriber in the dashboard.

6. Tag the subscriber

Tags are flat string labels used for segmentation. Pass an array — each call replaces the device's tag set.

await ReachBell.tag(['premium', 'beta-tester']);

The dashboard's segment builder reads these tags directly. See the Segments guide for the targeting rules they unlock.

Full working example

A minimal but complete HTML page with init, a manual prompt button, and identify on login.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>ReachBell demo</title>
    <script src="https://app.reachbell.com/reachbell.js" defer></script>
    <script>
      window.addEventListener('DOMContentLoaded', async () => {
        const init = await ReachBell.init({
          apiKey:     'rb_live_yourkey',
          autoPrompt: false,
        });

        if (!init.ok) {
          console.warn('init failed:', init.reason);
          return;
        }

        document.querySelector('#enable').addEventListener('click', async () => {
          const r = await ReachBell.prompt();
          document.querySelector('#status').textContent =
            r.ok ? 'Subscribed' : `Failed: ${r.reason}`;
        });

        document.querySelector('#login').addEventListener('click', async () => {
          const id = document.querySelector('#user-id').value.trim();
          if (!id) return;
          const r = await ReachBell.identify(id);
          if (!r.ok) console.warn('identify failed:', r.reason);
        });
      });
    </script>
  </head>
  <body>
    <h1>Notifications demo</h1>
    <button id="enable">Get notified</button>
    <p id="status"></p>

    <hr />
    <input id="user-id" placeholder="Your internal user ID" />
    <button id="login">Link this device</button>
  </body>
</html>

What's next?

  • Read the Concepts page for the org/project/subscriber data model the SDK maps to.
  • Wire the same audience into the Subscribers API to manage them server-side.
  • Build a welcome flow with the Automation guide.