Notifications: push and in-app messages

The Appwin automation editor: an entry trigger, a push notification step and an exit, with the audience and end settings on the right.

Notifications sends the right message at the right time: campaigns, automated journeys, in-app messages. Four channels (mobile push, in-app, web push, mobile landing) share one audience and measurement engine.

The SDK registers tokens and events; you build campaigns and automations in the dashboard, under Notifications.

Installation

  1. 1

    Install Appwin Core and Notifications

    Notifications relies on Appwin Core. Not installed yet? Start with the Quickstart, which installs Core and your modules for every platform.

    Connect at least one push key: APNs for iOS, FCM for Android and the web. With no key, the API simulates sends: a campaign can look like it went out with nothing leaving. Check your keys before the first real send.

    Compatibility and packages per platform
    PlatformPackageSymbol
    iOS 16SPM product AppwinNotificationsAppwinNotifications
    Android 7.0 (API 24)io.appwin:appwin-notificationsio.appwin.notifications.AppwinNotifications
    Flutter 3.3appwin_notificationsAppwinNotifications.instance
    React Native 0.73@appwin/react-nativeAppwinNotifications
  2. 2

    Initialize Notifications

    initialize() asks the server for its verdict; start() takes over the rest: push registration, lifecycle events, realtime delivery and in-app presentation. One call, at launch.

    swift
    import AppwinNotifications
    
    AppwinCore.configure(projectAppId: "your-app-id")
    
    if await AppwinNotifications.initialize().isReady {
      // Asks for push permission and registers the APNs token.
      await AppwinNotifications.start()
    }
    

    isReady reads the last verdict without calling initialize() again. stop() undoes everything start() installed: it is for an app that turns campaigns off for part of its life (a kids mode, a paused account), not for a sign-out. A sign-out goes through AppwinCore.logout(), which drops the identity behind the targeting.

Available methods

Push permission and tokens

start() asks for push permission and registers the token. To choose when the prompt appears, or to forward the Firebase token yourself on Android, take over per platform.

To ask for permission later, at a moment where the user understands why, run start(requestPushPermission: false), then:

swift
let granted = try await AppwinNotifications.requestPushAuthorization()

Forward silent pushes so in-app messages arrive mid-session rather than at the next app open. Enable the Remote notifications background mode:

swift
func application(
  _ application: UIApplication,
  didReceiveRemoteNotification userInfo: [AnyHashable: Any]
) async -> UIBackgroundFetchResult {
  if await AppwinPush.handleMessage(userInfo) { return .newData }
  return .noData
}

handleMessage returns true when the push was Appwin's, false otherwise, so your own handling proceeds.

Trigger an automation

An automation starts from an event. After start(), the SDK already sends the lifecycle events; what is left to you is what only your app knows: a purchase, a level finished, an onboarding step.

EventWho sends it
app_open, app_background, session_start, push_opt_inThe SDK, after start()
purchaseYou, with the amount in the properties if the campaign segments on it
custom_eventYou, named through eventName
swift
try await AppwinNotifications.trackEvent(.purchase, properties: [
  "plan": "pro",
  "amount": "49.00",
])

try await AppwinNotifications.trackEvent(
  .customEvent,
  eventName: "onboarding_finished"
)

A journey's exit event is declared in the same place, and at the same time as the trigger: see Automations.

Render in-app messages yourself

By default the SDK draws the messages: presentPendingMessages() fetches what is waiting, presents it and reports what becomes of it on its own. syncOnAppOpen() does the same work on app open, chaining app_open then fetchPendingMessages().

swift
try await AppwinNotifications.presentPendingMessages()

A studio that wants its own screens takes the other route, and inherits the measurement with it, otherwise the campaign reports nothing:

swift
let messages = try await AppwinNotifications.fetchPendingMessages()

for message in messages {
  // Your own rendering.
  try await AppwinNotifications.track(deliveryId: message.deliveryId, event: .opened)
}

Three outcomes to report: opened (shown), clicked (a button or the body was tapped, with the button index) and dismissed (closed without acting). These are the funnel steps you will read in Analytics: without them, the campaign looks like it was never seen.

The channels

ChannelWhere it shows
Mobile pushSystem notification, app closed or in the background
In-appModal, banner or full screen, app open
Web pushBrowser, through FCM
Mobile landingA destination page rendered by the SDK

A campaign can combine several channels; it refuses to go out without content on at least one.

Campaigns

Notifications → Campaigns. A one-off send to an audience. Life cycle: Draft → Scheduled → Sending → Sent, with Paused and Archived as branches. A draft stays a draft as long as you want; scheduling requires a future date and cancelling stays possible until the send has started.

Tutorial: a first campaign

  1. Notifications → Campaigns → New campaign.
  2. Name it for your team, not for the user: "Summer promo - iOS push" is still findable in six months.
  3. Choose the channel, write the title and the message.
  4. Choose an audience, or set rules on the fly.
  5. Send now, or Schedule for a date.
  6. Come back to Analytics an hour later: sent, delivered, opened, clicked.

Make a first send to a narrow audience: a badly worded push cannot be taken back, and it costs uninstalls.

Audiences

Notifications → Audiences. Reusable segments, shared between campaigns and automations. An audience combines rules with AND / OR: platform (iOS, Android, web), language, plan, tags, devices registered on the project.

The number of matching users is estimated live while you build the rules: an audience that drops to zero is visible before the send, not after. A campaign can also carry its rules inline, with no named audience; worth naming as soon as the segment is used again.

Automations

Notifications → Automations. A journey triggered by behaviour, not by a date: onboarding, re-engagement, follow-up after abandonment.

SettingWhat it decides
TriggerThe event that brings a user into the journey
StepsThe messages, in order, with their delays
Exit rulesWhat interrupts the journey along the way
Re-entryOn every trigger, never, never while active, or after a delay

An automation combines push, email and in-app in a single journey: the message follows the user wherever they are reachable.

Exit rules are not optional

The trigger brings people in, the exit event takes them out. A "you have not finished signing up" follow-up that keeps going after they signed up is the best way to get your app uninstalled. Set the exit event at the same time as the trigger, not afterwards. The events come from the SDK, through trackEvent.

Templates

Notifications → Templates. Reusable models for in-app messages and mobile landings: modal, banner, full screen. A template carries the layout, the campaign carries the content; three campaigns that share a visual identity share a template.

Analytics

Notifications → Analytics. What the sends produced: an engagement funnel (sent → delivered → opened → clicked), a breakdown of volume by channel and by type (campaigns / automations), and per-message performance, message by message.

What to look at first:

GapWhat it says
Sent ≫ deliveredStale tokens, or the wrong push environment
Delivered ≫ openedThe title is not appealing, or the timing is wrong
Opened ≫ clickedThe message promises something other than what it opens

Settings

Notifications → Settings.

  • Push channels: the state of the APNs and FCM integrations, with a direct link to their configuration.
  • SDK: enabling the product on the project; without it, no device token is registered.
  • User preferences: maximum number of devices per user, behaviour beyond that, handling of devices with no opt-in.

Next