BubblDocs

iOS Developer Documentation

📘 Objective — To provide an iOS App Developer with an overview of the information required to implement the Bubbl Plugin into an existing app written in Objective-C or Swift.

📘 Audience — iOS App Developer

Versions

Bubbl iOS Plugin Version: 2.0.7
Minimum iOS Version: 15.0
Xcode Version: 14.0+
Swift Version: 5.7+

Prerequisites

  • A Bubbl Dashboard account with an active API key
  • Firebase project with Cloud Messaging enabled
  • Firebase Messaging SDK integrated - Required for FCM token generation
  • Apple Developer account with push notification capability
  • CocoaPods or manual framework integration setup

Integration Options

You can integrate the Bubbl iOS SDK using two methods. Note: These options are only for the Bubbl SDK itself—you can integrate Firebase using any method you prefer (CocoaPods, SPM, or manual).

Bubbl API Key

To integrate the plugin with your app, you will need a unique

API Key

You will find your API_KEY on the Bubbl Dashboard Company page.

Key Features

  • Geofence-based notifications: Trigger notifications when users enter/exit defined locations
  • Firebase Cloud Messaging: Uses FCM tokens for reliable push notification delivery (Firebase Messaging required)
  • Background monitoring: Continuous location tracking even when app is closed
  • Segmentation support: Target specific user groups with custom tags
  • Battery optimization: Efficient power management for location services

Required Permissions

Your app must request the following permissions:

  • Location (Always): For background geofence monitoring
  • Push Notifications: For notification delivery
  • Background Modes: Location updates capability

SDK Architecture

The Bubbl iOS SDK consists of:

  • BubblPlugin
    - Main SDK interface and initialization
  • NotificationManager
    - Handles notification presentation and taps
  • GeofenceService
    - Manages location-based triggers
  • APIService
    - Backend communication (internal)

Quick Start Guide

  1. Install the SDK via CocoaPods or manual integration
  2. Install Firebase Messaging SDK (required dependency)
  3. Configure Firebase and add
    GoogleService-Info.plist
  4. Set up Firebase Messaging delegate to receive FCM tokens
  5. Use gated initialization pattern to ensure FCM token is available before SDK start
  6. Implement delegate callbacks for authentication status
  7. Handle notification taps using NotificationManager
🔥 Firebase Messaging Required: The Bubbl SDK requires Firebase Cloud Messaging to obtain FCM tokens for push notifications. You must integrate Firebase Messaging in your app (via CocoaPods, SPM, or manual) before using Bubbl SDK.
⚠️ Critical: Initialize SDK Only After FCM Token is Available

The Bubbl SDK requires a valid FCM token to authenticate and register the device. Initializing before the token is ready can cause:
  • "device_token: pending" errors
  • Failed authentication on first launch
  • SDK not loading campaigns or geofences

Use the gated initialization pattern shown in the integration guides to ensure reliable SDK start on fresh installs and TestFlight builds. This pattern uses
Messaging.messaging().token
to force token fetch and includes automatic retry logic.
⚠️ Multi-SDK Notification Delegate Limitation:

The Bubbl SDK sets itself as the UNUserNotificationCenter delegate and does not support delegate chaining.

If your app uses multiple SDKs that handle notifications:
  • Only ONE SDK can be the notification delegate at a time
  • The last SDK to set the delegate will override previous ones
  • This may cause notification handling conflicts with other SDKs

Note: Bubbl SDK must receive notification delegate callbacks to properly handle notification presentation, tap events, and campaign tracking. See the Multi-SDK Notification Router Pattern section below for the recommended solution.

Multi-SDK Notification Router Pattern

For apps using multiple notification SDKs, implement the notification router pattern where your host app owns the

UNUserNotificationCenter
delegate and routes notifications to the appropriate SDK based on payload inspection.

Bubbl Notification Identification Fields

Bubbl notifications can be identified by these payload fields:

  • n_id
    - Bubbl notification ID
  • location_id
    - Bubbl location ID
  • notification_data
    - Nested object containing Bubbl-specific data

Notification Router Implementation

Create a notification router class that your app owns:

import UserNotifications
import Bubbl

class AppNotificationRouter: NSObject, UNUserNotificationCenterDelegate {

    static let shared = AppNotificationRouter()

    func setup() {
        UNUserNotificationCenter.current().delegate = self
    }

    // MARK: - Check if notification is from Bubbl
    private func isBubblNotification(_ userInfo: [AnyHashable: Any]) -> Bool {
        // Check for Bubbl-specific fields
        if userInfo["n_id"] != nil { return true }
        if userInfo["location_id"] != nil { return true }
        if userInfo["notification_data"] != nil { return true }
        return false
    }

    // MARK: - Foreground presentation
    func userNotificationCenter(
        _ center: UNUserNotificationCenter,
        willPresent notification: UNNotification,
        withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
    ) {
        let userInfo = notification.request.content.userInfo

        if isBubblNotification(userInfo) {
            // Route to Bubbl SDK
            Bubbl.NotificationManager.shared.userNotificationCenter(
                center,
                willPresent: notification,
                withCompletionHandler: completionHandler
            )
        } else {
            // Handle other SDK notifications or your own
            // e.g., forward to Firebase, OneSignal, etc.
            completionHandler([.banner, .sound, .badge])
        }
    }

    // MARK: - Notification tap handling
    func userNotificationCenter(
        _ center: UNUserNotificationCenter,
        didReceive response: UNNotificationResponse,
        withCompletionHandler completionHandler: @escaping () -> Void
    ) {
        let userInfo = response.notification.request.content.userInfo

        if isBubblNotification(userInfo) {
            // Route to Bubbl SDK
            Bubbl.NotificationManager.shared.userNotificationCenter(
                center,
                didReceive: response,
                withCompletionHandler: completionHandler
            )
        } else {
            // Handle other SDK notifications or your own
            completionHandler()
        }
    }
}

Setup in AppDelegate

func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {

    // Configure Firebase first
    FirebaseApp.configure()

    // Set YOUR app as the notification delegate (not Bubbl SDK)
    AppNotificationRouter.shared.setup()

    // Request permissions
    UNUserNotificationCenter.current().requestAuthorization(
        options: [.alert, .sound, .badge]
    ) { granted, _ in
        DispatchQueue.main.async {
            application.registerForRemoteNotifications()
        }
    }

    return true
}

Delegate Verification Pattern

After starting the Bubbl SDK, verify that your delegate wasn't overridden. Some SDKs may set the delegate asynchronously during initialization:

// After calling BubblPlugin.shared.start(...)
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
    let currentDelegate = UNUserNotificationCenter.current().delegate

    if currentDelegate === AppNotificationRouter.shared {
        print("✅ Delegate still set correctly after SDK start")
    } else {
        print("⚠️ Delegate was overridden - resetting...")
        AppNotificationRouter.shared.setup()
    }
}
💡 Tip: The 1-second delay allows async SDK initialization to complete before verifying the delegate. If you find your delegate is being overridden, re-set it after the SDK starts.

Support and Documentation

For detailed implementation guides, please refer to:

Respecting your app users

The Bubbl Plugin can be configured to respect app users by restricting notification features when a device’s battery reaches a lower limit; this can be set on the SDK Configurations page.