Segments and events
Tag devices with segments for campaign targeting, record your own events, and listen to what Bubbl does as it happens.
Segments#
Segments are tags your app puts on a device, such as vip or newsletter, so campaigns in the dashboard can target them. They're created by your app through the SDK, never in the dashboard.
Bubbl.setSegments(listOf("vip", "newsletter"))Bubbl.setSegments(["vip", "newsletter"])await Bubbl.setSegments(['vip', 'newsletter']);Bubbl.setSegments(['vip', 'newsletter']);setSegmentsreplaces the device's segments: pass the whole list each time, and an empty list to clear them.- Up to 100 segments, each up to 255 characters. Bubbl trims them and drops empty ones and duplicates.
- To set them from the first launch, pass
segmentsinBubblOptionsatstart. - Bubbl keeps them on the device and sends them when it can, so it's fine to call offline.
In the dashboard, a segment appears under Company › Segments the first time a device reports it, with its device count and the campaigns that use it. Owners and admins can give it a readable label or hide it there. See Segments.
Custom events#
track records an event of your app's own, with optional properties, and sends it with Bubbl's event queue.
Bubbl.track("purchase.completed", mapOf("total" to 12.5, "currency" to "GBP"))Bubbl.track("purchase.completed", properties: ["total": 12.5, "currency": "GBP"])await Bubbl.track('purchase.completed', {'total': 12.5, 'currency': 'GBP'});Bubbl.track('purchase.completed', { total: 12.5, currency: 'GBP' });- Name: 1 to 100 characters from
A–Z a–z 0–9 . _ : -. An event with any other name isn't sent, and Bubbl logs a warning. - Properties: up to 50, flat: text, numbers, true or false, or null. Anything else (a list, a nested object) is left out.
- Events are only recorded while Bubbl is active: not before
setConsent(true)withrequireConsent, and not after an opt-out.
Where your events show in the dashboard#
Bubbl keeps each event against the device that sent it, with its name, its properties and when it happened. In the dashboard you see them in two places:
- Active users: open a device, and its Recent activity lists its latest events alongside geofence, notification and delivery events. A custom event shows as
custom.followed by its name. - The activity log: View full log → on a campaign's page opens it. It lists every device event, and a custom event has its name in the Type column.
An event also counts its device as active for Active users. Properties are stored but not shown anywhere in the dashboard, and there's no report, chart, segment or campaign rule built on custom events. Export workspace data (Company settings) includes them, without their properties. Keep location events for doesn't delete them; it only removes any position they carry.
Listening to events#
addEventListener tells your app what Bubbl does as it happens, on the main thread: each step of a notification's life, geofences entered and left, and errors. These are for your own use, such as your analytics or UI; Bubbl records its own for your campaign reports.
| What happened | Android (BubblEvent.) | iOS (BubblEvent.) | Flutter | React Native (type) |
|---|---|---|---|---|
| A notification arrived, before it's shown | NotificationReceived | .notificationReceived | BubblNotificationReceived | notification.received |
| It's on screen | NotificationDisplayed | .notificationDisplayed | BubblNotificationDisplayed | notification.displayed |
| Opened from its system notification | NotificationOpened | .notificationOpened | BubblNotificationOpened | notification.opened |
| Call to action tapped | NotificationCtaClicked | .notificationCtaClicked | BubblNotificationCtaClicked | notification.cta_clicked |
| Closed without acting | NotificationDismissed | .notificationDismissed | BubblNotificationDismissed | notification.dismissed |
| Media shown or started | MediaViewed | .mediaViewed | BubblMediaViewed | media.viewed |
| Video or audio played to the end | MediaCompleted | .mediaCompleted | BubblMediaCompleted | media.completed |
| Survey started | SurveyStarted | .surveyStarted | BubblSurveyStarted | survey.started |
| Survey answers sent | SurveySubmitted | .surveySubmitted | BubblSurveySubmitted | survey.submitted |
| Entered a geofence | GeofenceEntered | .geofenceEntered | BubblGeofenceEntered | geofence.entered |
| Left a geofence | GeofenceExited | .geofenceExited | BubblGeofenceExited | geofence.exited |
| Something went wrong that Bubbl couldn't fix | Error | .error | BubblError | error |
| The device credential was refused | CredentialRejected | .credentialRejected | BubblCredentialRejected | credential.rejected |
The notification events carry the BubblMessage (message). The geofence events carry locationId, the dashboard location's ID. The error event carries a message string, which diagnostics also keep as lastError.
when an else branch and your switch a default case, and ignore events you don't know. The Kotlin and Dart event types are open, so the compiler insists on it in a when or switch expression; elsewhere, add it yourself.val listener = BubblEventListener { event ->
when (event) {
is BubblEvent.NotificationDisplayed -> analytics.log("bubbl_shown", event.message.id)
is BubblEvent.GeofenceEntered -> analytics.log("bubbl_entered", event.locationId)
else -> {}
}
}
Bubbl.addEventListener(listener)
// later
Bubbl.removeEventListener(listener)let token = Bubbl.addEventListener { event in
switch event {
case .notificationDisplayed(let message): analytics.log("bubbl_shown", message.id)
case .geofenceEntered(let locationId): analytics.log("bubbl_entered", locationId)
default: break
}
}
// later
Bubbl.removeEventListener(token)final subscription = Bubbl.addEventListener((event) {
switch (event) {
case BubblNotificationDisplayed(:final message):
analytics.log('bubbl_shown', message.id);
case BubblGeofenceEntered(:final locationId):
analytics.log('bubbl_entered', locationId);
default:
break;
}
});
// later
await Bubbl.removeEventListener(subscription);const subscription = Bubbl.addEventListener((event) => {
switch (event.type) {
case 'notification.displayed': analytics.log('bubbl_shown', event.message.id); break;
case 'geofence.entered': analytics.log('bubbl_entered', event.locationId); break;
default: break;
}
});
// later
subscription.remove();In Flutter, Bubbl.events is a broadcast Stream<BubblEvent> of the same events, if you prefer a stream. On Android, keep the listener object to remove it; on iOS, keep the BubblEventToken that addEventListener returns (Swift closures have no identity to remove them by).
See BubblEvent for each event's fields.