Skip to content
IntelliProve

Expo

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:

  1. Setting up the Expo Module
  2. Interfacing with the Native code from Expo (bridging)

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

For this guide, we assume a minimal ‘Hello World’ application generated by the Expo project initialisation.

Last update 22/08/2026 14:32

expo-intelliprovewebview-2.0.0.tgz
  • Copy the expo-intelliprovewebview-x.x.x.tgz tarball into your Expo App root directory.
  • In your Expo App root directory, execute npm install /path/to/tarball/expo-intelliprovewebview-x.x.x.tgz.

We need to configure the minimum deployment target of the application, and allow Camera Usage by the application.

  • Open app.json and add:
...
"ios": {
...,
"deploymentTarget": "15.0",
"infoPlist": {
"NSCameraUsageDescription": "We need camera permission for performing the measurement."
}
},
...
  • Then run npx pod-install to ensure all iOS dependencies are added to your application.
  • Run npx expo install expo-build-properties. This allows you to edit the gradle build properties for the Android application.
  • Then in app.json add 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.js relative 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",
{}
]
]

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.tsx or wherever in the Expo app that the IntelliProve web view will be used. (For newer Expo projects, add the code to the RootLayout in the _layout.tsx file instead.)
  • Add the following imports:
// For registering the event listener
import { useEffect } from 'react';
// The IntelliProve expo module
import * as ExpoIntelliProveWebView from 'expo-intelliprovewebview';
  • Add a function handleOpenWebView that 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 --clean
  • npx expo run:ios or npx expo run:android
  • To match the plug-in with your brand’s colours and fonts, please visit our our UI Customization documentation.