Skip to main content
In-app messages reach contacts while they are using your product. A sequence step decides who sees what and when; your app fetches the contact’s in-app feed and draws each item with its own components, so it always matches your design. In-app is included in every plan and does not use email credits. Nothing is sent by email or push: if your app does not fetch the feed, contacts never see the items.

How it works

  1. Add a Show In-App step to a sequence. Each contact who reaches it gets one item in their in-app feed, with merge tags like {{FIRST_NAME|there}} already filled in.
  2. Your app fetches the signed-in contact’s feed, either from the browser or from your backend.
  3. Your app shows the items and reports displayed, clicked, dismissed and read back. Those reports power the step’s stats and decide what stays in the feed.

Set it up with an AI coding tool

In Settings → In-app, choose Copy prompt for a web app, or for a mobile or server-rendered app. The prompt has your workspace’s values filled in and explains how to fetch the feed, render each format and report events. Paste it into Cursor, Claude Code or Codex, or send it to your developer.

Add an in-app step

In the sequence builder, add Show In-App under Messages. Choose:
  • Message or Content card.
  • For messages, the format: modal, banner or full screen. Banners go at the top or bottom.
  • A title and message (at least one), and an optional https image.
  • Up to two buttons. A button either opens a link (an https URL or an app deep link such as myapp://billing) or closes the item.
  • Optional extra data: string key/values your app receives with the item, for example screen: billing. Merge tags work in values.
  • An optional expiry in days (1 to 365), and for cards, Pin to the top.
On the Design tab, pick a style: Brand (white with your brand buttons), Soft (tinted, pill buttons), Bold (your brand color as the background) or Dark. Presets use the brand color and button style from your Email design settings. You can then change the background, text and button colors, the corner radius and the button corners. Every item in the feed carries the resolved values in style (backgroundColor, textColor, mutedTextColor, buttonColor, buttonTextColor, cornerRadius, buttonRadius, fontFamily), so your app can draw it in your brand without hard-coding colors. The preview shows the result on a phone and on the web. Through the API, set style on the step, for example { "preset": "bold", "cornerRadius": 8 }. When you update a step, the style you send merges into its current style: set a value to null to go back to the preset’s value, or send "style": null to reset everything. If you override a background color but not the text color on it, the text switches to black or white when the preset’s color would be hard to read. A step never stops the journey: if the content is empty after merge tags are filled in, the step is skipped and the contact moves on. Each contact gets at most one item per step, even if the step is processed again. You can also add in-app steps through the API with type: "in_app" on Create Sequence or Update Sequence steps, with sequenzy sequences create --steps-json in the CLI, or with the insert_sequence_step MCP tool.

Fetch from the browser

Browser apps can call Sequenzy directly with your publishable site key (Settings → Integrations → Web tracking) and an identity token that your backend mints for the signed-in user. The token proves which contact the browser speaks for, so one user can never read another user’s feed.
  1. After sign-in, your backend calls POST /api/v1/web-tracking-identities with a secret API key (scopes commerce:write, automations:trigger and subscribers:write) and { "publicKey": "seq_pk_...", "email": "<user email>" }, and returns identityToken to the browser. If you already call sequenzy.identify, reuse that token.
  2. The browser fetches the feed:
kind (message or card) and limit (1 to 100) are optional. The response is { "success": true, "messages": [...] }, with items in the List In-App Messages shape.
  1. The browser reports events:
Send both as text/plain so browsers skip the CORS preflight. Requests come from allowed origins only when the site key has an origin allowlist; mobile apps that call these endpoints directly need a key without one, or should use the backend endpoints below. Both endpoints are rate limited per IP address. A valid identity for a contact that no longer exists returns an empty feed.

Fetch from your backend

For iOS, Android, React Native and server-rendered apps, fetch through your own backend with a secret API key:
  • List In-App Messages with the contact’s email or externalId (subscribers:read scope).
  • Record In-App Event for each report (subscribers:write scope). Forward only IDs that came from that user’s own feed.

Reporting events

Only the first report of each type sets its timestamp, so retrying displayed, dismissed and read is safe. Every clicked report adds to the click count, so send it once per click. Each event also appears in the contact’s activity as in_app.displayed, in_app.clicked, in_app.dismissed or in_app.read, next to in_app.created when the step ran and in_app.skipped when it was skipped.

Results

With stats turned on in the sequence flow, each in-app step shows how many contacts got the item, the share that saw it and the share that clicked. The same counts are available from Get In-App Step Stats, sequenzy in-app stats <stepId> and the get_in_app_step_stats MCP tool. A contact’s page lists their in-app items with what happened to each, and lets you remove an item that is still waiting. Deleting a contact deletes their in-app items.

CLI and MCP