# Braze Device Mode Integration


After you have successfully instrumented Braze as a destination in RudderStack, follow this guide to correctly send your events to Braze in [device mode]({{< ref "/destinations/rudderstack-connection-modes.md#cloud-mode" >}}).

## Add Braze integration

{{< warning >}}
Make sure to add the Braze integration to your project before sending events to Braze in device mode.
{{< /warning >}}

Depending on your integration platform, follow these steps:

{{< tabs tabTotal="7" >}}
{{% tab tabName="Android (Kotlin)" %}}

{{< warning >}}
The Braze integration v1.0.0 and above requires minimum SDK version (`minSdk`) of 25.
{{< /warning >}}

Follow the steps in this section to add Braze to your Kotlin project.

{{< version-badge registry="maven" package="com.rudderstack.integration.kotlin/braze" label="Maven Central" fallback="1.4.1" href="https://central.sonatype.com/artifact/com.rudderstack.integration.kotlin/braze" >}}

1. In your module (app-level) Gradle file (usually `<project>/<app-module>/build.gradle.kts` or `<project>/<app-module>/build.gradle`), add the following dependencies for the RudderStack-Braze integration:

```kotlin
dependencies {
  // ...
  
  // Add Rudder Kotlin and Braze integration SDKs:
  implementation("com.rudderstack.sdk.kotlin:android:<latest-version>")
  implementation("com.rudderstack.integration.kotlin:braze:<latest-version>")
}
```

2. For further steps on permissions and other optional configurations, see the [Braze documentation](https://www.braze.com/docs/developer_guide/sdk_integration).
3. Add the SDK initialization and the `Rudder-Braze` integration in your `Application` class:

```kotlin
import android.app.Application
import com.rudderstack.sdk.kotlin.android.Analytics
import com.rudderstack.sdk.kotlin.android.Configuration
import com.rudderstack.integration.kotlin.braze.BrazeIntegration

class MyApplication : Application() {
    lateinit var analytics: Analytics

    override fun onCreate() {
        super.onCreate()
        analytics = Analytics(
            configuration = Configuration(
                writeKey = "WRITE_KEY",
                application = this,
                dataPlaneUrl = "DATA_PLANE_URL",
            )
        )
        
        analytics.add(BrazeIntegration())
    }
}
```

{{% /tab %}}
{{% tab tabName="iOS (Swift)" %}}

{{< version-badge registry="github-tag" package="rudderlabs/integration-swift-braze" label="Swift Package Manager" fallback="1.2.0" href="https://github.com/rudderlabs/integration-swift-braze/" >}}

Follow these steps to add the Braze integration to your Swift project using Swift Package Manager:

1. In Xcode, select **File > Add Package Dependencies...**.

{{< figure src="images/event-stream-sources/swift/add-package-dependencies.webp"  >}}

2. Enter the below package repository URL in the search bar:

```text
https://github.com/rudderlabs/integration-swift-braze/
```

3. Select the latest version and the target to which you want to add the package.
4. Click **Add Package**.

Alternatively, you can add the dependency to your `Package.swift` file, as shown:

```swift
dependencies: [
    .package(url: "<https://github.com/rudderlabs/integration-swift-braze.git>", from: "<latest_integration_version>")
]
```

#### Usage

1. Import the SDK and the integration:

```swift
import RudderStackAnalytics
import RudderIntegrationBraze
```

2. Add `BrazeIntegration` to your `analytics` instance:

```swift
// Initialize RudderStack Analytics
let analytics = Analytics(
    configuration: Configuration(
        writeKey: "<WRITE_KEY>",
        dataPlaneUrl: "<DATA_PLANE_URL>"
    )
)

// Add Braze Integration
analytics.add(plugin: BrazeIntegration())
```
{{% /tab %}}
{{% tab tabName="React Native" %}}

1. Add the RudderStack-Braze module to your app by running the following command:

```bash
npm install @rudderstack/rudder-integration-braze-react-native
```

```bash
yarn add @rudderstack/rudder-integration-braze-react-native
```

2. Import the module you added above and add it to your SDK initialization code:

```typescript
import rudderClient from "@rudderstack/rudder-sdk-react-native";
import braze from "@rudderstack/rudder-integration-braze-react-native";
const config = {
  dataPlaneUrl: DATA_PLANE_URL,
  trackAppLifecycleEvents: true,
  withFactories: [braze]
};
rudderClient.setup(WRITE_KEY, config);
```

{{% /tab %}}
{{% tab tabName="Flutter" %}}

1. Add the following dependency to the `dependencies` section of your `pubspec.yaml` file:

```yaml
rudder_integration_braze_flutter: ^1.0.1
```

2. Run the below command to install the dependency added in the above step:

```groovy
flutter pub get
```

3. Import the `RudderIntegrationBrazeFlutter` in your application where you are initializing the SDK:

```dart
import 'package:rudder_integration_braze_flutter/rudder_integration_braze_flutter.dart';
```

4. Change the initialization of your `RudderClient` as shown:

```dart
final RudderController rudderClient = RudderController.instance;
RudderConfigBuilder builder = RudderConfigBuilder();
builder.withFactory(RudderIntegrationBrazeFlutter());
rudderClient.initialize(<write_key>, config: builder.build(), options: null);
```

{{% /tab %}}
{{% tab tabName="Android (Java) — Legacy" %}}

1. Add the following under `dependencies` section:

```groovy
implementation 'com.rudderstack.android.sdk:core:[1.0,2.0)'
implementation 'com.rudderstack.android.integration:braze:[1.3.0,)'
```

{{< warning >}}
The [Braze-RudderStack Android SDK integration](https://github.com/rudderlabs/rudder-integration-braze-android) v2.0.0 and above requires a minimum SDK version (`minSdkVersion`) of 25.
{{< /warning >}}

2. Add the following permissions to the `AndroidManifest.xml` file:

```groovy
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
```

3. Change the SDK initialization to the following:

```kotlin
// initialize Rudder SDK
val rudderClient: RudderClient =
    RudderClient.getInstance(
        this,
        WRITE_KEY,
        RudderConfig.Builder()
            .withDataPlaneUrl(DATA_PLANE_URL)
            .withLogLevel(RudderLogger.RudderLogLevel.DEBUG)
            .withFactory(BrazeIntegrationFactory.FACTORY)
            .build()
    )
```

{{% /tab %}}
{{% tab tabName="iOS (Obj-C) — Legacy" %}}

1. Open the `Podfile` of your project and add the following:

```ruby
pod 'Rudder-Braze'
```

2. Run the `pod install` command.
3. Change the SDK initialization to the following snippet:

```objectivec
RudderConfigBuilder *builder = [[RudderConfigBuilder alloc] init];
[builder withDataPlaneUrl:<data_plane_url>];
[builder withFactory:[RudderBrazeFactory instance]];
[RudderClient getInstance:<write_key>; config:[builder build]];
```

{{% /tab %}}
{{% tab tabName="iOS SDK v2 — Legacy" %}}

{{< warning >}}
RudderStack supports this device mode integration for Braze v4.4.4 and above.
{{< /warning >}}

1. Install `RudderBraze` (available through [CocoaPods](https://cocoapods.org)) by adding the following to your `Podfile`:

```ruby
pod 'RudderBraze', '~> 1.0.0'
```

2. Run the `pod install` command.
3. Import the SDK depending on your preferred platform:

```swift
import RudderBraze
```

```objectivec
@import RudderBraze;
```

4. Add the imports to your `AppDelegate` file under the `didFinishLaunchingWithOptions` method:

```swift
let config: RSConfig = RSConfig(writeKey: WRITE_KEY)
            .dataPlaneURL(DATA_PLANE_URL)
RSClient.sharedInstance().configure(with: config)
RSClient.sharedInstance().addDestination(RudderBrazeDestination())
```

```objectivec
RSConfig *config = [[RSConfig alloc] initWithWriteKey:WRITE_KEY];
[config dataPlaneURL:DATA_PLANE_URL];
[[RSClient sharedInstance] configureWith:config];
[[RSClient sharedInstance] addDestination:[[RudderBrazeDestination alloc] init]];
```

{{< info >}}
To send push notification events, see [Send push notifications]({{< ref "#send-push-notification-events" >}}).
{{< /info >}}

{{% /tab %}}
{{< /tabs >}}

### Use platform-specific Braze App Identifier keys

For device mode connections, you can configure platform-specific (Android, iOS, and web) Braze App Identifier keys while [setting up your Braze destination]({{< ref "destinations/streaming-destinations/braze/setup-guide.md#connection-settings" >}}). This is useful especially when connecting cross-platform SDK sources like React Native and Flutter, while also allowing Android and iOS sources to be configured to the same Braze destination.

To use this feature:

1. Enable the **Enable Platform-specific App Identifier Keys** setting in the [Connection settings]({{< ref "destinations/streaming-destinations/braze/setup-guide.md#connection-settings" >}}).
2. Configure the relevant App Identifier keys based on your connected sources.

#### How App Identifier key selection works

The Braze device mode integration looks for platform-specific App Identifier keys first. If unavailable, it uses the [Default App Identifier Key]({{< ref "destinations/streaming-destinations/braze/setup-guide.md#connection-settings" >}}) instead.

Note that:

- An older version of the device mode integration will continue to work with the default App Identifier key.
- If you remove the default App Identifier key and configure platform-specific App Identifier keys, **you must upgrade** to the latest version of the device mode integration highlighted below:

| SDK | Minimum supported integration version |
| :----| :----| 
| Android (Kotlin) | [1.1.1](https://github.com/rudderlabs/rudder-sdk-kotlin/releases/tag/com.rudderstack.integration.kotlin.braze%401.1.1) |
| iOS (Swift) | [1.0.1](https://github.com/rudderlabs/integration-swift-braze/releases/tag/1.0.1) |
| React Native | [2.1.0](https://github.com/rudderlabs/rudder-sdk-react-native/releases/tag/rudder-integration-braze-react-native%402.1.0)| 
| Flutter | [2.5.0](https://github.com/rudderlabs/rudder-sdk-flutter/releases/tag/rudder_integration_braze_flutter-v2.5.0)  |
| Android (Java) — Legacy | [2.1.1](https://github.com/rudderlabs/rudder-integration-braze-android/releases/tag/v2.1.1) | 
| iOS (Obj-C) — Legacy | [4.2.1](https://github.com/rudderlabs/rudder-integration-braze-ios/releases/tag/v4.2.1) |

#### Migration example

**Scenario**

Suppose you have three sources connected to three separate Braze destinations in your current setup:

- Android source (A) → Braze destination (B1)
- iOS source (B) → Braze destination (B2)
- JavaScript source (C) → Braze destination (B3)

Each destination is configured with platform-specific keys. 

**What you want to achieve**

You want to consolidate these connections to a single Braze destination (B3, for example) that supports all the platform-specific App Identifier keys, simplifying your overall setup.

**Steps**

1. **Upgrade your SDK integrations**: Upgrade your Android and iOS SDK integrations to the minimum versions that support platform-specific App Identifier keys. See the [supported versions table](#how-app-identifier-key-selection-works) above for details.

2. **Enable platform-specific keys**: In your existing Braze destination B3 (previously connected only to the JavaScript source), enable the **Enable Platform-specific App Identifier Keys** toggle in the [Connection settings]({{< ref "destinations/streaming-destinations/braze/setup-guide.md#connection-settings" >}}) and specify the platform-specific key for the JavaScript source.
3. **Connect additional sources**: Connect your Android (A) and iOS (B) sources to the Braze destination.
4. **Add platform-specific keys**: Configure the Android and iOS App Identifier keys in the destination settings.
5. **Remove old destinations**: Delete the older separate Braze destinations (B1 and B2) that are no longer needed.

After completing these steps, all three sources (Android, iOS, and JavaScript) send events to a single Braze destination configured with platform-specific App Identifier keys.

## Identify

You can use the [`identify`]({{< ref "event-spec/standard-events/identify.md" >}}) call to identify a user in Braze in any of the below cases:

- When the user registers to the app for the first time.
- When they log into their app.
- When they update their information.

A sample `identify` call is shown below:

```javascript
rudderanalytics.identify("1hKOmRA4GRlm", {
  email: "alex@example.com",
  name: "Alex Keener"
});
```

### Set custom user ID (`externalId`)

In mobile device mode, that is, when using Android (Java), iOS (Obj-C), React Native, or Flutter as source, you need to pass `externalId` in your `identify` events. Otherwise, Braze uses `userId` to identify the user.

{{< info >}}
Braze gives first preference to the `externalId` field in the `identify` event to identify the user. If `externalId` is absent, it falls back to the `userId` field.
{{< /info >}}

The following code snippet shows how to add an `externalId` to your `identify` event using the [React Native SDK]({{< ref "sources/event-streams/sdks/rudderstack-react-native-sdk.md#setting-custom-id" >}}):

```typescript
const options = {
  externalIds: [
    {
      id: "<your_external_id>",
      type: "brazeExternalId",
    },
  ],
}
rudderClient.identify(
  "1hKOmRA4GRlm",
  {
    email: "alex@example.com",
    gender: "male",
  },
  options
)
```

{{< warning >}}
Make sure to send the `identify` event containing the `externalId` before sending any subsequent `track` events. That way, RudderStack is able to successfully persist the `externalId` information in all the future events.
{{< /warning >}}

## Track

The [`track`]({{< ref "event-spec/standard-events/track.md" >}}) event lets you record the customer events along with any associated properties.

A sample `track` call is shown below:

```javascript
rudderanalytics.track("Product Added", {
  numberOfRatings: "12",
  name: "item 1"
});
```

### Order Completed

When you use the `track` call for an `Order Completed` event, RudderStack sends the product information present in the event to Braze as `purchases`.

A sample `Order Completed` event is shown:

```javascript
rudderanalytics.track("Order Completed", {
  userId: "1hKOmRA4GRlm",
  currency: "USD",
  products: [
    {
      product_id: "123454387",
      name: "Game",
      price: 15.99
    }
  ]
});
```

## Page

The [`page`]({{< ref "event-spec/standard-events/page.md" >}}) event lets you record your website's page views, with the additional relevant information about the viewed page.

A sample `page` call is as shown:

```javascript
rudderanalytics.page("Cart", "Cart Viewed", {
  path: "/cart",
  referrer: "test.com",
  search: "term",
  title: "test_item",
  url: "http://test.in"
});
```

## Delta management for `identify` and `track` calls

If you are sending events to Braze in device mode, you can save costs by deduplicating your `identify` calls. To do so, enable the [Deduplicate Traits]({{< ref "destinations/streaming-destinations/braze/setup-guide.md#deduplication-settings" >}}) dashboard setting. RudderStack then sends only the changed or modified attributes (traits) to Braze.

{{< info >}}
RudderStack recommends reviewing Braze's [data points policy](https://www.braze.com/docs/user_guide/onboarding_with_braze/data_points/) to fully understand how this functionality can help you avoid data overages.
{{< /info >}}

## Advanced features

This section covers some advanced Braze operations that you can perform using RudderStack.

### Send push notification events

Depending on your iOS (Obj-C) SDK version, follow these steps to send push notification events to Braze:

{{< tabs tabTotal="3" >}}
{{% tab tabName="iOS (Swift)" %}}

{{< warning >}}
The iOS (Swift) SDK does not auto-forward push notifications. You must explicitly integrate the push notification handling code in your app.

The underlying Braze instance is exposed and can be accessed via the `getDestinationInstance()` or `onDestinationReady()` callbacks for customizing the push notification handling code.
{{< /warning >}}

#### Prerequisites

You must enable the **Push Notifications** capability in Xcode under your target's **Signing & Capabilities** section.

#### Step 1: Initialize integration and register for push notifications

Store the `BrazeIntegration` instance as a property so it can be referenced throughout the app's lifecycle. Set up `UNUserNotificationCenter` synchronously before the app finishes launching.

For SwiftUI apps, use `@UIApplicationDelegateAdaptor` to wire in a `UIApplicationDelegate` implementation:

```swift
import SwiftUI
import UIKit
import UserNotifications
import RudderStackAnalytics
import RudderIntegrationBraze
import BrazeKit

@main
struct MyApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    var body: some Scene {
        WindowGroup { ContentView() }
    }
}

class AppDelegate: UIResponder, UIApplicationDelegate {

    // Store the plugin instance — required for getDestinationInstance() and onDestinationReady
    private let brazePlugin = BrazeIntegration()
    private var pendingDeviceToken: Data?

    private var braze: Braze? {
        brazePlugin.getDestinationInstance() as? Braze
    }

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

    private func setupRudderStack() {
        let configuration = Configuration(
            writeKey: "<WRITE_KEY>",
            dataPlaneUrl: "<DATA_PLANE_URL>"
        )
        let analytics = Analytics(configuration: configuration)
        analytics.add(plugin: brazePlugin)
    }

    private func setupPushNotifications(_ application: UIApplication) {
        let center = UNUserNotificationCenter.current()
        center.setNotificationCategories(Braze.Notifications.categories)
        center.delegate = self
        center.requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
            guard granted else { return }
            DispatchQueue.main.async {
                application.registerForRemoteNotifications()
            }
        }
    }
}
```

#### Step 2: Forward device token

The `didRegisterForRemoteNotificationsWithDeviceToken` callback can be triggered very early during app launch. Depending on OS-level timing, the device token may be received before the Braze SDK has been initialized and is ready to accept the token.

To avoid losing the token in such cases, temporarily store it and register it once Braze becomes available using `onDestinationReady`:

```swift
extension AppDelegate {

    func application(_ application: UIApplication,
                     didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        if let braze {
            // Braze already initialized — register immediately
            braze.notifications.register(deviceToken: deviceToken)
        } else {
            // Hold token until onDestinationReady fires
            pendingDeviceToken = deviceToken
            brazePlugin.onDestinationReady { [weak self] instance, result in
                guard let self, case .success = result,
                      let token = self.pendingDeviceToken,
                      let braze = instance as? Braze else { return }
                braze.notifications.register(deviceToken: token)
                self.pendingDeviceToken = nil
            }
        }
    }

    func application(_ application: UIApplication,
                     didFailToRegisterForRemoteNotificationsWithError error: Error) {
        // Handle registration failure
    }
}
```

#### Step 3: Handle notification events

```swift
extension AppDelegate: UNUserNotificationCenterDelegate {

    // Foreground display options
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.list, .banner, .sound])
    }

    // Notification tap / action response
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
        if let braze, braze.notifications.handleUserNotification(response: response, withCompletionHandler: completionHandler) {
            return
        }
        completionHandler()
    }

    // Silent / background push
    func application(_ application: UIApplication,
                     didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        if let braze, braze.notifications.handleBackgroundNotification(userInfo: userInfo, fetchCompletionHandler: completionHandler) {
            return
        }
        completionHandler(.noData)
    }
}
```

See the following references for more information:

- [Example code](https://github.com/rudderlabs/integration-swift-braze/blob/develop/Example/AppDelegate.swift)
- [Braze documentation](https://www.braze.com/docs/developer_guide/push_notifications?tab=manual)

{{% /tab %}}
{{% tab tabName="iOS (Obj-C) — Legacy" %}}

1. Follow the [Braze documentation](https://www.braze.com/docs/developer_guide/platform_integration_guides/swift/push_notifications/integration#push-notification-certificate) to generate a push notification certificate.
2. Add the following code to your `AppDelegate` file under the `didFinishLaunchingWithOptions` method:

```objectivec
[[UIApplication sharedApplication] registerForRemoteNotifications];

UNUserNotificationCenter *center = UNUserNotificationCenter.currentNotificationCenter;
[center setNotificationCategories:BRZNotifications.categories];
center.delegate = self;
UNAuthorizationOptions options = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
if (@available(iOS 12.0, *)) {
    options = options | UNAuthorizationOptionProvisional;
}
[center requestAuthorizationWithOptions:options
                      completionHandler:^(BOOL granted, NSError *_Nullable error) {
    NSLog(@"Notification authorization, granted: %d, "
          @"error: %@)",
          granted, error);
}];
```

{{< warning >}}
You must assign the delegate object using `center.delegate = self` synchronously before your app finishes launching - preferably in `application:didFinishLaunchingWithOptions`. 

Otherwise, your app may miss any incoming push notificaitons. See [Apple's `UNUserNotificationCenterDelegate` documentation](https://developer.apple.com/documentation/usernotifications/unusernotificationcenterdelegate) for more information.
{{< /warning >}}

3. Register push tokens with Braze:

```objectivec
// - Register the device token with Braze
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    if ([RudderBrazeFactory instance].integration) {
        [[RudderBrazeFactory instance].integration didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
    }
}
```

{{< warning >}}
Make sure that `RudderBrazeFactory` is initialized before making calls to this push API. 

Since the Braze push API is designed as an instance method, it relies on the SDK that is correctly initialized beforehand. To do this, you can utilize the [`dispatch_after`](https://developer.apple.com/documentation/dispatch/1452876-dispatch_after) API.
{{< /warning >}}

4. Enable push handling:

```objectivec
// - Add support for silent notification

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler: (void (^)(UIBackgroundFetchResult))completionHandler {
    if ([RudderBrazeFactory instance].integration) {
        [[RudderBrazeFactory instance].integration didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
    }
}

// - Add support for push notifications

- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
    if ([RudderBrazeFactory instance].integration) {
        [[RudderBrazeFactory instance].integration didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
    }
}

// - Add support for displaying push notification when the app is currently running in the foreground

- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler: (void (^)(UNNotificationPresentationOptions))completionHandler {
    if (@available(iOS 14, *)) {
        completionHandler(UNNotificationPresentationOptionList |
                          UNNotificationPresentationOptionBanner);
    } else {
        completionHandler(UNNotificationPresentationOptionAlert);
    }
}
```

{{< info >}}
Braze recommends invoking the [push integration code](https://www.braze.com/docs/developer_guide/platform_integration_guides/swift/push_notifications/integration#step-3-enable-push-handling) within the application's main thread.
{{< /info >}}

{{% /tab %}}
{{% tab tabName="iOS SDK v2 — Legacy" %}}
Add the following code to your `AppDelegate` file under the `didFinishLaunchingWithOptions` method:

```swift
if #available(iOS 10, *) {
    let center = UNUserNotificationCenter.current()
    center.delegate = self
    var options: UNAuthorizationOptions = [.alert, .sound, .badge]
    if #available(iOS 12.0, *) {
        options = UNAuthorizationOptions(rawValue: options.rawValue | UNAuthorizationOptions.provisional.rawValue)
        }
        center.requestAuthorization(options: options) { (granted, error) in
            RSClient.sharedInstance().pushAuthorizationFromUserNotificationCenter(granted)
    }
    UIApplication.shared.registerForRemoteNotifications()
} else {
    let types: UIUserNotificationType = [.alert, .badge, .sound]
    let setting: UIUserNotificationSettings = UIUserNotificationSettings(types: types, categories: nil)
    UIApplication.shared.registerUserNotificationSettings(setting)
    UIApplication.shared.registerForRemoteNotifications()
}
```

```objectivec
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
  center.delegate = self;
  UNAuthorizationOptions options = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
  if (@available(iOS 12.0, *)) {
  options = options | UNAuthorizationOptionProvisional;
  }
  [center requestAuthorizationWithOptions:options
                        completionHandler:^(BOOL granted, NSError * _Nullable error) {
      [[RSClient sharedInstance] pushAuthorizationFromUserNotificationCenter:granted];
  }];
  [[UIApplication sharedApplication] registerForRemoteNotifications];
} else {
  UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound) categories:nil];
  [[UIApplication sharedApplication] registerForRemoteNotifications];
  [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}
```

{{% /tab %}}
{{< /tabs >}}

### Send in-app message events

{{< tabs tabTotal="3" >}}
{{% tab tabName="iOS (Swift)" %}}

{{< warning >}}
Braze in-app messages are not automatically supported in the iOS (Swift) SDK. After the Braze SDK is initialized, you must explicitly configure a presenter — use the `onDestinationReady` callback to assign `BrazeInAppMessageUI` as the in-app message presenter.
{{< /warning >}}

#### 1. Add dependency

- Using `Package.swift` (requires adding `BrazeUI` to your target's package dependencies in the `Package.swift` file):

```swift
..
dependencies: [
  .package(url: "https://github.com/braze-inc/braze-swift-sdk-prebuilt-static", from: "<latest_version>"),
],
targets: [
  .target(
    name: "<your_target>",
    dependencies: [
      .product(name: "BrazeUI", package: "braze-swift-sdk-prebuilt-static"),
    ]
   )
]
..
```

- Using SPM:

  - Use [the Braze repository](https://github.com/braze-inc/braze-swift-sdk-prebuilt-static) to search for the package.
  - Select the `BrazeUI` package to add it as a dependency for your target.

#### 2. Implementation

After add the dependency, import the package as shown:

```swift
import BrazeKit
import BrazeUI
import RudderIntegrationBraze

// Inside setupAnalytics(), after analytics.add(plugin: brazePlugin):
brazePlugin.onDestinationReady { instance, result in
    guard case .success = result, let braze = instance as? Braze else { return }
    braze.inAppMessagePresenter = BrazeInAppMessageUI()
}
```

In-app messages are triggered by custom events. When the app is foregrounded and a matching campaign is active in the Braze dashboard, the message displays automatically after the presenter is assigned.

See the [Braze documentation](https://www.braze.com/docs/developer_guide/in_app_messages) for more information on this feature.

{{% /tab %}}
{{% tab tabName="iOS (Obj-C) — Legacy" %}}

{{< info >}}
This feature is available in the [iOS (Obj-C) SDK]({{< ref "sources/event-streams/sdks/rudderstack-ios-sdk/_index.md" >}}) [device mode integration](https://github.com/rudderlabs/rudder-integration-braze-ios) starting from version 1.4.0.
{{< /info >}}

1. Add the following line to your `Podfile` for Braze IAM support:

```ruby
pod 'BrazeUI'
```

2. Navigate to your Xcode app project directory and run `pod install`.
3. Import the BrazeUI SDK in your `AppDelegate.m` file:

```objectivec
@import BrazeUI;
```

4. Add a static variable to your `AppDelegate.m` file to keep a reference to the Braze instance throughout your app's lifetime:

```objectivec
static Braze *braze;
```

5. Add the following code in your `AppDelegate.m` file just after the RudderStack iOS (Obj-C) SDK initialization snippet:

```objectivec
id<RSIntegrationFactory> brazeFactoryInstance = [RudderBrazeFactory instance];
// RudderStack SDK initialization
[[RSClient getInstance] onIntegrationReady:brazeFactoryInstance withCallback:^(NSObject *brazeInstance) {
    if (brazeInstance && [brazeInstance isKindOfClass:[Braze class]]) {
        braze = (Braze *)brazeInstance;
        [self configureIAM];
    } else {
        NSLog(@"Error getting Braze instance.");
    }
}];
```

The corresponding Swift snippet is as follows:

```swift
let brazeFactoryInstance = RudderBrazeFactory()
// RudderStack SDK initialization
RSClient.getInstance().onIntegrationReady(brazeFactoryInstance) { brazeInstance in
    if let brazeInstance = brazeInstance as? Braze {
        AppDelegate.braze = brazeInstance
        self.configureIAM()
    } else {
        print("Error getting Braze instance.")
    }
}
```

6. Add the `configureIAM` method in the `AppDelegate.m` file:

```objectivec
-(void) configureIAM {
    // Refer here: https://www.braze.com/docs/developer_guide/platform_integration_guides/swift/in-app_messaging/customization/setting_delegates/#setting-the-in-app-message-delegate
    BrazeInAppMessageUI *inAppMessageUI = [[BrazeInAppMessageUI alloc] init];
    braze.inAppMessagePresenter = inAppMessageUI;
}
```

The corresponding Swift snippet is as follows:

```swift
func configureIAM() {
    // Refer here: https://www.braze.com/docs/developer_guide/platform_integration_guides/swift/in-app_messaging/customization/setting_delegates/#setting-the-in-app-message-delegate
    let inAppMessageUI: BrazeInAppMessageUI = BrazeInAppMessageUI()
    AppDelegate.braze?.inAppMessagePresenter = inAppMessageUI
}
```
{{% /tab %}}
{{< /tabs >}}
