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
| Parameter | Required | Description |
|---|---|---|
clientId | Yes | Client ID provided by the Hubble team |
clientSecret | Yes | Client secret provided by the Hubble team |
token | No | Auth token that uniquely identifies your user. Optional if lazy login is enabled. |
wrap-plt | Yes | Platform identifier. Use rn. |
appVersion | No | App version string. Defaults to "10000". |
deviceId | No | Device identifier. |
Deep Links
To navigate directly to a specific page, append the route path before the query parameters. See the Deeplinks page for the full route mapping.
| Page | URL Format |
|---|---|
| Home (default) | https://vouchers.myhubble.money/sdk/gc/?clientId=... |
| Brand purchase | https://vouchers.myhubble.money/sdk/gc/buy/{brandId}?clientId=... |
| Search | https://vouchers.myhubble.money/sdk/gc/search?clientId=... |
| Transactions | https://vouchers.myhubble.money/sdk/gc/transactions?clientId=... |
| Help | https://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"}}| Action | Description |
|---|---|
close | User tapped close. Dismiss the WebView. |
app_ready | SDK loaded successfully. |
error | SDK 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> );}