Introduction
Section titled “Introduction”Using the native iOS/Android WebView implies some extra setup in your Expo project. This setup involves incorporating the IntelliProve plug-in Mobile SDK as a pre-packaged Expo Module and adding the necessary bridging code.
All this is nicely laid out in our step-by-step guide below.
The integration guide covers two sections:
- Setting up the Expo Module
- Interfacing with the Native code from Expo (bridging)
GitHub
Section titled “GitHub”Our GitHub repository provides a fully functional example of our platform’s integration, demonstrating the seamless setup and utilisation of our pre-packaged Expo Module.
https://github.com/IntelliProve/intelliprove-web-plugin-expo
Minimal Requirements
Section titled “Minimal Requirements”For this guide, we assume a minimal ‘Hello World’ application generated by the Expo project initialisation.
1. Expo Module Setup
Section titled “1. Expo Module Setup”Adding the framework
Section titled “Adding the framework”Last update 22/08/2026 14:32
- Copy the
expo-intelliprovewebview-x.x.x.tgztarball into your Expo App root directory. - In your Expo App root directory, execute
npm install /path/to/tarball/expo-intelliprovewebview-x.x.x.tgz.
Configuration for iOS
Section titled “Configuration for iOS”We need to configure the minimum deployment target of the application, and allow Camera Usage by the application.
- Open
app.jsonand add:
...
"ios": { ..., "deploymentTarget": "15.0", "infoPlist": { "NSCameraUsageDescription": "We need camera permission for performing the measurement." } },
...- Then run
npx pod-installto ensure all iOS dependencies are added to your application.
Configuration for Android
Section titled “Configuration for Android”- Run
npx expo install expo-build-properties. This allows you to edit the gradle build properties for the Android application. - Then in
app.jsonadd the following, so we can set the correct SDK versions and permissions:
...
"android": { ..., "permissions": [ "android.permission.INTERNET", "android.permission.CAMERA" ] },
...
"plugins": [ [ "expo-build-properties", { "android": { "compileSdkVersion": 34, "targetSdkVersion": 34, "minSdkVersion": 24, "kotlinVersion": "1.8.0", "buildToolsVersion": "34.0.0" } } ],
... ]We also need to do some updates to the Android Manifest, so we can run the IntelliProve module from the application.
- First, create a file at
plugins/withIntelliProveAndroidManifest.jsrelative to the Expo Application root folder. - In that file, add the following code:
const { withAndroidManifest } = require("@expo/config-plugins");
function addUsesFeatureCameraToManifest(androidManifest) { const { manifest } = androidManifest;
if (!Array.isArray(manifest["uses-feature"])) { manifest["uses-feature"] = []; }
if (!manifest["uses-feature"].find( (item) => item.$["android:name"] === "android.hardware.camera" )) { manifest["uses-feature"]?.push({ $: { "android:name": "android.hardware.camera", "android:required": "false", }, }); }
return androidManifest;}
function addIntelliWebViewActivityToManifest(androidManifest) { const { manifest } = androidManifest;
if (!Array.isArray(manifest["application"])) { console.warn("withIntelliProveAndroidManifest: No application array in manifest?"); return androidManifest; }
const application = manifest["application"].find( (item) => item.$["android:name"] === ".MainApplication" ); if (!application) { console.warn("withIntelliProveAndroidManifest: No .MainApplication?"); return androidManifest; }
if (!Array.isArray(application["activity"])) { application["activity"] = []; }
if (!application["activity"].find( (item) => item.$["android:name"] === "com.intelliprove.webview.IntelliWebViewActivity" )) { application["activity"]?.push({ $: { "android:name": "com.intelliprove.webview.IntelliWebViewActivity" }, }); }
return androidManifest;}
module.exports = function withIntelliProveAndroidManifest(config, attributes) { return withAndroidManifest(config, (config) => { config.modResults = addUsesFeatureCameraToManifest(config.modResults); config.modResults = addIntelliWebViewActivityToManifest(config.modResults); return config; });};- Finally, add the following to
app.json:
... "plugins": [ ... [ "./plugins/withIntelliProveAndroidManifest", {} ] ]2. Expo Integration
Section titled “2. Expo Integration”To be able to call functions on, and receive callbacks from the IntelliProve Expo Module, we need to import it in the Expo application.
- Open
App.tsxor wherever in the Expo app that the IntelliProve web view will be used. (For newer Expo projects, add the code to theRootLayoutin the _layout.tsx file instead.) - Add the following imports:
// For registering the event listenerimport { useEffect } from 'react';// The IntelliProve expo moduleimport * as ExpoIntelliProveWebView from 'expo-intelliprovewebview';- Add a function
handleOpenWebViewthat calls the IntelliProve Expo Module to present the Web View - Also add a callback handler for receiving ‘PostMessage’ messages.
- The post messages allow you to track the progress of the Face Scan and obtain the results from the IntelliProve plug-in immediately after the user has performed the Face Scan. This allows you to use the results in your mobile app, enabling you to link actions to the results or design a custom results screen.
- You can find an overview of the different types of messages on the Message events page.
- Finally, we call the
handleOpenWebView()function from wherever the entry point to the WebView should be. - The URL to open the IntelliProve Face Scan Plug-in (webapp) is also passed to this function. In our example, it is added on a Button press handler.
- Make sure to request the URL for the Face Scan plug-in using the Get Face Scan URL API endpoint.
export default function App() { const handleOpenWebView = () => { ExpoIntelliProveWebView.presentWebView('https://<subdomain.intelliprove.com/...'); };
// Add Event Listener for IntelliWebViewPostMessage API useEffect(() => { // Make sure the name of the listener matches what was used on Native code const subscription = ExpoIntelliProveWebView.addPostMessageListener((event) => { // Handle the received postMessage console.log('Expo PostMessage Full Body:', event.postMessage);
try { // The PostMessage is received as a JSON String, so we need to parse it const parsedMessage = JSON.parse(event.postMessage); if (parsedMessage && parsedMessage.stage) { console.log('Expo PostMessage Stage:', parsedMessage.stage); } else { console.warn('Expo invalid PostMessage format:', parsedMessage); } } catch (error) { console.error('Expo error parsing PostMessage:', error); } });
// Unsubscribe from the event when the component unmounts return () => { subscription.remove(); }; }, []);
...
return ( ... <Button title="Open WebView" onPress={handleOpenWebView} /> ... )}Now run the application as you normally would, for example:
npx expo prebuild --cleannpx expo run:iosornpx expo run:android
Next steps
Section titled “Next steps”- To match the plug-in with your brand’s colours and fonts, please visit our our UI Customization documentation.

