SDK API Reference
This page lists the SDK calls most apps use after installing Bubbl. Names vary slightly by platform, but the integration flow is the same: boot the SDK, forward permissions and push data from your app, pass location updates when needed, then use diagnostics and events to confirm behavior.
Only use APIs exposed by the SDK package version installed in your app. If a method is not present in your installed 4.0.2 package, do not rely on it in a live release.
Required vs optional
Every integration needs:
apiKeyboot(config)- A live environment value in the platform quickstart
- Push token forwarding if the app uses Bubbl notifications
- Location permission and location updates if the app uses geofences
diagnostics()during verification
Most integrations also use:
segmentsorupdateSegments(tags)for campaign eligibilitycorrelationIdorsetCorrelationId(id)for matching Bubbl activity to your app journeyflush()after important verification steps
Optional features:
- SDK-managed location tracking
- Default Bubbl notification modal and survey UI
- Host-rendered notification UI
- Custom modal colors and corner radius
- Custom app events through
track(event)
Configuration
| Option | Required | Description |
|---|---|---|
apiKey |
Yes | Your live Bubbl SDK API key. |
environment |
Yes | Set this to the live Bubbl environment value shown in your platform quickstart. |
segments |
No | Segment tags for campaign eligibility. Set at boot and update when the user's eligibility changes. |
correlationId |
No | Your app's user, session, order, journey, visit, or job reference. Avoid values that expose unnecessary personal data. |
defaultDistanceMeters |
No | Default distance used where campaign/location distance is not supplied. |
refreshIntervalSeconds |
No | Minimum refresh interval for SDK-managed refreshes. |
enablePushHandling |
No | Enables Bubbl push payload handling. Leave on for most notification integrations. |
enableLocationTracking |
No | Lets the SDK manage location tracking. Leave off if your app already owns location collection. |
notificationRenderingMode |
No | Choose SDK default, host-rendered, or event-only notification behavior. |
enableDefaultNotificationModal |
No | Allows the SDK default notification detail modal. |
defaultNotificationModalStyle |
No | Sets supported default modal colors and corner radius. |
enableDefaultSurveyUi |
No | Allows the SDK default survey UI. |
allowGeofenceRetriggers |
No | Allows the same geofence campaign to trigger again when campaign rules permit it. Leave enabled unless your product needs one trigger per qualifying visit. |
enableGeofenceDebugEvents |
No | Emits extra geofence evaluation events during integration testing. Keep disabled in normal production builds. |
logLevel |
No | SDK log verbosity. Use a quieter level in production builds. |
Only set custom endpoint URLs if Bubbl support asks you to.
Common option values
Environment values:
| Platform | Production value |
|---|---|
| Android | BubblEnvironment.Production |
| iOS | .production |
| Flutter | BubblEnvironment.production |
| React Native | 'production' |
Notification rendering values:
| Platform | SDK default | Host rendered | Event only |
|---|---|---|---|
| Android | BubblNotificationRenderingMode.SdkDefault |
BubblNotificationRenderingMode.HostRendered |
BubblNotificationRenderingMode.EventOnly |
| iOS | .sdkDefault |
.hostRendered |
.eventOnly |
| Flutter | BubblNotificationRenderingMode.sdkDefault |
BubblNotificationRenderingMode.hostRendered |
BubblNotificationRenderingMode.eventOnly |
| React Native | 'sdkDefault' |
'hostRendered' |
'eventOnly' |
Use sdkDefault when you want Bubbl to render notification details and surveys. Use hostRendered when your app renders the notification UI but still forwards actions back to Bubbl. Use eventOnly when your app only wants parsed events and will own all presentation.
Boot examples
Boot once during app startup, after your app configuration is available. Keep the API key in app configuration rather than reusable library code.
Android:
BubblSdk.install(applicationContext)
val result = BubblSdk.boot(
BubblConfig(
apiKey = BuildConfig.BUBBL_API_KEY,
environment = BubblEnvironment.Production,
segments = listOf("loyalty-member"),
correlationId = currentVisitId,
enablePushHandling = true,
enableLocationTracking = false
)
)
iOS:
let result = try await BubblClient.shared.boot(
BubblConfig(
apiKey: bubblApiKey,
environment: .production,
segments: ["loyalty-member"],
correlationId: currentVisitId,
enablePushHandling: true,
enableLocationTracking: false
)
)
Flutter:
final result = await BubblSdk.instance.boot(
const BubblConfig(
apiKey: String.fromEnvironment('BUBBL_API_KEY'),
environment: BubblEnvironment.production,
segments: ['loyalty-member'],
enablePushHandling: true,
enableLocationTracking: false,
),
);
React Native:
const result = await Bubbl.boot({
apiKey: Config.BUBBL_API_KEY,
environment: 'production',
segments: ['loyalty-member'],
correlationId: currentVisitId,
enablePushHandling: true,
enableLocationTracking: false,
});
After boot, check result.ready, result.requiresPermission, and result.warnings if your platform exposes them.
Common methods
| Method | Required | Use it when |
|---|---|---|
boot(config) |
Yes | Starting the SDK with your API key and settings. |
shutdown() |
No | Stopping SDK activity for the current app process, usually during sign-out or teardown. |
refresh() |
No | Refreshing SDK configuration and push-related campaign state. |
getConfiguration() |
No | Reading the current campaign/config summary. |
getPrivacyText() |
No | Displaying privacy text supplied by Bubbl configuration. |
startLocationTracking() |
Conditional | Letting the SDK manage location tracking after the user grants permission. |
stopLocationTracking() |
Conditional | Stopping SDK-managed location tracking. |
handleLocationUpdate(location) |
Conditional | Passing an app-managed location update to Bubbl. |
refreshGeofence(location) |
Conditional | Fetching and evaluating geofence campaign state for a known location. |
refreshPush() |
Conditional | Refreshing push-related campaign state. |
registerPushToken(token) |
Conditional | Sending the current FCM/APNs token to Bubbl. |
handleFirebasePayload(payload) |
Conditional | Letting Bubbl parse a Firebase data payload. |
showNotification(payload) |
No | Asking Bubbl to display a notification payload with SDK UI. |
handleNotificationPayload(payload) |
No | Recording receipt and applying the configured rendering mode. |
handleNotificationOpen(payload, action) |
No | Telling Bubbl the user opened a notification in host-rendered UI. |
openNotificationModal(payload) |
No | Opening the SDK default detail modal from your own notification list or inbox. |
handleNotificationCta(payload, action) |
No | Telling Bubbl the user tapped a CTA in host-rendered UI. |
handleNotificationMediaViewed(payload) |
No | Telling Bubbl the user viewed campaign media in host-rendered UI. |
handleNotificationSurveyRequested(payload) |
No | Telling Bubbl the user opened a survey from host-rendered UI. |
updateSegments(tags) |
No | Replacing current segment tags after sign-in, profile, tier, or journey changes. |
setCorrelationId(id) |
No | Setting the current app user, session, visit, journey, order, or job reference. |
clearCorrelationId() |
No | Removing the current correlation ID, usually at sign-out or journey end. |
track(event) |
No | Tracking a supported custom SDK event. |
submitSurveyResponse(response) |
Conditional | Sending a survey response from custom UI. |
flush() |
No | Asking the SDK to send queued events now. |
diagnostics() |
Yes for verification | Returning SDK health and setup details. |
Method recipes
Use these recipes as a quick map from app workflow to SDK calls.
| App workflow | Calls |
|---|---|
| App starts and the user is eligible for Bubbl content | boot(config), then diagnostics() during verification. |
| User signs in or their profile changes | updateSegments(tags) and setCorrelationId(id) if you have a current app journey reference. |
| User signs out | clearCorrelationId(), replace segments with the next valid set, and optionally flush(). |
| Firebase/APNs returns a new token | registerPushToken(token). |
| Foreground push message arrives | handleFirebasePayload(data), then render according to your chosen mode. |
| User opens your own notification card | handleNotificationOpen(payload, action). |
| User taps a CTA in your own UI | handleNotificationCta(payload, action), then navigate in your app. |
| User views campaign media in your own UI | handleNotificationMediaViewed(payload). |
| User opens a custom survey | handleNotificationSurveyRequested(payload). |
| User submits a custom survey | submitSurveyResponse(response), then flush() if you need immediate verification. |
| App already has a location update | handleLocationUpdate(location). |
| App wants immediate geofence evaluation | refreshGeofence(location). |
| QA/support evidence is needed | diagnostics(), then flush(). |
Push token and payload forwarding
Register the latest push token whenever Firebase/APNs gives one to your app.
Android:
override fun onNewToken(token: String) {
scope.launch {
BubblSdk.registerPushToken(token)
}
}
iOS:
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
Task {
try? await BubblClient.shared.updateAPNsToken(deviceToken)
}
}
Flutter:
final token = await FirebaseMessaging.instance.getToken();
if (token != null) {
await BubblSdk.instance.registerPushToken(token);
}
React Native:
const token = await messaging().getToken();
await Bubbl.registerPushToken(token);
Forward Firebase data payloads to the SDK. handleFirebasePayload returns a parsed Bubbl notification payload when the message contains Bubbl notification data, or null when it does not.
Flutter:
FirebaseMessaging.onMessage.listen((message) async {
final payload = await BubblSdk.instance.handleFirebasePayload(message.data);
if (payload != null) {
debugPrint('Bubbl notification received: ${payload.id}');
}
});
If your app has separate foreground, background, and tap handlers, forward the same Bubbl data payload in each path. The platform-specific push libraries decide which handler runs; Bubbl only sees messages that your app forwards.
React Native:
messaging().onMessage(async message => {
const data = Object.fromEntries(
Object.entries(message.data ?? {}).map(([key, value]) => [key, String(value)]),
);
const payload = await Bubbl.handleFirebasePayload(data);
if (payload) {
console.log('Bubbl notification received', payload.id);
}
});
Location and geofence patterns
If your app already collects location, pass location updates to Bubbl:
BubblSdk.handleLocationUpdate(
BubblLocation(latitude = 51.5072, longitude = -0.1276)
)
await BubblSdk.instance.handleLocationUpdate(
const BubblLocation(latitude: 51.5072, longitude: -0.1276),
);
await Bubbl.handleLocationUpdate({
latitude: 51.5072,
longitude: -0.1276,
});
If you want the SDK to manage location tracking, request the correct platform permission first, then start tracking:
BubblSdk.startLocationTracking()
await BubblSdk.instance.startLocationTracking();
await Bubbl.startLocationTracking();
Use refreshGeofence(location) when you want to evaluate a known location immediately. It does not return a geofence snapshot directly; observe SDK events, diagnostics, and logs to verify results.
Geofence trigger behavior
Campaign timing rules are managed in Bubbl. The SDK evaluates device movement and applies the campaign rules it receives. In most apps, keep allowGeofenceRetriggers enabled so dashboard campaign timing controls repeat behavior. Disable it only when your app deliberately wants to suppress repeated geofence candidates on the device.
During QA, enableGeofenceDebugEvents can help you see enter, exit, dispatch, and suppression events in the SDK event stream. Turn it off before general release unless Bubbl support asks you to keep it enabled for a short investigation.
Segments and correlation IDs
Use segments for eligibility and correlation IDs for your own references.
BubblSdk.updateSegments(listOf("gold-member", "store-visitor"))
BubblSdk.setCorrelationId("visit_12345")
try await BubblClient.shared.updateSegments(["gold-member", "store-visitor"])
try await BubblClient.shared.setCorrelationId("visit_12345")
await BubblSdk.instance.updateSegments(['gold-member', 'store-visitor']);
await BubblSdk.instance.setCorrelationId('visit_12345');
await Bubbl.updateSegments(['gold-member', 'store-visitor']);
await Bubbl.setCorrelationId('visit_12345');
At sign-out or journey end, clear the correlation ID and replace segments with the next valid set for the device:
BubblSdk.clearCorrelationId()
BubblSdk.updateSegments(emptyList())
Do not put email addresses, phone numbers, or raw names in segment tags or correlation IDs. Use stable app references such as a visit ID, order ID, booking ID, loyalty tier, or product journey state.
Custom event examples
Use track(event) for supported app milestones that should be visible to Bubbl. Keep events small and tied to a user action or journey state.
Flutter:
await BubblSdk.instance.track(
const BubblTrackEvent(
type: 'journey',
activity: 'booking_confirmed',
locationId: 'store-123',
),
);
React Native:
await Bubbl.track({
type: 'journey',
activity: 'booking_confirmed',
locationId: 'store-123',
});
Android:
BubblSdk.track(
BubblTrackEvent(
type = "journey",
activity = "booking_confirmed",
locationId = "store-123"
)
)
iOS:
try await BubblClient.shared.track(
BubblTrackEvent(
type: "journey",
activity: "booking_confirmed",
locationId: "store-123"
)
)
Notification and survey handling
For SDK-rendered notifications, let handleFirebasePayload or handleNotificationPayload process the payload and use your configured rendering mode.
For host-rendered UI, parse the payload and forward user actions back to Bubbl:
const payload = await Bubbl.handleFirebasePayload(data);
if (payload) {
renderYourNotificationCard(payload);
}
await Bubbl.handleNotificationOpen(payload, 'card_opened');
if (payload.cta?.label) {
await Bubbl.handleNotificationCta(payload, payload.cta.action ?? 'primary_cta');
}
if (payload.media) {
await Bubbl.handleNotificationMediaViewed(payload);
}
Submit survey responses only after the user completes your survey UI:
await BubblSdk.instance.submitSurveyResponse(
BubblSurveyResponse(
curatedNotificationId: payload.curatedNotificationId!,
locationId: payload.locationId,
answers: [
BubblSurveyAnswer(
questionId: question.id,
type: 'single_choice',
choiceIds: [choice.id],
),
],
),
);
Diagnostics, logging, and flushing
Use diagnostics to confirm the SDK is booted, the package version is correct, and queued events are not growing unexpectedly.
Useful diagnostics checks:
readyshould be true after a successful boot.requiresPermissiontells you which app permissions still need user approval.- Pending event counts should fall after
flush()when the device has connectivity. - The reported SDK version should match the package version you installed.
val diagnostics = BubblSdk.diagnostics()
println(diagnostics)
let diagnostics = await BubblClient.shared.diagnostics()
print(diagnostics)
final diagnostics = await BubblSdk.instance.diagnostics();
debugPrint('Bubbl diagnostics: $diagnostics');
const diagnostics = await Bubbl.diagnostics();
console.log('Bubbl diagnostics', diagnostics);
Call flush() after important verification steps or before collecting support evidence:
const result = await Bubbl.flush();
console.log('Pending Bubbl events', result.pendingCount);
The public SDK supports clearing correlation IDs and replacing segments. Do not depend on local-state reset or stored-event replay methods unless they are documented for the exact SDK package installed in your app.
Event streams
Where your platform wrapper exposes SDK events, use them to observe notification, location, geofence, diagnostics, and error events during testing. Events are useful for logging and custom UI, but your app should still handle normal platform permission and notification lifecycle states.
Flutter:
final subscription = BubblSdk.instance.events.listen((event) {
debugPrint('Bubbl event: $event');
});
React Native:
const subscription = Bubbl.events.addListener(event => {
console.log('Bubbl event', event);
});
subscription.remove();
Android:
lifecycleScope.launch {
BubblSdk.events.collect { event ->
Log.d("Bubbl", "Event: $event")
}
}
Use event streams for app logging, QA screens, and host-rendered UI. Do not block your core app navigation while waiting for an event; mobile operating systems can deliver notification and location callbacks at different times depending on app state.