# In-app messages


An in-app message is a card the SDK draws over your own UI during a session — an
onboarding nudge, a promotion, a prompt to rate. No notification permission is
involved, and nothing in the path touches APNs or FCM.

The mechanism is a device-side read of an ordinary OpenPush route. Each
subscription asks for its own eligible set (`GET /v1/apps/{app}/subscriptions/{subscription}/iams`,
capped at 25 definitions), caches it, and from then on the SDK decides locally
which card qualifies and when to draw it. That read runs on a cold start, and
again when a session resumes after the app has been backgrounded for 30 seconds
or more. So setting a definition live makes it *fetchable*: a device picks it up
on its next qualifying session, not at the moment you publish.

## Create a message

Open **Messages → In-App → Compose message**. Choose:

1. an all-users or segment audience;
2. a placement: top, center, bottom, full screen, or carousel;
3. block content (text, images, and up to three buttons per card) or guarded
   custom HTML;
4. optional app/session triggers and a dismissal rule; and
5. start, stop, and redisplay limits.

Use **Review before going live** to confirm the current audience estimate and
saved device surface. Going live changes the definition's status and nothing
else — no send is queued and no provider is contacted.

## Triggers

Trigger groups are OR-of-ANDs. Every row within a group must match; any group may
qualify. The SDK supports custom string/number/boolean values, session duration,
and time since the previous in-app dismissal.

```swift
OpenPush.InAppMessages.addTrigger("level", withValue: 12)
OpenPush.InAppMessages.addTriggers(["plan": "pro", "onboarded": true])
```

```kotlin
OpenPush.InAppMessages.addTrigger("level", 12)
OpenPush.InAppMessages.addTriggers(mapOf("plan" to "pro", "onboarded" to true))
```

```csharp
OpenPush.InAppMessages.AddTrigger("level", 12);
```

Removing or changing a trigger re-evaluates the waiting queue. Set `paused` /
`Paused` when the host needs to temporarily suppress presentation.

## Actions and state

Buttons and clickable images can open a URL, request notification permission,
update a user tag, record a custom outcome/event, or emit a custom action id.
Location permission remains host-owned and is reported as unsupported rather
than silently requested.

The SDK persists dismissals, de-duplicated click ids, last-dismissal time, and
redisplay counters. A device therefore honors once/frequency rules across app
restarts.

## Reports and lifecycle

Active definitions can be paused, resumed, ended, or duplicated. Reports show
impressions, unique clickers, total clicks, CTR, daily activity, block-level
interaction, and device activity. Use **Export CSV** for the complete activity
set.

See [In-app messages API](../api-handbook/10-in-app-messages.md) for management,
device fetch, compiled HTML, and receipt routes.
