# Inline in-app messages

## How it works[](#how-it-works)

An inline message targets a specific widget in your app. You create a placeholder `InlineInAppMessageView` in your UI, and the SDK fills it with the content of your message.

Inline messages let you show dynamic content without releasing a new version of your app. Unlike push notifications, banners, or modal in-app messages, an inline message looks and feels like part of your interface.

## 1\. Add View to your app UI to support inline messages[](#1-add-view-to-your-app-ui-to-support-inline-messages)

Add `InlineInAppMessageView` anywhere you want to display inline messages. The widget expands or contracts automatically when a message loads or when people interact with it.

 See [our sample apps](https://github.com/customerio/customerio-flutter/tree/main/apps) for real-world implementations.

```dart
import 'package:customer_io/customer_io.dart';
import 'package:customer_io/customer_io_widgets.dart';

class InlineExample extends StatelessWidget {
  const InlineExample({super.key});

  @override
  Widget build(BuildContext context) {
    return InlineInAppMessageView(
      elementId: 'inline', // Use this ID in Customer.io when you build your message.
      onActionClick: (
        InAppMessage message,
        String actionValue,
        String actionName,
      ) {
        // Handle button taps or other actions.
        debugPrint(
          'Inline message action clicked: $actionName with value: $actionValue',
        );
      },
    );
  }
}
```

### View layout[](#view-layout)

*   Avoid hard-coding a height. The widget manages its own height as messages load and change.
*   You control layout—padding, margins, alignment—just like any other widget.

## 2\. Build and send your message[](#2-build-and-send-your-message)

When you add an in-app message to a broadcast or campaign in Customer.io:

1.  Set **Display** to **Inline**.
2.  Enter the **Element ID** that matches the `elementId` you set in your widget.
3.  (Optional) If you send multiple messages to the same Element ID, set a **Priority** so we know which message to show first.

Then design and send your message!

[![Inline display settings in the in-app message editor](https://docs.customer.io/images/in-app-inline.png)](#74810b23329cd479a11edfdda9f818e0-lightbox)

## Handling custom actions[](#handling-custom-actions)

When you configure an in-app message, you decide what happens when someone taps a button or the message itself. For deep links, the SDK opens the link automatically. For other interactions—like showing a settings page—you can listen for action events and run your own code.

### 1\. Compose a message with a custom action[](#1-compose-a-message-with-a-custom-action)

In Customer.io, add an action to your in-app message, choose **Custom Action**, and set the action *Name* and *Value*. The *Name* maps to `actionName`; the *Value* maps to `actionValue` in your callback.

[![Set up a custom in-app action](https://docs.customer.io/images/in-app-custom-action.png)](#1005ee0b179f3999e81398a57e369557-lightbox)

### 2\. Listen for events[](#2-listen-for-events)

You have two ways to detect clicks in inline messages.

1.  **Callback on the widget** – Pass `onActionClick` (shown above) to handle actions for that specific inline view.
2.  **Global listener** – Subscribe to `CustomerIO.inAppMessaging.subscribeToEventsListener` to handle inline **and** modal message events in one place.

```dart
final subscription = CustomerIO.inAppMessaging.subscribeToEventsListener(
  (InAppEvent event) {
    if (event.eventType == EventType.messageActionTaken) {
      // Perform your logic here.
      debugPrint('Action taken: ${event.actionName} / ${event.actionValue}');
    }
  },
);

// Later, when you no longer need events
subscription.cancel();
```

## Handle responses to messages (event listeners)[](#event-listeners)

Just like modal messages, inline messages emit events you can react to:

*   `messageShown` – The message appeared.
*   `errorWithMessage` – We encountered an error rendering the message.
*   `messageActionTaken` – Someone tapped an action. This only triggers if the inline view does **not** have an `onActionClick` callback.

Inline messages have no *dismiss* concept, so there is no `messageDismissed` event.