Firebase and Push
Bubbl can receive campaign notifications through Firebase Cloud Messaging and APNs. Your app owns the Firebase/APNs setup; the Bubbl SDK handles Bubbl payload parsing, token registration, tracking, and optional default UI.
What you need before testing
- A Firebase project connected to the exact Android application ID and iOS bundle ID you are testing.
google-services.jsonin the Android app if using Firebase on Android.GoogleService-Info.plistin the iOS app if using Firebase on iOS.- APNs key/certificate configured in Firebase for iOS push.
- Notification permission requested from the user.
- Your live Bubbl API key.
How push handoff works
Your app remains responsible for Firebase/APNs setup and platform permission prompts. The SDK does not replace Firebase Messaging or APNs. Instead, your app forwards two things to Bubbl:
- The current push token, so Bubbl can target the installed app.
- Firebase/APNs data payloads, so the SDK can parse Bubbl campaign content, track receipt, and apply your rendering mode.
Forward the token whenever the platform gives you a new one. Tokens can change after reinstall, restore, notification permission changes, Firebase refresh, or APNs refresh.
Forward message data exactly as key/value strings. Do not pass only the visible notification title/body wrapper if Firebase gives you both notification and data sections.
Typical integration sequence:
- Initialize Firebase/APNs in your app.
- Boot Bubbl with your live API key.
- Request notification permission at the right point in your app journey.
- Register the current FCM/APNs token with Bubbl.
- Forward foreground, background, and notification tap payloads to the SDK where your platform exposes those handlers.
- Confirm diagnostics after a real device receives a Bubbl campaign notification.
Android
Add Firebase to your app using Firebase's Android setup instructions. The package name in Firebase must match your Android app ID.
On Android 13 and newer, request POST_NOTIFICATIONS at runtime before expecting notification banners.
Add Firebase Messaging:
dependencies {
implementation(platform("com.google.firebase:firebase-bom:34.7.0"))
implementation("com.google.firebase:firebase-messaging")
}
Then forward token and message events from your Firebase Messaging service:
class ExampleMessagingService : FirebaseMessagingService() {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
override fun onNewToken(token: String) {
scope.launch {
BubblSdk.registerPushToken(token)
}
}
override fun onMessageReceived(message: RemoteMessage) {
scope.launch {
BubblSdk.handleFirebasePayload(message.data)
}
}
}
If your app already has its own FirebaseMessagingService, add the Bubbl calls to that existing service instead of creating a second competing service.
Forward the token:
BubblSdk.registerPushToken(token)
Forward incoming Firebase data payloads:
val bubblPayload = BubblSdk.handleFirebasePayload(remoteMessage.data)
If bubblPayload is null, the message did not contain Bubbl notification content. Your app can ignore it or handle it as a non-Bubbl message.
For notification taps that open your launcher activity, forward the intent through the Bubbl Android notification helper if your app uses the SDK default tap behavior. If your app renders its own tap destination, parse the payload and call the host-rendered tracking methods when the user opens the content.
iOS
Enable these capabilities in Xcode if you need push and background behavior:
- Push Notifications.
- Background Modes: remote notifications.
- Background Modes: location updates, if your app uses background location.
Forward APNs and FCM tokens:
try await BubblClient.shared.updateAPNsToken(deviceToken)
try await BubblClient.shared.updateFCMToken(token)
Ask for notification permission and register for remote notifications:
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
if granted {
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
Forward remote notification payloads:
let bubblPayload = try await BubblClient.shared.handleRemoteNotification(userInfo)
If your app uses Firebase Messaging on iOS, forward the FCM token with updateFCMToken. If your app uses APNs directly, forward the APNs device token with updateAPNsToken.
If your app owns UNUserNotificationCenterDelegate, keep your existing delegate and forward Bubbl payloads inside the delegate methods you already use. Make sure the delegate is installed early enough for foreground presentation and tap handling.
Flutter
Use FlutterFire for Firebase setup:
flutter pub add firebase_core firebase_messaging
flutterfire configure
Initialize Firebase before booting Bubbl:
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
After Firebase returns a token:
final token = await FirebaseMessaging.instance.getToken();
if (token != null) {
await BubblSdk.instance.registerPushToken(token);
}
Forward foreground Firebase message data:
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
await BubblSdk.instance.handleFirebasePayload(message.data);
});
Foreground example with host-rendered UI:
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
final payload = await BubblSdk.instance.handleFirebasePayload(message.data);
if (payload == null) {
return;
}
showBubblOfferSheet(payload);
await BubblSdk.instance.handleNotificationOpen(
payload,
action: 'foreground_sheet',
);
});
You can also forward a token you already have:
await BubblSdk.instance.registerPushToken(token);
Forward Firebase message data:
final payload = await BubblSdk.instance.handleFirebasePayload(message.data);
For background messages, follow FlutterFire's background handler requirements. Initialize Firebase in the background isolate before calling SDK methods.
If you use a background handler, keep it small. Initialize Firebase, forward the message data, and return. Avoid opening UI from the background handler; route UI from the notification tap path or the next foreground app state.
React Native
Install React Native Firebase app and messaging modules:
npm install @react-native-firebase/app @react-native-firebase/messaging
On Android, add the default notification channel metadata to android/app/src/main/AndroidManifest.xml if Firebase Messaging and Bubbl SDK both contribute channel metadata:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application>
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="bubbl_notifications"
tools:replace="android:value" />
</application>
</manifest>
After Firebase returns a token:
import messaging, {
type FirebaseMessagingTypes,
} from '@react-native-firebase/messaging';
const token = await messaging().getToken();
await Bubbl.registerPushToken(token);
Forward Firebase message data:
messaging().onMessage(async (remoteMessage: FirebaseMessagingTypes.RemoteMessage) => {
const data = Object.fromEntries(
Object.entries(remoteMessage.data ?? {}).map(([key, value]) => [
key,
String(value),
]),
);
await Bubbl.handleFirebasePayload(data);
});
Foreground example with host-rendered UI:
messaging().onMessage(async remoteMessage => {
const data = Object.fromEntries(
Object.entries(remoteMessage.data ?? {}).map(([key, value]) => [
key,
String(value),
]),
);
const payload = await Bubbl.handleFirebasePayload(data);
if (!payload) {
return;
}
showBubblOfferSheet(payload);
await Bubbl.handleNotificationOpen(payload, 'foreground_sheet');
});
For background messages, follow React Native Firebase's background message handler requirements. Make sure the native app has initialized enough of the Bubbl SDK before forwarding background data.
If your app uses React Navigation or another router, store the parsed payload or notification ID during the tap path, then navigate after your app container is ready. This avoids losing the campaign when the app cold-starts from a notification.
Parser-only payload checks
If you have a documented sample payload from Bubbl support, you can pass it to handleFirebasePayload to confirm parsing. This does not prove that Firebase delivery is configured correctly; it only proves that your app can hand a Bubbl-style payload to the SDK.
Sample parser-only payload:
{
"bubbl_notification_id": "sample-notification",
"title": "Bubbl verification",
"body": "This is a Bubbl verification message",
"curated_notification_id": "sample-curated-notification",
"location_id": "sample-location",
"cta_label": "Open",
"cta_url": "https://www.bubbl.tech"
}
For full validation, send a real push to the same Firebase app ID or iOS bundle ID that is installed on the device.
Common push checks
- The Firebase config file matches the app ID or bundle ID installed on the device.
- Notification permission is granted.
- The app has forwarded the latest token to Bubbl.
- The SDK booted successfully before push handling.
- iOS provisioning includes push entitlement.
- Android notification channels are not disabled in system settings.
- The dashboard campaign targets the same live app/API key that the installed app booted with.
- Your foreground path and background/tap path both forward the data payload, not just visible notification text.
- The device is not suppressing notifications through Focus, Do Not Disturb, battery saver, or app-specific notification settings.
Foreground and background behavior
Test foreground and background paths separately:
- Foreground: your app process is active. Confirm the message listener runs,
handleFirebasePayloadreturns a payload for Bubbl messages, and the configured rendering path works. - Background: the app is not visible. Confirm the platform delivers the notification, the user can tap it, and the SDK receives the open/tap path where your platform integration forwards it.
- Terminated or cold start: confirm your app can boot, restore its configuration, and route the notification tap without losing the payload.
Collect diagnostics after each path. A successful foreground parse does not prove background delivery, and a successful background delivery does not prove your foreground UI path.