In-app messages

Modals, slide-ups, and full-screen messages rendered inside your app. The right channel for product announcements, paywalls, onboarding nudges, "you just unlocked X" moments — anywhere a push would be overkill but a banner isn't enough.

  1. 1 · Build
    Content & questions
  2. 2 · Design
    Theme & layout
  3. 3 · Target
    Audience · trigger · schedule · caps
  4. 4 · Analyze
    Performance & responses

Stage 1 — Build

Format

A 3-card picker. Pick one:

ValueDashboard labelHint
modalModal"Centered popup with dimmed background."
modal_fullFull-screen"Fills the device screen — for major announcements."
slideupSlide-up"Bottom sheet — same look as feedback prompts."

Content

FieldNotes
TitleRequired. Placeholder What's new in 2.4.
BodyRequired, multi-line.
Image (optional)Image uploader.
ActionsUp to 2 CTA rows (see below).
Auto-dismiss (slide-up only)Numeric input 1–120 seconds. Shown only when format is slideup. Leave blank to keep open until tapped.

CTA editor — the 4 action types

Each CTA is a label + an action. Action picks one of:

ActionDashboard labelHintTarget field
open_urlOpen URL"Opens a URL in an in-app browser."Yes — URL string. Placeholder https://example.com/promo.
deep_linkDeep link"Routes to a specific screen in your app."Yes — your scheme. Placeholder usergist://feature/whats-new.
dismissDismiss"Closes the message — no further action."None.
custom_eventCustom event"Fires a named event your app handles."Yes — event name. Placeholder feature_x_announce_clicked.

The first CTA defaults to { label: 'Got it', action: 'dismiss' }.

In-app message composer — Build stage.
Build stage: format picker, title, body, image, CTAs, slide-up auto-dismiss.

Stage 2 — Design

Theme gallery + custom token overrides. Same tokens as Feedback.

Per-message tints (override the workspace theme just for this one):

  • backgroundColor — card background.
  • accentColor — active button + scale fill.

The phone preview reflects the current format, copy, image, and theme.

Stage 3 — Target

Choose Audience, then Platforms, then Trigger. The platform section shows only the app's configured delivery platforms. React Native, Expo and Flutter offer iOS and Android; choose both for both app versions. Web covers mobile and desktop browsers and appears when enabled in app settings. See platform targeting.

Audience

Same 8 condition kinds as every other channel — see Segments.

Trigger

In-app uses the shared composer trigger builder, 3 kinds:

KindDashboard labelHint
app_openOn app open"Fire when the user opens the app."
eventWhen a user performs an event"Fire when the SDK records a specific event (with optional property filters)."
app_version_changedWhen the user updates the app"Fires on the first cold-start after the app version changes — perfect for "What's new"."

The event kind exposes event name + property filters + occurrence (Every time / First occurrence / After Nth occurrence). All three kinds share Delay (in minutes), Once only (checkbox), and Active window (date range toggle).

audience_join is push-only and not shown here.

Screen context

Two chip lists let you scope where the message can appear, by the screen name your app reports via UserGist.setCurrentScreen(...):

ListDashboard labelBehaviour
AllowlistShow only onEmpty = anywhere. Populated = only these screens.
DenylistNever onAlways wins over the allowlist. Use for Checkout, SignUp, etc.

Both are free-text chip inputs — press Enter to add, Backspace to remove the last.

Frequency caps

All 6 caps are exposed in the editor. Three are cooldown-by-outcome (the differentiator) and three are cross-pillar caps.

SectionUI labelField
Cooldown by outcomeCooldown if shown (days)cooldownAfterShownDays
Cooldown by outcomeCooldown if dismissed (days)cooldownAfterDismissedDays
Cooldown by outcomeCooldown if CTA clicked (days)cooldownAfterCtaClickedDays
Cross-pillarMax impressions per usermaxImpressionsPerUser (1–100)
Cross-pillarPer-pillar cap (days)perPillarDays (0–365) — across all in-app messages
Cross-pillarGlobal cap (days)perGlobalDays (0–365) — across every channel
Sensible defaults

For a paywall: cooldownAfterDismissedDays = 7, cooldownAfterCtaClickedDays = 30, maxImpressionsPerUser = 5. For a release-note takeover: maxImpressionsPerUser = 1.

Stage 4 — Analyze

  • Impressions — how many users saw it.
  • CTA click-through rate per button.
  • Dismiss ratedismissals / impressions.
  • Slide-up specific — auto-dismiss vs user-dismiss split.
  • Daily time series of impressions + clicks.
In-app message Analyze view.
Analyze stage: impressions, CTR per CTA, dismiss rate.

Status lifecycle

StatusMeaning
draft · active · paused · completed · archivedSame lifecycle as surveys.

SDK side

// Tell the SDK what screen the user is on, so screen context works
UserGist.setCurrentScreen('Home')
 
// Handle a custom_event action from a CTA
UserGist.setSurveyHandlers({
  onAction: ({ messageId, actionId }) => {
    if (actionId === 'open_pro_paywall') openPaywall()
  },
})

API

  • GET /v1/apps/:appId/inapp-messages — list
  • POST /v1/apps/:appId/inapp-messages — create
  • PATCH /v1/apps/:appId/inapp-messages/:id — update
  • DELETE /v1/apps/:appId/inapp-messages/:id — permanently delete

Canonical schemas: apps/api/src/schemas/inapp-messages.ts.

Personalized content and actions

Use Insert field in supported message fields and button labels, destinations or JSON action values. The action editor groups Button label and Behavior, then the destination or Action data. Use one activity source for related movie title/ID/position fields and handle the resolved action in your app. Personalize messages covers user properties, latest activity, triggering events, fallbacks and Preview as user.

With the immediate-delivery API and SDK release, web plus mobile campaigns can return authorized content with event ingestion. Server eligibility and network latency still apply; eligible ordinary native campaigns keep cached matching.

What's next

Messages on websites

In-app messages also render in desktop and mobile browsers through the Web SDK. Include Web in Target, activate the intended user and grant feedback consent; analytics consent is needed to track trigger events. Set page context explicitly for screen allow/deny rules.

In Design, Web presentation sits beneath the theme and app backdrop settings. It controls the browser layout, size, side and backdrop. Desktop and mobile web previews share saved content and brand settings; desktop can be enlarged. These messages do not use browser push or notification permissions.