Amba
SDKsFeatures

Push notifications

Register a platform-native token, subscribe to topics, receive sends from the push campaign API.

The client SDK has two responsibilities for push:

  1. Register the platform-native push token (APNs on iOS, FCM on Android, web push on browsers) so the server knows where to deliver.
  2. Subscribe the user to named topics — message broadcasts ("breaking_news", "weekly_digest") that fan out to every subscribed device.

Actual sends are server-side via the push campaign API or scheduled fan-outs.

Quick start

import { Amba } from '@layers/amba-web';
 
// 1. Get a web push subscription from the browser
const registration = await navigator.serviceWorker.register('/amba-sw.js');
const subscription = await registration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: 'YOUR_VAPID_PUBLIC_KEY',
});
 
// 2. Register the token with amba
await Amba.push.register(JSON.stringify(subscription), 'web');
 
// 3. Subscribe to a topic
await Amba.push.subscribe('breaking_news');

Operations

register(token, platform, bundleId?)

Records the device's push token against the signed-in user. Call this:

  • Once after sign-in, when you first obtain a token.
  • Again whenever the platform issues a new token (rotation, app re-install).

platform is one of 'apns' (iOS APNs), 'fcm' (Android Firebase Cloud Messaging), or 'web' (web push). bundleId is required for 'apns' and 'fcm' so the server knows which app the token belongs to.

The call is idempotent — re-registering the same token for the same user is a no-op.

subscribe(topic) / unsubscribe(topic)

Opt the user into a named topic. Topic names match the same identifier shape as collection names (^[a-z][a-z0-9_]*$, up to 64 characters).

await Amba.push.subscribe('breaking_news');
await Amba.push.subscribe('user_segment_engaged');
// ... time passes ...
await Amba.push.unsubscribe('breaking_news');

Topics are a server-side fan-out target: a single send to topic breaking_news reaches every device subscribed to it for the signed-in user, across iOS / Android / web.

Patterns

Re-register on app launch

Push tokens rotate; the platform issues fresh ones periodically. Re-register on every cold start to keep server-side delivery routing accurate:

useEffect(() => {
  void (async () => {
    if (!Amba.isAuthenticated) return;
    const { data: token } = await Notifications.getDevicePushTokenAsync();
    await Amba.push.register(token, Platform.OS === 'ios' ? 'apns' : 'fcm');
  })();
}, []);

Topic opt-in flow

Surface topic subscription as user preference toggles. Persist the toggle state in a collection so the user's choice survives across devices:

async function setBreakingNewsOptIn(opt: boolean) {
  if (opt) {
    await Amba.push.subscribe('breaking_news');
  } else {
    await Amba.push.unsubscribe('breaking_news');
  }
  await Amba.collections.update('user_prefs', userPrefsId, { breaking_news_optin: opt });
}

Permission UX

Always request the OS push permission separately — register only after the user has explicitly granted permission. The SDK's register() will accept a token without permission, but no notification will deliver.

Handling taps

When you send a campaign with a data payload (see the data payload reference), it arrives on the device alongside the notification. Read it in your notification-response handler to route the tap. Pick one deep-link key and use it consistently across campaigns — the recommended convention is data.deep_link:

import * as Notifications from 'expo-notifications';
 
Notifications.addNotificationResponseReceivedListener((response) => {
  const data = response.notification.request.content.data as Record<string, unknown>;
  // On iOS your keys are top-level in the payload; on Android FCM delivers
  // them as strings, so a value that was an object arrives JSON-stringified —
  // parse it before use.
  const target = typeof data.deep_link === 'string' ? data.deep_link : undefined;
  if (target) router.push(target);
});

Amba injects nothing into the device payload — data contains exactly the keys you sent. Campaign/delivery identifiers live server-side for analytics and are not part of the pushed payload. The literal envelope per platform (including the Android string-coercion rules) is documented in the push payload contract.

Limits

  • Topic count per user: up to 100 simultaneous topic subscriptions per user.
  • Topic name: lowercase identifier, up to 64 characters.
  • Token freshness: tokens are not validated by the SDK at register time. If a token has been invalidated by the platform (e.g. user uninstalled and reinstalled), pushes to it won't be delivered until you re-register with a fresh token.
  • Platform requirements: APNs requires the Push Notifications capability in Xcode. FCM requires google-services.json and the Google Services Gradle plugin. Web push requires a service worker and a VAPID key pair.
  • No client-side send: client SDKs cannot send pushes; that's the push campaign API or scheduled fan-outs.

Reference

On this page