Documentation

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.

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.1

react-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

CapabilityExpo / RNiOSAndroid
goNext, goBack, goToStep, setAnswer, flushCapture, reloadYesYesYes
Typed events and discount callbacksYesYesYes
Native hapticsYesYesYes
First-paint loading, custom loading and error viewsYesYesYes
Capture flushing on app lifecycle changesYesYesYes
Deep links and external links handed to your appYesYesYes
Local test configs and custom capture transportsYesYesYes
Hardware Back handledYesn/aYes

Verify

  1. Run the app and open the screen that hosts the Journey. The first screen renders inside your native view.
  2. Answer a screen and continue. The native back gesture or button walks you back one screen, not out of the flow.
  3. 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.

AI agent or LLM? Read this page as markdown

On this page