React Native and Hybrid Apps
Use this guide when an existing hybrid mobile app needs to embed Loyal Guru loyalty modules.
In React Native, the recommended integration is WebView-based. The app loads a small HTML host inside react-native-webview; that HTML host loads the Web SDK from the CDN and initializes the Loyal Guru module.
Architectureβ
This approach reuses the same Web SDK across browser and hybrid app integrations, while the host app keeps control of native navigation, login, token refresh, analytics, and error handling.
Requirementsβ
| Requirement | Description |
|---|---|
| WebView dependency | Install and configure react-native-webview. |
| Module origin | Loyal Guru module URL for the Company and environment. |
| Customer JWT | Token issued by the host backend. |
| Token refresh endpoint | Host backend endpoint that can issue a fresh JWT. |
| Message handling | Host app must process WebView messages from the embedded module. |
Exampleβ
import React, { useMemo, useRef } from 'react';
import { WebView } from 'react-native-webview';
export function LoyaltyWebViewScreen() {
const webViewRef = useRef<WebView>(null);
const iframeOrigin = 'https://your-loyalty-module.loyal.guru';
const token = 'CUSTOMER_JWT';
const locale = 'en';
const module = 'rewards';
const html = useMemo(() => `
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id="loyalty-container"></div>
<script src="https://cdn.loyal.guru/sdk/v1.1.3/embed-sdk.umd.js"></script>
<script>
window.EmbedLoyaltyApp.init({
containerId: 'loyalty-container',
iframeOrigin: '${iframeOrigin}',
module: '${module}',
token: '${token}',
locale: '${locale}',
autoResize: true,
onLoad: function () {
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'SDK_LOADED'
}));
},
onSize: function (size) {
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'SDK_SIZE',
payload: size
}));
},
onServerError: function (error) {
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'SERVER_ERROR',
payload: error
}));
},
onData: function (data) {
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'SDK_DATA',
payload: data
}));
}
});
window.EmbedLoyaltyApp.onTokenRefreshRequested(function () {
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'REQUEST_NEW_TOKEN'
}));
});
</script>
</body>
</html>
`, [iframeOrigin, token, locale, module]);
return (
<WebView
ref={webViewRef}
originWhitelist={['*']}
source={{ html }}
javaScriptEnabled
domStorageEnabled
startInLoadingState
onMessage={async (event) => {
const message = JSON.parse(event.nativeEvent.data);
if (message.type === 'REQUEST_NEW_TOKEN') {
const refreshedToken = await fetchFreshTokenFromYourBackend();
webViewRef.current?.injectJavaScript(`
window.EmbedLoyaltyApp.refreshToken('${refreshedToken}');
true;
`);
}
if (message.type === 'SERVER_ERROR') {
console.warn('Loyalty server error', message.payload);
}
}}
/>
);
}
Token Refreshβ
When the embedded module requests a fresh token:
- The SDK emits
REQUEST_NEW_TOKEN. - The HTML host forwards it through
window.ReactNativeWebView.postMessage. - The React Native app calls its own backend to get a fresh Customer JWT.
- The app injects
EmbedLoyaltyApp.refreshToken(newToken)into the WebView. - The Loyal Guru module resumes without interrupting the Customer session.
Do not reuse expired tokens. Issue short-lived tokens and refresh them on demand.
Native App Responsibilitiesβ
| Responsibility | Detail |
|---|---|
| Navigation | Decide where the loyalty WebView appears and how the Customer enters/leaves it. |
| Login | Authenticate the Customer before opening the loyalty module, unless using LG-managed authentication. |
| Token refresh | Provide a backend refresh endpoint and handle REQUEST_NEW_TOKEN. |
| Error handling | Surface SERVER_ERROR and SDK errors using the host app's UX patterns. |
| External links | Open external URLs outside the WebView where required. |
| Analytics | Forward SDK events to the host analytics layer if needed. |
Production Notesβ
| Area | Recommendation |
|---|---|
| Origin validation | Restrict allowed origins in production. |
| JWT storage | Do not hardcode production JWTs. Store and refresh tokens according to the host app's security standards. |
| WebView permissions | Enable only what the embedded module needs. |
| Layout | Avoid fixed parent heights that clip auto-resized content. |
| Versioning | The host app release cadence remains under the retailer's control; Loyal Guru can update embedded module content without a native release when no native-layer change is required. |