Mobile (RN / iOS / Android)
Embed FounderHQ Journeys in mobile apps.
Render a published Journey inside your Expo, React Native, iOS, or Android app, with the same screens your web embed shows.
Before you start
You need a published Journey in FounderHQ, its Journey ID, and a
publishable key (fhq_pk_XXXX). See Journeys for how
keys work, and Embed on the web for the
props the native SDKs mirror.
How the native SDKs work
Every platform SDK hosts the same Journey renderer and wraps it in a native view. Config fetching and event capture stay in the platform's own networking layer. Your app never puts a FounderHQ key in a URL.
Because the renderer is shared, a screen you publish once looks and behaves the same on web and on device. Haptics run natively, not inside the web view. Links are handed to your app to route.
Every SDK connects to https://app.getfounderhq.com by default and calls
/api/v1/journeys/{journeyId} for preparation, the published config,
capture, and completion. Set baseUrl (baseURL on iOS) only to point at
a local FounderHQ while you develop. The native SDKs accept any HTTPS
origin there and reject plain http:// unless the host is local, so a bad
value fails loudly instead of leaking responses.
Native apps send no Origin header, so a key's allowed-origin list does
not gate them. It is still required when you create the key.
Prepare before presenting
For an immediate opening, prepare the first screen while your app is visible, then present it when the user chooses to continue. Preparation does not count as a Journey view or start animations, media, or haptics. Each host retains one web view and checks for updates while foregrounded.
- Expo and React Native preparation —
@founderhq/journeys-react-native0.7.0 and later. - SwiftUI and UIKit preparation —
FounderHQJourneys0.7.0 and later. - Android View and Compose preparation — Journeys 0.7.0 and later.
The direct JourneyView integrations below remain supported. For custom
clients, see the preparation API
and Limits and reliability.
Expo and React Native
npx expo install react-native-webview react-native-safe-area-context expo-haptics
npm install @founderhq/journeys-react-native@^0.8.1react-native-webview ships with Expo Go, so this SDK needs no custom
native module.
import {
JourneyView,
type JourneyViewRef,
} from "@founderhq/journeys-react-native/expo";
import { useRef } from "react";
export function OnboardingJourney() {
const journey = useRef<JourneyViewRef>(null);
return (
<JourneyView
ref={journey}
apiKey={process.env.EXPO_PUBLIC_FOUNDERHQ_KEY!}
journeyId="journey_123"
identity={{ externalId: "usr_1042" }}
onEvent={(event) => {
if (event.type === "complete") {
// Continue into the app.
}
}}
onOpenURL={(url) => {
// Route through Expo Router or Linking.
}}
style={{ flex: 1 }}
/>
);
}Bare React Native imports JourneyView from the package root instead of
/expo.
Haptics differ by entry point. The Expo entry point maps every Journey
haptic to expo-haptics. The bare entry point uses React Native's
Vibration module, and you can pass haptics={(type) => ...} to route it
to your own haptics library without changing the Journey.
iOS
FounderHQJourneys is a Swift Package for SwiftUI and UIKit. It supports
iOS 15 and later.
import FounderHQJourneys
struct OnboardingView: View {
private let controller = JourneyController()
var body: some View {
JourneyView(
configuration: JourneyConfiguration(
apiKey: "fhq_pk_XXXX",
journeyID: "journey_123",
identity: JourneyIdentity(externalID: "usr_1042")
),
controller: controller,
onEvent: { event in
if event.type == .complete {
// Continue into the app.
}
}
)
}
}UIKit apps present JourneyViewController instead. JourneyController
publishes canGoBack, currentStepID, and currentStepIndex. Both entry
points accept your own loading and error views.
In Xcode, add https://github.com/FounderHQ/founderhq-journeys-ios using
Swift Package Manager, version 0.8.0 or later.
CocoaPods consumers can use:
pod 'FounderHQJourneys', '~> 0.8.0'Or install directly from the Git release:
pod 'FounderHQJourneys', :git => 'https://github.com/FounderHQ/founderhq-journeys-ios.git', :tag => 'v0.8.0'Android
The Android SDK is a core View artifact plus an optional Jetpack Compose adapter. It supports Android API 24 and later.
val journey = JourneyView(context)
journey.load(
JourneyConfiguration(
apiKey = "fhq_pk_XXXX",
journeyId = "journey_123",
identity = JourneyIdentity(externalId = "usr_1042"),
),
object : JourneyListener {
override fun onEvent(event: JourneyEvent) {
if (event.type == JourneyEventType.COMPLETE) {
// Continue into the native app.
}
}
},
)Compose apps use com.founderhq.journeys.compose.JourneyView and configure
the underlying View with configureView. The core View exposes
loadingViewFactory, errorViewFactory, hapticHandler,
handleBackPressed(), and the current navigation state.
Add mavenCentral() to your repositories and install:
implementation("com.getfounderhq:journeys:0.8.1")
// Optional Jetpack Compose integration:
implementation("com.getfounderhq:journeys-compose:0.8.1")What every platform gives you
| Capability | Expo / RN | iOS | Android |
|---|---|---|---|
goNext, goBack, goToStep, setAnswer, flushCapture, reload | Yes | Yes | Yes |
| Typed events and discount callbacks | Yes | Yes | Yes |
| Native haptics | Yes | Yes | Yes |
| First-paint loading, custom loading and error views | Yes | Yes | Yes |
| Capture flushing on app lifecycle changes | Yes | Yes | Yes |
| Deep links and external links handed to your app | Yes | Yes | Yes |
| Local test configs and custom capture transports | Yes | Yes | Yes |
| Hardware Back handled | Yes | n/a | Yes |
Verify
- Run the app and open the screen that hosts the Journey. The first screen renders inside your native view.
- Answer a screen and continue. The native back gesture or button walks you back one screen, not out of the flow.
- Finish the flow, then open the Journey in FounderHQ. The response is
listed with the contact you passed in
identity.
A note on @founderhq/journeys-bridge
@founderhq/journeys-bridge holds the message types the renderer and the
native hosts speak. Install a platform SDK instead. You only need the
bridge package if you are building a host of your own.