Skip to content

React Native Integration

Gift Card Store - React Native integration example

This example demonstrates how to integrate the Hubble Gift Card Store SDK in a React Native application.

Parameters

ParameterRequiredDescription
clientIdYesClient ID provided by the Hubble team
clientSecretYesClient secret provided by the Hubble team
tokenNoAuth token that uniquely identifies your user. Optional if lazy login is enabled.
wrap-pltYesPlatform identifier. Use rn.
appVersionNoApp version string. Defaults to "10000".
deviceIdNoDevice identifier.

To navigate directly to a specific page, append the route path before the query parameters. See the Deeplinks page for the full route mapping.

PageURL Format
Home (default)https://vouchers.myhubble.money/sdk/gc/?clientId=...
Brand purchasehttps://vouchers.myhubble.money/sdk/gc/buy/{brandId}?clientId=...
Searchhttps://vouchers.myhubble.money/sdk/gc/search?clientId=...
Transactionshttps://vouchers.myhubble.money/sdk/gc/transactions?clientId=...
Helphttps://vouchers.myhubble.money/sdk/gc/help?clientId=...

Events

The SDK communicates with the host app via window.ReactNativeWebView.postMessage(json). Events are JSON objects with a type field:

Action events — SDK lifecycle and navigation:

{"type": "action", "action": "close"}
{"type": "action", "action": "app_ready"}
{"type": "action", "action": "error"}

Analytics events — user interaction tracking:

{"type": "analytics", "event": "event_name", "properties": {"key": "value"}}
ActionDescription
closeUser tapped close. Dismiss the WebView.
app_readySDK loaded successfully.
errorSDK failed to load. Show an error state.

See the Events page for the full list of analytics events.

Full Example

import { router } from "expo-router";
import { useEffect, useRef, useState } from "react";
import { BackHandler, Linking, SafeAreaView } from "react-native";
import WebView, { WebViewMessageEvent } from "react-native-webview";
import { ShouldStartLoadRequest } from "react-native-webview/lib/WebViewTypes";
type HubbleParams = {
token?: string;
clientId: string;
clientSecret: string;
"wrap-plt": string;
appVersion?: string;
deviceId?: string;
};
type HubbleActionEvent = {
type: "action";
action: "close" | "app_ready" | "error";
};
type HubbleAnalyticsEvent = {
type: "analytics";
event: string;
properties: Record<string, any>;
};
type HubbleEvent = HubbleActionEvent | HubbleAnalyticsEvent;
export default function HubbleWebView() {
const params: HubbleParams = {
token: "your_auth_token", // optional for lazy login
clientId: "id_given_by_hubble",
clientSecret: "secret_given_by_hubble",
"wrap-plt": "rn",
// appVersion: "10000", // optional, defaults to 10000
// deviceId: "device_id", // optional
};
const baseUrl = "https://vouchers.dev.myhubble.money/sdk/gc/";
// prod baseUrl: https://vouchers.myhubble.money/sdk/gc/
const sourceUrl = `${baseUrl}?clientId=${params.clientId}&clientSecret=${params.clientSecret}&token=${params.token}&wrap-plt=${params["wrap-plt"]}`;
// Deep link example: to open a brand page directly, append the route path:
// const sourceUrl = `${baseUrl}buy/uber?clientId=${params.clientId}&clientSecret=${params.clientSecret}&token=${params.token}&wrap-plt=${params["wrap-plt"]}`;
const webViewRef = useRef<WebView>(null);
// maintain a variable to keep track of state, if it can be popped or not
const [canGoBack, setCanGoBack] = useState(false);
useEffect(() => {
const backAction = () => {
if (canGoBack && webViewRef.current) {
webViewRef.current.goBack();
return true; // prevent default behavior (app exit)
}
return false; // allow default behavior
};
const backHandler = BackHandler.addEventListener(
"hardwareBackPress",
backAction
);
return () => backHandler.remove();
}, [canGoBack]);
const onShouldStartLoadWithRequest = (e: ShouldStartLoadRequest) => {
if (
e.url?.startsWith(baseUrl) ||
e.url?.startsWith("https://api.razorpay.com")
) {
return true;
} else {
Linking.openURL(e.url);
return false;
}
};
const handleEvent = (e: WebViewMessageEvent) => {
console.log("event", e.nativeEvent.data);
const eventData: HubbleEvent = JSON.parse(e.nativeEvent.data);
if (eventData.type === "action") {
if (eventData.action === "close") {
router.back();
} else if (eventData.action === "app_ready") {
console.log("Hubble SDK is ready");
} else if (eventData.action === "error") {
console.log("Hubble SDK failed to load");
}
} else if (eventData.type === "analytics") {
logEvent(eventData.event, eventData.properties);
}
};
function logEvent(eventType: string, eventParams: Record<string, any>) {
// your implementation of sending events to analytics
console.log("eventType", eventType);
console.log("eventParams", eventParams);
}
return (
<SafeAreaView style={{ flex: 1 }}>
<WebView
ref={webViewRef}
showsVerticalScrollIndicator={false}
javaScriptEnabled={true}
startInLoadingState={true}
webviewDebuggingEnabled={true} // Disable at your end
cacheEnabled={false} // Disable at your end
source={{ uri: sourceUrl }}
setSupportMultipleWindows={true}
javaScriptCanOpenWindowsAutomatically={true} // has to be true
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
onMessage={handleEvent}
onNavigationStateChange={(navState) => {
setCanGoBack(navState.canGoBack);
}}
/>
</SafeAreaView>
);
}