How to use Web SDK
This tutorial will help you create a simple identity validation web app using the Incode Web SDK
Prerequisites
Read the following guide before you start:
Sample Code
You can find sample code for this approach in Code Samples for Web Integrations. This includes a fake_backend.js with all the needed steps to move to a formal back end for production.
Steps
This tutorial uses a linear approach; that is, all Incode verification modules are executed one after the other. The following diagram illustrates this at a high level:
This approach is the most convenient for scenarios where you want users to go through all the Incode modules before they go any further in your application.
Set up tutorial project
Set up a project with the following structure:
my-incode-app
|__ index.html
|__ app.jsmy-incode-app
|__index.html
|__main.js
|__package.json
|__.envSet up HTML
Some SDK methods require an HTML element to contain the UI components. A div element with the id incode-container will hold the SDK components as shown in the following code. https://demo-api.incodesmile.com/0/
index.html
<!DOCTYPE html>
<html lang="en" translate="no">
<head>
<title>Incode WebSdk</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="google" content="notranslate">
<script src="https://sdk.incode.com/sdk/onBoarding-{user.WEB_SDK_VERSION}.js" defer></script>
<script src="./app.js" defer></script>
</head>
<body>
<div id="incode-container"></div>
</body>
</html><!DOCTYPE html>
<html lang="en" translate="no">
<head>
<title>Incode WebSdk</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="google" content="notranslate">
</head>
<body>
<div id="incode-container"> </div>
<script type="module" src="/main.js"></script>
</body>
</html>
Known Issue: DOM mutations by Google TranslateObserve the
translate="no"attribute at thehtmltag and the<meta name="google" content="notranslate">within theheadtag. You should include them in your project to prevent undesired DOM mutations from Google Chrome's Translate functionality. These mutations may cause DOM errors in your integration.If your application requires multiple languages, read our guide on how to include and customize String Localizations
Initialize the Web SDK
- Initialize the Incode Web SDK using the
createmethod. - Create a new Onboarding Session.
- Create a reference to the HTML element that will contain the SDK UI components.
app.js
let incode;
async function app(){
incode = await window.OnBoarding.create({
apiURL: "{user.DEMO_URL_0}" // API URL provided by Incode
});
await incode.initialize();
}
document.addEventListener("DOMContentLoaded", app);import { create } from '@incodetech/welcome';
let incode;
async function app() {
incode = create({
apiURL:"{user.DEMO_URL_0}", // API URL provided by Incode
});
await incode.initialize();
}
document.addEventListener("DOMContentLoaded", app);Fetch a session object
session objectCreate a session object
session objectAn Onboarding Session Token (or just "session token") is required. It provides a link between all the user information and the validation results.
NOTE
If you don't know how to create an onboarding session, read the guide on creating onboarding sessions from your application back end before you continue.
Save the session token for later
If you already know how to create an onboarding session, you can fetch a new session object from your application back end and save the response in a variable (session) for later use. The following code shows how to do this.
let incode;
let session;
async function app(){
incode = await window.OnBoarding.create({
apiURL: "{user.DEMO_URL_0}" // API URL provided by Incode
});
await incode.initialize();
// Get the session from your backend
session = await mySessionRequestMethod();
}
document.addEventListener("DOMContentLoaded", app);import { create } from '@incodetech/welcome';
let incode;
let incodeSession;
async function app() {
incode = create({
apiURL: "<<DEMO_URL_0>>", // API URL provided by Incode
});
await incode.initialize();
// Get the session from the backend
incodeSession = await mySessionRequestMethod();
}
document.addEventListener("DOMContentLoaded", app);Use the onboarding session object
session objectThe session object contains two properties:
{
token:"abc123",
interviewId:"xyz098"
}token: Session token that is sent in every call to the Incode APIinterviewId: Unique identifier of the current Incode onboarding session
In almost all cases, you need the full session object value as an input parameter for the SDK methods. However, specific methods may only require the token value. Read our official SDK Methods reference to know when to use each.
The next steps in building your app involve the Incode onboarding Modules. These Modules are discussed in the recommended implementation order, as shown in the image at the top of this page.
Best Practice
Maintain well-organized code by having a function for each step.
One - Check for any applicable mandatory Biometric Consent
Laws around biometric consent can change from country to country and even from state to state. These laws apply to you depending on where the user is from and where the customer is accessing your system—even if they are using a VPN. You might be subject to fines and penalties even if you didn't know you had to get proper consent from the user.
This pattern of integration lets you leverage the Incode system to detect whether the end user's location is subject to such regulations. Further verifications are done once we know the user's geolocation via GPS and again when we analyze their ID card to determine their origin.
The Biometric Consent check returns a boolean result in our sendFingerprint() method. It clearly shows if biometric consent is necessary and provides any relevant regulationType for such consent.
You can then show the relevant biometric consent using renderBiometricConsent().
In most cases your end user will never see this consent. However, this is likely to change as privacy laws become stricter.
const incodeContainer = document.querySelector("#incode-container");
// 1.- Check if mandatory consent is required. and show it if it is.
function checkMandatoryConsent() {
incode.sendFingerprint({ token: incodeSession.token }).then((response) => {
// Send fingerprint returns a response with the following structure:
// {
// "success": true,
// "sessionStatus": "Alive",
// "ipCountry": "UNITED STATES",
// "ipState": "ILLINOIS",
// "showMandatoryConsent": true,
// "regulationType": "US_Illinois"
// }
// If the response has showMandatoryConsent and is set to true, we need to show the mandatory consent
if (response?.showMandatoryConsent) {
incode.renderBiometricConsent(incodeContainer, {
token: incodeSession,
onSuccess: captureCombinedConsent,
onCancel: () => showError("Mandatory consent was denied"),
regulationType: response.regulationType,
});
} else {
captureCombinedConsent();
}
});
}
NOTE
In the preceding code example, the
onSuccesscallback is used to execute the function corresponding to the next step of the flow. This is to create a "linear" experience for the user.
Two - Show Data Sharing Consent
Before you get any more information from the end user, you must need ask for their consent, Our Data Sharing Consent (or combinedConsent) Module makes this easy.
If you haven't already done so, you can create your first consent and get the consentId for this function from Dashboard > Configuration > Consents.The following image shows an example.
Once you have the consentId, create the following function in your app.js.
// 2.- Show the combined consent
// This consent is created in the dashboard and has to be passed as a parameter
// to the renderCombinedConsent function.
function captureCombinedConsent() {
incode.renderCombinedConsent(incodeContainer, {
token: incodeSession,
onSuccess: sendGeolocation,
consentId: consentId, // id of a consent created in dashboard
});
}Three - Capture Geolocation
Create the following function in your app.js to capture the geolocation of the user.
// 3.- Send geolocation and start the ID capture flow
function sendGeolocation() {
incode.sendGeolocation({ token: incodeSession.token });
captureId();
}Four - Capture and validate ID card
There are two steps to validate an ID card. First, capture the front and back sides of the ID using the renderCaptureId() method. Second, execute the ID validation process (covered in the following section Five).
The renderCaptureId() method is a ready-to-use component. It can activate the device camera and present a capture assistant to capture the ID
NOTE
Most of the options and settings for the
renderCaptureId()andrenderCaptureFace()methods are configured in the Dashboard. These settings include number of capture attempts, manual capture timeout, and optional tutorials. You should complete these configurations before you implement the code in your app.
The following code shows how to implement the renderCaptureId() method to create a flow for the user to capture both sides of a two-sided ID.
// 4.- Capture the ID
function captureId() {
incode.renderCaptureId(incodeContainer, {
session: incodeSession,
onSuccess: processId,
onError: showError,
forceIdV2: false //default to false
});
}renderCaptureId() expects two arguments:
container(HTMLElement): The container HTML element that holds the UI component. In this case, you can see we have selected the element with idincode-container.optionsObject(object): The configuration options for the method, including:session(object): the fullsessionobjectonSuccess(function): A callback to be executed after a successful capture.onError(function): A callback to be executed if the number of tries is reached.forceIdv2(boolean): If you want to forcibly enable the new ID capture experience, set totrue, if not, it will dynamically adjust how many of your users it will present the old and the new capture experience.
TIP
The Web SDK takes care of requesting permission from the user for use of the device's camera. The camera cannot be activated without the user explicitly allowing its use.
If the user denies use of the camera, the
renderCaptureId()method triggers theonErrorcallback with the error messageDOMException: Permission denied. This error means the ID capture and validation cannot be performed.
Five - Process ID
Identity validations and OCR data extraction occur on the Incode platform. This processing is triggered using the processId() method shown here.
// 5.- Process the ID
async function processId() {
return incode.processId({ token: incodeSession.token })
.then(() => {
captureSelfie();
})
.catch((error) => {
showError(error);
});
}processId() expects one argument:
optionsObject(object):token(string): Sessiontokenvalue, taken from thesessionobject.
processId() returns a promise. If the promise is resolved, the ID is processed. If it is rejected, there was an error trying to process the ID.
In example shown previously, we use then to execute the next step of the user flow and catch to display the error in the console.
IMPORTANT
The
processId()method does not return either the scores or OCR data of the ID document. Validation scores and OCR data must be requested in your application back end.
Six - Validate user selfie against ID
To compare the face of the user against the photo in the ID, use the renderCaptureFace() method one more time, as shown here.
// 6.- Capture the selfie
function captureSelfie() {
incode.renderCaptureFace(incodeContainer, {
session: incodeSession,
onSuccess: processFace,
onError: showError,
forceV2: false //default to false
});
}As you may notice, the configuration options here are the same as for the ID capture step. However, this time, the forceV2 option is slightly different (in the ID capture, it is forceIdV2).
Seven - Process face
Face validations and OCR data extraction occur on the Incode platform. This processing is triggered using the processFace() method, as shown here.
// 7.- Process the Face
async function processFace() {
return incode.processFace({ token: incodeSession.token })
.then(() => {
finishOnboarding();
})
.catch((error) => {
showError(error);
});
}processFace() expects one argument:
optionsObject(object):token(string): The sessiontokenvalue, taken from thesessionobject.
processFace() returns a promise. If the promise is resolved, the face is processed. If it is rejected, there was an error trying to process the face.
As before, we use then to execute the next step of the user flow and catch to display the error in the console.
IMPORTANT
The
processFace()method does not return scores. Validation scores and OCR data must be requested in your application back end.
Eight - Mark the onboarding session as complete
Marking an onboarding session as complete tells the Incode platform that the user has finished all flow steps, regardless of the scores. This is a critical step. It tells you how many users went through all the steps from start to finish.
Sessions are marked complete by calling the Mark onboarding complete endpoint from your app back end. You need to pass the session token for the back end to be able to mark the session.
At this point, your app.js file should look like this example:
let incode;
let incodeSession;
const incodeContainer = document.getElementById("camera-container");
// 1.- Check if mandatory consent is required. and show it if it is.
function checkMandatoryConsent() {
incode.sendFingerprint({ token: incodeSession.token }).then((response) => {
// Send fingerprint returns a response with the following structure:
// {
// "success": true,
// "sessionStatus": "Alive",
// "ipCountry": "UNITED STATES",
// "ipState": "ILLINOIS",
// "showMandatoryConsent": true,
// "regulationType": "US_Illinois"
// }
// If the response has showMandatoryConsent and is set to true, we need to show the mandatory consent
if (response?.showMandatoryConsent) {
incode.renderBiometricConsent(incodeContainer, {
token: incodeSession,
onSuccess: captureCombinedConsent,
onCancel: () => console.log("Mandatory consent was denied"),
regulationType: response.regulationType,
});
} else {
captureCombinedConsent();
}
});
}
// 2.- Show the combined consent
// This consent is created in the dashboard and has to be passed as a parameter
// to the renderCombinedConsent function.
function captureCombinedConsent() {
incode.renderCombinedConsent(incodeContainer, {
token: incodeSession,
onSuccess: sendGeolocation,
consentId: < CONSENT ID >, // id of a consent created in dashboard
});
}
// 3.- Send geolocation and start the ID capture flow
function sendGeolocation() {
incode.sendGeolocation({ token: incodeSession.token });
captureId();
}
// 4.- Capture the ID
function captureId() {
incode.renderCaptureId(incodeContainer, {
session: incodeSession,
onSuccess: processId,
onError: console.log,
forceIdV2: forceV2 // Use the global V2 flag
});
}
// 5.- Process the ID
async function processId() {
return incode.processId({ token: incodeSession.token })
.then(() => {
captureSelfie();
})
.catch((error) => {
console.log(error);
});
}
// 6.- Capture the selfie
function captureSelfie() {
incode.renderCaptureFace(incodeContainer, {
session: incodeSession,
onSuccess: processFace,
onError: console.log,
forceV2: forceV2 // defaults to false
});
}
// 7.- Process the Face
async function processFace() {
return incode.processFace({ token: incodeSession.token })
.then(() => {
finishOnboarding();
})
.catch((error) => {
showError(error);
});
}
// 8.- Finish the onboarding
function finishOnboarding() {
myFinishSessionRequestMethod(incodeSession.token)
.then((response) => {
console.log('Finished');
})
.catch((e) => {
console.log(e);
});
}
async function app() {
incode = create({
apiURL: "<<DEMO_URL_0>>", // API URL provided by Incode
});
// Get the session from the backend
incodeSession = await mySessionRequestMethod();
}
document.addEventListener("DOMContentLoaded", app);
import { create } from '@incodetech/welcome';
let incode;
let session;
const incodeContainer = document.querySelector("#incode-container");
function captureIdFrontSide() {
incode.renderCamera("front", incodeContainer, {
token: session,
numberOfTries: 3,
onSuccess: captureIdBackSide,
onError: console.log,
showTutorial: true,
});
}
function captureIdBackSide() {
incode.renderCamera("back", incodeContainer, {
token: session,
numberOfTries: 3,
onSuccess: validateId,
onError: console.log,
showTutorial: true,
});
}
function validateId() {
return incode.processId({ token: session.token })
.then(() => {
captureSelfie();
})
.catch((error) => {
console.log(error);
});
}
function captureSelfie() {
incode.renderCamera("selfie", container, {
token: session,
numberOfTries: 3,
onSuccess: () => mySessionFinishMethod(session.token),
onError: console.log,
showTutorial: true,
});
}
async function app() {
incode = create({
apiURL: "<<DEMO_URL_0>>"
});
//Store the session object in a variable for later use
session = await mySessionRequestMethod();
}
document.addEventListener("DOMContentLoaded", app);Start the flow
To begin the session flow, go to the app() function and add the first step of the flow by calling the captureIdFrontSide() function:
async function app() {
incode = create({
apiURL: "<<DEMO_URL_0>>", // API URL provided by Incode
});
// Get the session from the backend
incodeSession = await mySessionRequestMethod();
// Run first step in the validation
checkMandatoryConsent();
}Test your app
Your application should be fully functional at this point. You should test it thoroughly before putting it into production. Here are some recommendations for making it available for testing:
- All HTTP requests executed from the Web SDK are secured. Run your application over HTTPS. Otherwise, it may cause mixed content warnings and CORS errors.
- The Incode Web SDK is compatible with most development environments and frameworks like Express and Vite. You can use a local server or make it public so others can test it.
IMPORTANT
Make sure you use the Incode testing environment during your development process. Using the Incode production environment may result in service charges in your account. To learn more about service fees, contact your Incode representative.
Updated 3 days ago
Now that your identity validation app is complete, it's time to check the results of each onboarding.
