Appearance
Expo and React Native
The widget embeds in an Expo or bare React Native app via react-native-webview. Full feature parity with the web widget, typically about a day of integration work.
Setup
bash
npx expo install react-native-webviewComponent
tsx
import { useMemo } from 'react';
import { ActivityIndicator, StyleSheet, View } from 'react-native';
import { WebView } from 'react-native-webview';
const WIDGET_ORIGIN = 'https://widget.inviaro.com';
const EMBED_URL = `${WIDGET_ORIGIN}/embed`;
export function InviaroChat({ credentials }) {
const injected = useMemo(() => {
const settings = {
key: process.env.EXPO_PUBLIC_INVIARO_KEY,
origin: WIDGET_ORIGIN,
mode: 'embed',
...(credentials.userId
? {
userId: credentials.userId,
userHash: credentials.userHash,
userEmail: credentials.userEmail,
userName: credentials.userName
}
: {})
};
return `window.InviaroSettings = ${JSON.stringify(settings)}; true;`;
}, [credentials]);
return (
<View style={{ flex: 1 }}>
<WebView
source={{ uri: EMBED_URL }}
injectedJavaScriptBeforeContentLoaded={injected}
originWhitelist={[WIDGET_ORIGIN]}
javaScriptEnabled
domStorageEnabled
keyboardDisplayRequiresUserAction={false}
startInLoadingState
renderLoading={() => (
<View style={styles.loading}>
<ActivityIndicator size="large" />
</View>
)}
/>
</View>
);
}
const styles = StyleSheet.create({
loading: { flex: 1, alignItems: 'center', justifyContent: 'center' }
});Auth hook
tsx
import { useEffect, useState } from 'react';
export function useInviaroCredentials() {
const [creds, setCreds] = useState({
userId: null,
userHash: null,
userEmail: null,
userName: null
});
useEffect(() => {
fetch('https://yourapi.com/api/me/widget-credentials', {
headers: { Authorization: `Bearer ${getToken()}` }
})
.then((r) => r.json())
.then(setCreds)
.catch(() => {
// Anonymous fallback on auth failure.
});
}, []);
return creds;
}Backend endpoint
Your backend computes user_hash server-side. See Identity verification for code samples.
js
app.get('/api/me/widget-credentials', requireAuth, (req, res) => {
const user = req.user;
res.json({
userId: user.id,
userHash: hmacSha256(user.id, process.env.INVIARO_WIDGET_SECRET),
userEmail: user.email,
userName: user.name
});
});Security
The widget_secret lives only on your server. Never bundle it into the Expo app.
Behavior
What works inside the WebView exactly like the web widget:
- Polling and realtime delivery.
- Pre-chat form with localStorage persistence.
- HMAC identity verification.
- Light and dark theme.
- Localization.
- CSAT thumbs.
- Privacy modes and consent gate.
What is slightly different:
- Browser-style notifications may not work in the WebView.
- Keyboard handling requires
keyboardDisplayRequiresUserAction={false}to allow programmatic focus on the composer. - WebView storage is per-origin and persists across app launches.