> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zixflow.com/llms.txt
> Use this file to discover all available pages before exploring further.

# In-App Messaging

> Display and handle in-app messages with the Zixflow iOS SDK.

In-app messages appear while users are active in your app. The iOS SDK displays them automatically when you enable the in-app module and identify the user.

### Enable in-app messaging

1. Install the `ZixflowMessagingInApp` pod or the `MessagingInApp` SPM product (see [Installation](/documentation/sdk/ios/installation)).
2. Initialize the module **after** core SDK init:

```swift theme={null}
import ZixflowDataPipelines
import ZixflowMessagingInApp

let config = SDKConfigBuilder(apiKey: "YOUR_API_KEY").build()
Zixflow.initialize(withConfig: config)

MessagingInApp.initialize(
    withConfig: MessagingInAppConfigBuilder().build()
)
```

> **Note:** `MessagingInAppConfigBuilder` currently has no additional customer-facing options. Call `.build()` after creating the builder.

### Identify users

Identify a user before personalized in-app messages can be delivered:

```swift theme={null}
Zixflow.shared.identify(
    userId: "user-123",
    traits: [
        "email": "user@example.com"
    ]
)
```

### How messages appear

1. Create and launch an in-app campaign in the Zixflow dashboard.
2. When campaign conditions match, the SDK fetches and displays the message.
3. No extra UI code is required for standard modal messages—the SDK renders them.

Track screen views if your campaigns target specific screens:

```swift theme={null}
Zixflow.shared.screen(title: "Home")
```

You can also enable `.autoTrackUIKitScreenViews()` or use `.screenViewUse(screenView: .inApp)` so screen events drive in-app page rules (see [Advanced Configuration](/documentation/sdk/ios/advanced-configuration)).

### Listen for in-app events

Conform to `InAppEventListener` and register it on the shared instance:

```swift theme={null}
import ZixflowMessagingInApp

class AppDelegate: UIResponder, UIApplicationDelegate, InAppEventListener {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        // ... Zixflow.initialize ...

        MessagingInApp
            .initialize(withConfig: MessagingInAppConfigBuilder().build())
            .setEventListener(self)

        return true
    }

    func messageShown(message: InAppMessage) {
        print("Shown \(message.messageId)")
    }

    func messageDismissed(message: InAppMessage) {
        print("Dismissed \(message.messageId)")
    }

    func errorWithMessage(message: InAppMessage) {
        print("Error \(message.messageId)")
    }

    func messageActionTaken(
        message: InAppMessage,
        actionValue: String,
        actionName: String
    ) {
        print("Action \(actionName) \(actionValue)")
    }
}
```

| Callback             | When it fires              |
| -------------------- | -------------------------- |
| `messageShown`       | Message is displayed       |
| `messageDismissed`   | Message is closed          |
| `messageActionTaken` | User taps a message action |
| `errorWithMessage`   | Message fails to display   |

### Dismiss a message

```swift theme={null}
MessagingInApp.shared.dismissMessage()
```

### Inline in-app messages

Use an inline view whose `elementId` matches the placement ID in your campaign.

#### SwiftUI

```swift theme={null}
import SwiftUI
import ZixflowMessagingInApp

struct PromoBanner: View {
    var body: some View {
        InlineMessage(elementId: "home-banner") { message, actionValue, actionName in
            print("Inline action: \(actionName) \(actionValue)")
        }
    }
}
```

#### UIKit

```swift theme={null}
import ZixflowMessagingInApp

let banner = InlineMessageUIView(elementId: "home-banner")
view.addSubview(banner)
// Add your own Auto Layout constraints (the view manages its height)
```

### Notification inbox

Access persistent inbox messages via `MessagingInApp.shared.inbox`:

```swift theme={null}
import ZixflowMessagingInApp

let inbox = MessagingInApp.shared.inbox

// One-shot fetch
Task {
    let messages = await inbox.getMessages()
    // Optionally: await inbox.getMessages(topic: "promotions")
}

// Live updates (AsyncStream)
Task {
    for await messages in inbox.messages() {
        // Rebuild your inbox UI
    }
}

// Mark read / unread / delete / track clicks
inbox.markMessageOpened(message: message)
inbox.markMessageUnopened(message: message)
inbox.markMessageDeleted(message: message)
inbox.trackMessageClicked(message: message, actionName: "cta")
```

You can also use `addChangeListener` / `removeChangeListener` on the main actor if you prefer a listener-based API.

For the full method list, see the [API Reference](/documentation/sdk/ios/api-reference).

***
