Push notifications that bring users back
Back-in-stock alerts, reminders and replies on iOS, Android and the web from one Beams-compatible API, with interests users choose and deep links.
Most of your users are not in your app right now. A well-timed push notification ("Your item is back in stock", "Your class starts in 15 minutes", "Ann replied to you") brings them back for a reason they care about. Hibira Push sends to iOS, Android and browsers through one Beams-compatible API, so you write the logic once.
What your users get
- Alerts for the things they asked to follow: a price drop, a team's match, a new episode.
- Personal reminders and replies on whichever device they use.
- A tap that opens the exact page, not the home screen.
Built with
- Interests: topics devices subscribe to, such as
price-drop-sku-123orteam-tigers, for one publish to everyone who follows. - Authenticated users: publish to a user ID and reach all of that user's signed-in devices.
- APNs, FCM and Web Push from one request, with the web, Android and iOS SDKs.
- Your existing Beams code: the official Beams server SDKs work with your endpoint.
Step 1: let users choose what to follow
Subscribe the device to an interest when the user taps "Notify me":
import { Client } from '@hibira-io/push-web';
const push = new Client({ instanceId: 'YOUR_INSTANCE_ID', endpoint: 'https://ws.hibira.io' });
// Browsers only show the permission prompt after a click or tap.
notifyButton.addEventListener('click', async () => {
await push.start();
await push.addDeviceInterest(`price-drop-sku-${sku}`);
notifyButton.textContent = 'We will tell you';
});Android and iOS have the same addDeviceInterest call; see the push notifications guide for setup on each platform.
Step 2: publish when it happens
const PushNotifications = require('@pusher/push-notifications-server');
const beams = new PushNotifications({ instanceId: 'YOUR_INSTANCE_ID', secretKey: process.env.HIBIRA_PUSH_SECRET_KEY, endpoint: 'ws.hibira.io' });
beams.protocol = 'https';
await beams.publishToInterests([`price-drop-sku-${sku}`], {
web: { notification: { title: 'Back in stock', body: `${name} is back, now ${price}.`, deep_link: `https://your-shop.example/p/${sku}` } },
fcm: { notification: { title: 'Back in stock', body: `${name} is back, now ${price}.` }, data: { url: `/p/${sku}` } },
apns: { aps: { alert: { title: 'Back in stock', body: `${name} is back, now ${price}.` } }, data: { url: `/p/${sku}` } },
});One publish reaches every device that follows the interest.
Step 3: personal messages for signed-in users
Link the device to your user ID after sign-in (the SDK calls your token route), then publish to the user:
await beams.publishToUsers([String(userId)], {
fcm: { notification: { title: 'Your class starts in 15 minutes', body: 'Yoga with Mei, studio 2.' } },
apns: { aps: { alert: { title: 'Your class starts in 15 minutes', body: 'Yoga with Mei, studio 2.' } } },
web: { notification: { title: 'Your class starts in 15 minutes', deep_link: 'https://your-site.example/bookings' } },
});When the user signs out, call push.stop() in the browser (clearAllState() on Android and iOS), and beams.deleteUser(userId) on your server when they delete their account.
Tips
- Ask for permission at the moment it is useful ("Tell me when it's back"), not on the first page view; people say yes far more often.
- Keep one interest per thing to follow. Interests are cheap; notifications people did not ask for get your app muted.
- Respect quiet hours in the user's time zone on your server before you publish.
- Combine push with realtime: while the user is in the app, show the same event in place with in-app notifications and skip the push.