Skip to main content

React Native Integration

This guide covers how to integrate the Hubble SDK into a React Native application using react-native-webview.

1. Setup the WebView

Install the required dependency:

npm install react-native-webview
# or
yarn add react-native-webview

For iOS, run pod install after adding the dependency.

2. Initialization

Build the SDK URL with your credentials:

ParameterRequiredDescription
clientIdYesClient ID provided by the Hubble team
appSecretYesApp secret provided by the Hubble team
tokenConditionalSSO token for the current user. Required unless lazy login is enabled.
appVersionNoApp version string. Defaults to "10000".
deviceIdNoDevice identifier for analytics.

For React Native, set wrap-plt=rn.

const params = {
clientId: "id_given_by_hubble",
appSecret: "secret_given_by_hubble",
token: "your_sso_token",
"wrap-plt": "rn",
};

const baseUrl = "https://sdk.dev.myhubble.money/";
// prod: https://sdk.myhubble.money/

const sourceUrl = `${baseUrl}?clientId=${params.clientId}&appSecret=${params.appSecret}&token=${params.token}&wrap-plt=${params["wrap-plt"]}`;

3. Load the WebView

Render the WebView component with the required props:

<WebView
ref={webViewRef}
source={{ uri: sourceUrl }}
javaScriptEnabled={true}
domStorageEnabled={true}
startInLoadingState={true}
setSupportMultipleWindows={true}
javaScriptCanOpenWindowsAutomatically={true}
cacheEnabled={false}
onShouldStartLoadWithRequest={handleNavigation}
onMessage={handleEvent}
onNavigationStateChange={(navState) => setCanGoBack(navState.canGoBack)}
/>

4. Handling Navigation

This configuration is what enables your app to open the UPI app — without it, it will fail to do so.

Use onShouldStartLoadWithRequest to keep Hubble and payment gateway URLs in the WebView, while handing every other URL — UPI schemes (upi://, phonepe://, tez://), bank pages, external links — to the system:

import { Linking } from "react-native";

// Matches sdk.myhubble.money, sdk.dev.myhubble.money and any Razorpay host
const INTERNAL_URL = /^https:\/\/([a-z0-9-]+\.)*(myhubble\.money|razorpay\.com)(\/|$)/i;

const handleNavigation = (request) => {
if (INTERNAL_URL.test(request.url)) {
return true; // load inside the SDK webview
}
Linking.openURL(request.url).catch(() => {
// No app installed to handle this URL (e.g. a UPI app that is not installed)
});
return false; // everything else goes external
};
Razorpay Must Stay Inside the WebView

Match on the host, not just the base URL. This covers both the dev and production Hubble domains without an env switch, and — critically — allows Razorpay through. The earlier version of this snippet matched only baseUrl, which sent the payment gateway to the external browser and broke the flow: the user completes payment outside the WebView and the SDK never sees the result.

A regex is used here rather than new URL(), whose behaviour is unreliable under Hermes.

Back Navigation

Handle the hardware back button on Android:

useEffect(() => {
const backAction = () => {
if (canGoBack && webViewRef.current) {
webViewRef.current.goBack();
return true;
}
return false;
};
const handler = BackHandler.addEventListener("hardwareBackPress", backAction);
return () => handler.remove();
}, [canGoBack]);

5. Handling Events

The SDK communicates with your application by sending events. There are two types:

Action Events

SDK lifecycle and navigation:

ActionWhen It FiresWhat You Should Do
app_readySDK has finished loadingShow the WebView / iframe. Hide your loading spinner.
closeUser tapped the close or back button in the SDKDismiss the WebView / iframe. Navigate the user back.
errorSDK failed to load (invalid credentials, network error, SSO failure)Hide the WebView. Show a user-friendly error with a retry option.
Always Handle the close Event

The close action is the only way the SDK tells your application that the user wants to leave. If you do not handle it, the user will be stuck inside the SDK with no way to navigate back. This is one of the most common integration issues.

Analytics Events

User interaction tracking:

{ "type": "analytics", "event": "payment_success", "properties": { "amount": 500 } }

Forward analytics events to your analytics provider (Mixpanel, CleverTap, Amplitude, etc.) to track SDK usage.

For a complete list of events, see the Full Events Reference.

Setting Up the Event Handler

Use the onMessage prop to receive events:

const handleEvent = (event) => {
const data = JSON.parse(event.nativeEvent.data);

if (data.type === "action") {
if (data.action === "close") {
navigation.goBack();
} else if (data.action === "app_ready") {
setLoading(false);
} else if (data.action === "error") {
setError(true);
}
} else if (data.type === "analytics") {
// Forward to your analytics provider
analytics.track(data.event, data.properties);
}
};

6. Payment Configuration

The Hubble SDK supports UPI and credit/debit card payments. Credit/debit card payments are not enabled by default - contact Hubble support to enable them.

UPI on React Native

This configuration is what enables your app to open the UPI app — without it, it will fail to do so.

The navigation handling in Section 4 is only half of it. React Native runs on both iOS and Android, and each platform needs a native declaration before the OS will let your app open a UPI app:

  • iOS: add LSApplicationQueriesSchemes to ios/<YourAppName>/Info.plist (see the iOS Integration Guide for the schemes to declare).
  • Android: add the <queries> block to android/app/src/main/AndroidManifest.xml (see the Android Integration Guide for the configuration required on Android 11+ / API 30+).

The full list of schemes and packages is in the Payment Configuration guide.

Raising an Integration Issue?

Share your equivalent of these three snippets — your onShouldStartLoadWithRequest implementation, your Info.plist schemes, and your AndroidManifest.xml queries — with the Hubble team. These are the first things we check when UPI apps do not open.

Best Practices

  • Wrap in SafeAreaView: Always wrap the WebView in a SafeAreaView to avoid content being hidden behind the notch or status bar.
  • Disable caching: Set cacheEnabled={false} to ensure a fresh session on every load.
  • Handle loading state: Use startInLoadingState={true} and the app_ready event to show a smooth loading experience.
  • Test on both platforms: React Native WebView behavior can differ between iOS and Android. Test on both.