Quickstart

relaybell adds web push notifications to any website. Drop in a snippet, and you can collect subscribers and send notifications โ€” with automation, targeting, and analytics โ€” in minutes.

Grab your Project ID and an API key from your dashboard (Settings โ†’ API keys), then:

<script src="https://relaybell.com/relaybell-sdk.js"></script>
<script>
  RelayBell.init({ projectId: "YOUR_PROJECT_ID", apiBase: "https://relaybell.com" });
</script>

That's the whole install. relaybell shows your opt-in prompt, subscribes visitors, and stores them. To send, POST to the REST API with your API key (see Sending).

Installing the SDK

The SDK needs a service worker at your site root. If you use the hosted relaybell-sdk.js, the default swPath is /sw.js โ€” host our sw.js there, or pass a custom path. On WordPress/Shopify our plugins/snippets handle this for you.

On iOS/iPadOS, web push only works once a visitor adds your site to their Home Screen (Apple's rule). The SDK detects iOS and shows an "Add to Home Screen" hint automatically.

Browser SDK โ€” init & options

RelayBell.init({
  projectId: "YOUR_PROJECT_ID",   // required
  apiBase:   "https://relaybell.com",
  swPath:    "/sw.js",            // service-worker path
  externalId: "user_123",         // link this browser to your own user id
  tags: { plan: "pro" },          // custom attributes for segmentation
  requireConsent: false,          // true = wait for grantConsent() (CMP integration)
  policyVersion: "2026-01"        // recorded with consent for your audit trail
});

Browser SDK โ€” methods

MethodWhat it does
init(opts)Registers the SW, shows the opt-in prompt, subscribes.
subscribeNow()Triggers the browser permission prompt (call from a click).
unsubscribe()Opts the visitor out and suppresses future sends.
isSupported(){ supported, browser, os, needsInstall } โ€” feature detection.
setTags({...})Update custom attributes for segmentation.
setTopics(["news"])Save which topics the subscriber wants.
showPreferences()Opens a preference-center modal of your topics.
showInbox()Opens a modal of your recent notifications.
track(event, props)Send a behavioral event (fires automations + attribution).
trackConversion(value, props)Record a purchase/conversion with revenue.
grantConsent() / revokeConsent()For cookie-consent (CMP) gating when requireConsent is set.
// Behavioral tracking โ†’ powers cart abandonment, back-in-stock, attribution
RelayBell.track("cart.updated", { product: "Blue Shoes", price: 49, url: location.href });
RelayBell.trackConversion(79.99, { orderId: "A123" });

Opt-in prompts

Prompt style, copy, trigger and colors are configured per project (dashboard, or PUT /api/v1/prompt). Styles: slidein (default), bar, modal, native. Triggers: delay, load, click, scroll, exit. Add a privacyUrl (Settings โ†’ Compliance) to show a privacy link. Set a prompt b variant to A/B-test opt-in copy.

REST API โ€” authentication

All server-side calls use a Bearer API key (starts with rb_live_):

curl https://relaybell.com/api/v1/stats \
  -H "Authorization: Bearer rb_live_xxxxx"

Sending notifications

POST /api/v1/notifications โ€” returns 202, delivered asynchronously.

curl -X POST https://relaybell.com/api/v1/notifications \
  -H "Authorization: Bearer rb_live_xxxxx" -H "Content-Type: application/json" \
  -d '{
    "title": "Flash sale ๐Ÿ”ฅ",
    "body": "30% off ends tonight โ€” {name|there}!",
    "url": "https://shop.example/sale"
  }'
FieldDescription
title *Notification title. Supports {merge} tags.
body, url, icon, image, badge, tagRich content. requireInteraction keeps it sticky.
actionsUp to 2 buttons: [{action,title,url}].
segmentId / filtersTarget a saved segment or inline filters.
topicIdTarget subscribers of a topic.
excludeSegmentId / excludeFiltersSuppress a segment from this send.
sendAtISO timestamp to schedule.
perTimezone + localTimeDeliver at a local time (e.g. "09:00") per subscriber.
smartTimeDeliver at each subscriber's most-active hour.
ttlTime-to-live in seconds (default 24h).
translations{ "es": {title,body}, ... } โ€” auto-picked by subscriber language.
abA/B test: { "b": { title, body, url, image } }.
abTestAuto-winner: { autoWinner:true, testPercent:20, afterHours:4 } โ€” tests, then sends the winner to the rest.

Events & automation

POST /api/v1/events โ€” send a behavioral event (server-side; the browser SDK's track() does this too).

{ "event": "purchase", "externalId": "user_123", "properties": { "value": 79.99 } }

Automations (/api/v1/automations) fire a push when an event happens, with an optional delay and a cancelOn event. This powers cart abandonment (a purchase cancels the reminder), back-in-stock, price-drop, and welcome-back flows. A purchase with a value is attributed as a conversion to the last notification delivered to that subscriber.

POST /api/v1/automations
{ "name":"Cart abandon", "event":"cart.updated", "delaySeconds":3600,
  "cancelOn":"purchase", "action":{ "title":"You left {product} ๐Ÿ›’", "url":"{url}" } }

Drip sequences

/api/v1/sequences โ€” multi-step journeys. Subscribers enter on subscribe or on an event, then flow through steps with per-step delays; cancelOn drops them if they convert.

POST /api/v1/sequences
{ "name":"Welcome series", "trigger":"subscribe", "cancelOn":"purchase",
  "steps":[ { "delaySeconds":0, "title":"Welcome ๐Ÿ‘‹" },
            { "delaySeconds":86400, "title":"Here's how to start" },
            { "delaySeconds":604800, "title":"A little something for you" } ] }

Segments & topics

Analytics & webhooks

Errors, rate limits & webhook verification

Errors return a JSON body { "error": "code" } with a standard HTTP status โ€” 400 invalid input, 401 bad/missing key, 403 unverified sender or suspended account, 404 not found, 429 rate-limited. The API is rate-limited per IP; back off and retry on 429.

Sending rules: quiet hours and a per-subscriber daily frequency cap are set per project (Settings โ†’ Sending rules) and applied automatically to every send โ€” no per-request flags needed.

Verify a webhook signature

Every webhook is signed with your webhook secret. Check the X-Relaybell-Signature header (sha256=<hex>) against the raw request body:

const crypto = require("crypto");
const sig = req.headers["x-relaybell-signature"];            // "sha256=abc123โ€ฆ"
const expected = "sha256=" + crypto.createHmac("sha256", WEBHOOK_SECRET)
  .update(rawBody).digest("hex");
if (crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
  // trusted โ€” handle req.body.event
}

Compliance / GDPR

relaybell records consent (time, page, policy version) on opt-in. For data-subject requests:

White-label: relaybell's prompts, service worker, and notifications carry no relaybell branding โ€” they show only your copy and icon. You can host the SDK/SW under your own domain via a CNAME.

WordPress & WooCommerce

Install the relaybell WordPress plugin: set your Project ID + API key, and it injects the SDK, serves the service worker, and can auto-send a push when you publish. With WooCommerce active, it also fires purchase, cart.updated, and back_in_stock events automatically.

Shopify

Two parts: (1) add the storefront snippet from integrations/shopify/snippet.liquid to your theme to collect subscribers; (2) point your Shopify webhooks at https://relaybell.com/api/v1/integrations/shopify/<PROJECT_ID>. Topics are mapped automatically:

Shopify topicrelaybell event
checkouts/create, checkouts/updatecart.updated
orders/paidpurchase (value = total)
orders/fulfilledorder.fulfilled

Set a Shopify webhook secret (Settings โ†’ Compliance) to verify signatures.

Google Tag Manager

Add a Custom HTML tag in GTM, set to fire on All Pages:

<script src="https://relaybell.com/relaybell-sdk.js"></script>
<script>
  window.addEventListener('load', function () {
    RelayBell.init({ projectId: "YOUR_PROJECT_ID", apiBase: "https://relaybell.com" });
  });
</script>

Server SDKs

Thin wrappers over the REST API โ€” install from your package manager:

LanguageInstall
Node.jsnpm install relaybell
Pythonpip install relaybell
PHPcomposer require relaybell/relaybell-php

Prefer no package manager? Zipped builds are also available: Node ยท PHP ยท Python.

// Node
const { RelayBell } = require("relaybell");
const rb = new RelayBell({ apiKey: "rb_live_xxxxx" });
await rb.send({ title: "Hello", body: "World", url: "https://example.com" });
await rb.track("purchase", { externalId: "user_123", properties: { value: 42 } });
# PHP
$rb = new Relaybell\Client("rb_live_xxxxx");
$rb->send(["title" => "Hello", "body" => "World", "url" => "https://example.com"]);

# Python
from relaybell import RelayBell
rb = RelayBell("rb_live_xxxxx")
rb.send(title="Hello", body="World", url="https://example.com")

Zapier

Connect relaybell to thousands of apps with no code. Actions: Send Notification and Track Event; trigger: New Subscriber. Add it when building a Zap by searching relaybell and connecting with your API key. note the public-directory listing is completing Zapier's review; until then, connect via the invite link from your relaybell Zapier app.

Browser support

Standards-based Web Push (VAPID) works on Chrome, Firefox, Edge, Opera, Samsung Internet, and Brave (desktop & Android), and Safari 16.1+ on macOS 13 (Ventura) and later, plus Safari on iOS/iPadOS 16.4+ (iPhone/iPad requires adding the site to the Home Screen, which the SDK guides). Dead subscriptions are pruned automatically.