First-party SDKs for every platform.
Same four-method mental model on every platform: init, identify, track, push.registerToken. Every SDK ships with types, background retries, automatic consent handling, and (where applicable) per-platform push wiring.
Core methods available on every SDK:
init / configure— supplypk_prod_*public key. Org / project derived from the key.identify(userId, traits)— bind the current device to a user. Persists to localStorage on web / EncryptedSharedPreferences on Android / Keychain on iOS — survives page reload + cold launch. Future events + push sends target this id.track(eventName, properties)— emit a custom analytics event. Workflows trigger off these.push.registerToken(token, platform)— register an APNs / FCM / Web Push subscription. Platform enum:ios | android | web.
Push-adjacent helpers (where each platform supports them):
- iOS:
push.requestAuthorization()(UNUserNotificationCenter prompt),push.trackOpen(sendId),liveActivities.track(activity, ...)(ActivityKit token watcher),geofences.start() / refresh() / stop(),SendoraCloudCriticalAlerts.requestPermission(_:). - Android:
push.trackOpen(sendId),liveActivities.start(fcmToken, ...) / handleFcmMessage(...),geofences.start(ctx) / refresh(ctx) / stop(ctx) / handleBroadcast(intent). - Web:
webPush.subscribe(swPath)wrapsnavigator.pushManager.subscribe()with VAPID. Service worker handlespush+notificationclickevents — see /docs/api § Web Push SW sample. - React Native (bare): same JS surface as Web; bring your own
@react-native-firebase/messagingfor FCM token grab.
Web (SPA)
TypeScript • npm 2.12.0+npm install @sendoracloud/sdk-web
import { SendoraCloud } from "@sendoracloud/sdk-web";
const s = SendoraCloud.init({ apiKey: "pk_prod_..." });
// Bind the user. Future track() / push sends target this id.
s.identify("u_123", { email: "alice@example.com", plan: "pro" });
// Send an event.
s.track("page.viewed", { path: "/" });
// Web Push (VAPID) — registers the subscription against this user.
await s.webPush.subscribe("/sw.js");Web (SSR)
TypeScript • npm 0.2.0+ • Next.js / Remix / SvelteKitnpm install @sendoracloud/sdk-web-ssr @sendoracloud/sdk-web
// middleware.ts — protect routes
import { sendoraMiddleware } from "@sendoracloud/sdk-web-ssr/middleware";
export default sendoraMiddleware({
publicKey: process.env.NEXT_PUBLIC_SENDORA_KEY!,
protected: ["/dashboard"],
loginPath: "/login",
});
// app/page.tsx (server component) — read session
import { cookies } from "next/headers";
import { createSendoraServerClient }
from "@sendoracloud/sdk-web-ssr/server";
const sendora = createSendoraServerClient(cookies(), {
publicKey: process.env.NEXT_PUBLIC_SENDORA_KEY!,
});
const session = sendora.getSession(); // null if signed out
// "use client" component — track event
import { SendoraCloud }
from "@sendoracloud/sdk-web-ssr/client";
SendoraCloud.init({ apiKey: "pk_prod_..." })
.track("page.viewed");iOS
Swift • SwiftPM 3.9.0+SwiftPM: github.com/sendoracloud/sdk-ios
import SendoraCloud
SendoraCloud.configure(apiKey: "pk_prod_...")
// Bind the user.
SendoraCloud.identify(
userId: "u_123",
traits: ["email": "alice@example.com", "plan": "pro"]
)
// Send an event.
SendoraCloud.trackEvent("screen.viewed", properties: ["screen": "Home"])
// Push token registration (in didRegisterForRemoteNotificationsWithDeviceToken:)
let token = deviceTokenData.map { String(format: "%02x", $0) }.joined()
SendoraCloud.push?.registerToken(token, platform: .ios) { _ in }Android
Kotlin • JitPack 3.8.0+implementation("com.github.sendoracloud:sdk-android:3.8.0")
SendoraCloud.init(
context = this,
apiKey = "pk_prod_..."
)
// Bind the user.
SendoraCloud.identify(
userId = "u_123",
traits = mapOf("email" to "alice@example.com", "plan" to "pro")
)
// Send an event.
SendoraCloud.trackEvent("screen.viewed", mapOf("screen" to "Home"))
// Push token registration (FCM)
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
val token = task.result ?: return@addOnCompleteListener
SendoraCloud.push?.registerToken(token, platform = SendoraCloudPush.Platform.ANDROID)
}React Native
TypeScript • npm 0.16.0+ • Bare workflownpm install @sendoracloud/sdk-react-native
import { SendoraCloud } from "@sendoracloud/sdk-react-native";
const sendora = SendoraCloud.init({ publicKey: "pk_prod_..." });
// Bind the user.
sendora.identify({ userId: "u_123", traits: { email: "alice@example.com" } });
// Send an event.
sendora.track("screen.viewed", { screen: "Home" });
// Push: bare workflow only — uses @react-native-firebase/messaging.
// platform enum: "ios" | "android" | "web".
import messaging from "@react-native-firebase/messaging";
const token = await messaging().getToken();
await sendora.push.registerToken({ token, platform: "android" });Expo managed: see /docs/push#expo for the webhook-bridge path. Sendora dispatches via APNs / FCM directly — Expo Push Service tokens are not supported. @react-native-firebase/messaging is required only for Android FCM token grab; iOS-only RN apps can skip Firebase entirely and call iOS-native APIs (UIApplication.registerForRemoteNotifications) via a tiny native module then pass the APNs token to push.registerToken({ token, platform: 'ios' }).
Start in minutes. Scale without switching tools.
The free tier covers most side projects. Every module is turn-key and every SDK is first-party.