Braze, Iterable, and Customer.io each sell the in-app feed as a product line of its own — Orbit ships the same owned channel inside Messages, one master toggle and two authoring primitives, with no carrier leg and no per-message cost. This post is the operator guide: what the channel actually is, the decision matrix against push, email, and SMS, the authoring primitives under Messages → In-app, how it plugs into fallback chains, the governance and disable path, and how to measure it. The field-by-field reference lives in the in-app channel guide and the channel model; this post keeps the operator's arc.
What an owned in-app channel actually is
Every carrier channel pays a delivery leg: SMS exits through a gateway, WhatsApp exits through Meta, email exits through a provider. The in-app channel has no carrier leg at all, because delivery is a pull, not a push — your own web or React Native app fetches the visitor's eligible feed from the in-app feed endpoint and renders it with your own components. Engagement (impressions, clicks, dismissals) travels back in one lightweight events call, over traffic your app already pays for.
That is the whole trick, and it is worth being precise about: "zero carrier cost" does not mean "free messaging with the same reach." It means the channel renders inside a surface you already operate — your website or app — and only for visitors running your SDK. Eligibility is computed at fetch time, not send time, so there is no per-send cost, no sender registration, and no external throughput ceiling. The Messages → In-app dashboard page frames this exactly: the feed your web and React Native SDKs render, with Braze / Iterable / Customer.io parity — parity on the owned reaction-engage lane those vendors charge a separate line for, shipped here beside SMS, WhatsApp, and email on one bill.
Two SDK surfaces render the same wire model, so a card you author once looks identical in both: the web SDK renders content cards into a container you own and shows the highest-priority in-app message as an overlay; the React Native SDK hands your components the same feed and event model. Both keep a sticky anonymous id per device and a per-device dismissed list, so a dismissed card never flashes back on the next fetch.
The decision matrix: push vs email vs in-app vs SMS
In-app wins when the visitor is already inside your product and the message benefits from placement rather than interruption:
| In-app | Push | SMS | ||
|---|---|---|---|---|
| Consent gate | None beyond the app session | OS-level opt-in, revocable silently | Address + opt-out duty | Phone number + opt-in, opt-out duty |
| Creative | Richest — cards, images, buttons, HTML | Title + body + tap target | Full HTML, inbox competition | ~160 chars, links |
| Cost per message | Zero carrier leg | Zero carrier leg | Provider leg | Carrier leg |
| Ordering | Deterministic — priority + pinned | OS-controlled | Inbox-sorted | FIFO carrier |
| Reach | Active app sessions only | Requires installed app + opt-in | Anyone with an address | Anyone with a number |
When in-app wins: no consent window to clear, the richest creative surface of the four, no carrier cost, and deterministic ordering — a pinned card floats to the top of the feed and a numeric priority decides which overlay message wins when several are eligible. When it does not: in-app has no opt-in reach outside your own surfaces. A visitor who never opens your app never sees the feed, and there is nothing to notify them with. That trade-off is why the channel is a complement to push, SMS, and email, not a replacement — and why the fallback section below matters.
Authoring primitives under Messages → In-app
The dashboard page (Messages → In-app) ships two render classes, both travelling over the same feed:
Content cards — persistent. A card lives in the visitor's feed until it expires or is dismissed. Three families: classic (title-led, with optional description, image, and tap link), banner (image-only, the whole card is the tap target), and captioned_image (image plus title). Pinned floats a card to the top of the feed; Dismissible controls whether the visitor can remove it. Cards are the inbox-that-never-pushes surface — a promotion, an announcement, an order status that should stay visible across sessions.
In-app messages — transient. A message renders once as a modal, slideup, fullscreen, or html overlay, then leaves the feed. The editor carries a header, body (or raw HTML for the html type), an image, and a numeric priority that decides which message renders when several are eligible — one at a time. Messages are the interrupt-politely surface: a welcome-back nudge, a VIP preview, a one-time announcement.
Both classes accept segment labels (comma-separated) so a surface only renders for the audiences you tag, and both carry an expiry after which the surface drops out of the feed server-side — a time-boxed campaign never needs a cleanup job. The authored set is capped at 100 cards and 100 messages per tenant: a real feed, not a firehose. Saves are validated in the editor before they are accepted (duplicate ids, malformed image URLs, missing bodies all block the save), and the same configuration is writable over the API for teams who manage Messages from CI.
How the channel plugs into fallback chains
In-app is a pull channel, so it never sits inside an org-level fallback chain — fallback advances are triggered by carrier-side reachability failures, and the in-app feed has no carrier leg to fail on. The correct wiring is the reverse: author in-app first, then let the carrier channels catch whoever never pulled.
The pattern that works in practice: publish the card or message with an expiry that matches the campaign window, then send the same content as an email or SMS to the segment that has not engaged by the halfway point. In-app carries the zero-cost, richest-creative impression for every active visitor; the carrier hop carries reach for everyone else. When you do escalate to a carrier channel, the org-level fallback chain (RCS → SMS, Viber → WhatsApp → SMS, and the like) governs the hops between carrier channels — configuring it once on the organization makes every outbound send path inherit it, and each hop re-runs the opt-out check for the channel it lands on. Keep in-app out of that chain by design; it is the head of the sequence, not a hop.
Governance and the disable path
The channel's kill switch is the master toggle on Messages → In-app: Enable in-app channel. Toggle it off and the SDK feed returns empty even while authored content remains in place — the page itself describes the semantics as a paused campaign set. That distinction is what makes the toggle safe to use: authoring and enablement are separate states, so you can prepare a campaign dark, flip it on at the window, and flip it off after — no deletion, no redeploy, and a re-enable restores exactly what was authored.
Governance beyond the toggle is deliberately thin because the blast radius is small: the channel only renders inside your own surfaces, to visitors already in your app. There is no sender registration to lose, no carrier quality rating to burn, and no quiet-hours regime that applies to a pull the visitor initiates. The discipline that remains is editorial: caps keep the feed finite, expiry keeps campaigns time-boxed, and segment labels keep promotions scoped to the audiences they were priced for. Write access to the surface is role-gated (owner, admin, developer) the same as the rest of the Messages hub.
Measurement: views, click-throughs, conversions
Because there are no carrier receipts, engagement is the delivery signal. The SDK reports impressions, clicks, and dismissals back as events, and those events land in the same delivery-log and analytics surfaces as every other channel — the Messages → Delivery log view for the per-event record, and the analytics export when you need the numbers in your own BI. Read the channel on three ratios: views per eligible fetch (is the feed actually being pulled), click-through per view (are cards earning taps — banner cards and the tap link carry this), and conversions per click (the tap-through landed; did the visitor complete the action the card promoted). A card with healthy views and no clicks is a creative problem; a campaign with no views is a distribution problem — the SDK is not installed widely enough, or the master toggle is off.
Frequently asked questions
How is in-app different from push? Push interrupts from outside the app and needs an OS-level opt-in the user can revoke silently; in-app renders inside the app session with no consent gate and deterministic ordering. Use push to bring visitors back; use in-app to talk to them once they arrive.
How is in-app different from SMS? SMS reaches anyone with a phone number and pays a carrier leg per message; in-app reaches active app sessions at zero carrier cost with far richer creative. They are complements — in-app for depth, SMS for reach — not substitutes.
What happens when a subscriber opts out — does in-app respect that? Opt-out registries govern carrier channels (SMS, WhatsApp, email). In-app is a pull over your own surface, so the visitor's own dismissed list is the suppression mechanism: dismiss a card and it never renders again on that device. Turning the whole channel off for a visitor class is a segment-label decision you control at authoring time.
Do subscribers need your app installed? Yes — that is the channel's one hard constraint. The feed renders where your web or React Native SDK runs. For audiences without the app, route the same content through email or SMS and keep in-app as the zero-cost head of the sequence.
Is there an API, or is this dashboard-only? Both. The same authoring configuration the dashboard edits is readable and writable over the Messages in-app API, and the SDK feed/events endpoints are the wire your app talks to — the in-app channel guide has copy-pasteable requests for the full loop.
Put it in front of a segment today
Open Messages → In-app, author one classic card — a title, one line of description, a tap link to the page you are promoting — pin it, set an expiry a week out, and flip the master toggle on. Then run the carrier half of the sequence from Outbound → Direct Send: pick the same segment, choose the contact's reachable channel (SMS, WhatsApp, or email), and send the fallback copy to whoever has not clicked by mid-window. One feed, one fallback, and the two halves of an owned-first engagement program running inside an afternoon.