Skip to main content

Web App Integration

Markdown

This page describes how the Unico journeys work and the available integration models for embedding them into an application.

A journey is the set of steps the user goes through to complete an identity verification. For example: capturing a document photo and performing a facial capture (liveness).

Unico manages the entire experience. The integration effort is minimal: the journey is created via CreateProcess, the user is directed to it, and the result is received at the end. Everything in between — screens, instructions, validations — is already built and maintained by Unico.

Two integration models​

Each client has different needs. Unico offers two models for directing the user to the journey.

ModelBest for
Journeys SDKWeb applications that need an integrated, seamless experience, keeping the user within the same environment
Direct accessWeb flows where the journey can happen outside the main page, or apps that already embed a WebView. Native apps should prefer the platform SDK
Native apps

If your application is a native mobile app, we recommend using the SDK for the platform it is built on (Android, iOS, or Flutter) instead of a web integration.

The journey takes place inside the application itself, without taking the user out of their context. The Journeys SDK is installed in the application and used to open the journey when needed.

This is the recommended path for a more integrated and seamless experience, keeping the user in the same environment throughout, which tends to reduce friction and drop-off across the flow.

Unico provides a JavaScript library compatible with modern browsers, allowing the journey to be integrated into virtually any application with just a few lines of code.

Compatibility​

The library is designed to fit into any project without friction, regardless of the stack in use:

  • Any web application. Distributed in UMD format, it works when imported through modern bundlers (such as webpack or Vite). Compatible with any framework (React, Angular, Vue) or plain JavaScript.
  • Modern browsers. The library already includes the necessary polyfills for features like Promises and async/await, extending compatibility to older browser versions as well.
  • Standard web APIs. The journey runs on native browser capabilities, with no dependency on plugins or external libraries in the project.

How the SDK works internally​

When a journey is opened, the SDK inserts an iFrame into the page and takes control of the entire visual experience from that point on. The screens, scripts, and assets for each step run inside this iFrame, from the moment the user begins through to the completion of the process.

This architectural decision is intentional: iFrame isolation ensures the Unico journey does not interfere with the application's styles or behavior. No script leaks into the external context, no CSS rule collides with the application's own styles. The result is a consistent experience for the end user and minimal impact on the client's product.

Since Unico is responsible for creating and managing the iFrame, journey improvements — whether in performance, experience, or validation — are delivered automatically to all users, with no changes required in the integrated application. The integration will always run with the best available optimizations, without needing to track or react to every platform update.

Getting started​

Step 1 — Installation

The unico-journey-sdk package is shared between IDPay payment journeys and identity verification journeys. For identity use cases, import the ByUnicoSDK class as shown in the steps below.

npm install unico-journey-sdk
Formerly idpay-b2b-sdk

This package was previously published as idpay-b2b-sdk. It is the same SDK under a new name and keeps the same version line. Only 2.3.0 and later are available under the new name — see the Release Notes for the full history.

The recommended way to install the Journeys SDK is through a package manager such as npm or yarn, from the package available on the npm registry. In addition to simplifying installation and dependency management, this approach provides clear control over the version in use and makes it straightforward to update whenever a new version is published.

The SDK follows Semantic Versioning (SemVer), meaning patch and minor updates do not introduce breaking changes. It is safe to configure the project to receive these updates automatically. Changes that may require integration updates are reserved for major versions and always come with a migration guide.

Keeping the SDK up to date

Staying on the latest version is especially important for two reasons. The first is security: security patches are published whenever vulnerabilities are identified or opportunities to strengthen the communication protocol arise. Running an outdated version means missing these fixes and exposing the flow to unnecessary risk. The second is stability: bug fixes are distributed the same way, and older versions may exhibit behaviors that have already been resolved in more recent releases.

Before getting started, register your domains with the Unico support team. All domains must use HTTPS.

Step 2 — Call init(options)

Initializes the SDK and pre-loads the scripts necessary for the journey to function correctly, creating a smoother experience for the end user. Call this as early as possible in the flow.

ParameterRequiredDescription
tokenYesProcess token returned by the Create Process API
envNoSet to 'uat' for test environments only
import { ByUnicoSDK } from 'unico-journey-sdk';

ByUnicoSDK.init({
token,
// env: 'uat' // only for test environments
});
Step 3 — Call open(options)

Displays the iFrame and starts the journey for the user. From this point on, everything happens automatically inside the iFrame, with no need to manage any intermediate step.

ParameterRequiredDescription
transactionIdYesProcess ID returned by the Create Process API
tokenYesProcess token returned by the Create Process API
onFinishYesCallback executed when the journey ends or is closed
onWidgetVisibilityChangeNoCallback executed when the widget visibility state changes

The next interaction with the application occurs when the journey ends, whether the user completed it or closed it. At that point, the SDK invokes the onFinish callback, passed as a parameter in open. From there, the application can call the getProcess API to check the result, or wait for a Webhook notification if an asynchronous approach is preferred.

In addition to querying the result, it is recommended to use onFinish to handle the application's front-end state:

  • Avoid loops. Prevent the immediate and unnecessary recreation of processes in case the user triggers the flow again right after the journey ends.
  • Flow management. Ensure the user is directed to the next step of the application, avoiding a dead-end screen after the journey closes.
warning

The onFinish callback signals that the user has completed the journey, but does not guarantee approval. The process may have ended with a failure on one of the Unico validation rules. Querying via getProcess or receiving the Webhook notification is not optional: these are the only sources of the actual result, and the application's behavior must be based on them. onFinish must not be used in isolation to determine whether a user was approved.

The onFinish callback receives an object describing how the journey ended:

FieldTypeDescription
typestringHow the journey ended: 'FINISH' (completed) or 'CLOSE' (user closed before finishing)
transactionobject | undefinedPresent when type is 'FINISH'; undefined when type is 'CLOSE'
transaction.idstringProcess identifier (same as transactionId passed in)
transaction.​redirectUrlstringURL to redirect the user after the journey

Handling the onWidgetVisibilityChange callback is optional and may not be relevant to your use case. It is invoked whenever the widget's visibility state changes, and is useful only in a specific scenario: some journeys display a transparent background, keeping the application page visible behind the experience. Applications that show a custom modal during the verification flow (for example, as part of an orchestration across multiple KYC providers) may end up displaying that modal behind the Unico widget, degrading the visual experience. In that case, the callback lets the application suppress any additional visual elements while the Unico journey is active, and restore them once it ends. If your application has no UI that could overlap the widget, you can safely omit it.

ByUnicoSDK.open({
transactionId: '9bc22bac-1e64-49a5-94d6-9e4f8ec9a1bf',
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
onFinish: ({ transaction, type }) => {
if (type === 'FINISH') {
// Journey completed (transaction = { id, redirectUrl }) — continue your flow here.
}
// type === 'CLOSE' → user closed before finishing;
},
// Optional: only needed if your app shows UI that could overlap the widget.
onWidgetVisibilityChange: (visible) => {
// suppress or restore your modal based on widget visibility
},
});

// To close the SDK explicitly at any point:
ByUnicoSDK.close();

The sequence diagram below demonstrates how to use the SDK and the API result to configure the iFrame:

Reference app​

Language / FrameworkDescriptionRepository
Node.js (Express)Reference app in Node.js that implements the full user journey flow with the Journeys SDKGitHub — reference-apps/web

Security​

Security in this model is built in layers, starting with the communication protocol between the SDK and the application running inside the iFrame.

When the journey is loaded, both parties perform a handshake to establish communication. In this process, the Unico application validates the origin of the data injection message received via postMessage against a closed list of authorized domains, segmented by environment (UAT and PROD). Messages from non-approved origins are discarded immediately, preventing the journey from being embedded in unauthorized pages and eliminating the attack surface for vulnerabilities such as clickjacking.

In addition to origin validation, the flow only proceeds with a valid transaction token: a single-use JWT, issued and signed by the Unico backend. This ensures that even an authorized origin cannot operate with an expired, reused, or forged token.

After the handshake, the token is injected into the iFrame and no sensitive information flows between the two parties. All remaining communication serves only for interface control — opening, closing, and screen transitions — preventing process data from being intercepted or leaked during the journey.

The iFrame isolation also protects the integrity of the Unico scripts at runtime. Since the code runs in a context separate from the page, it cannot be accessed or modified by external scripts, ensuring the journey executes exactly as built, without interference.

By design, CSP is not adopted in this integration model. The authorized domains are part of each client's security configuration, and their public exposure in headers could facilitate infrastructure mapping by malicious actors. Since client identification only happens at the time of init, it is not possible to inject these domains dynamically into the headers before that point, making CSP unviable without giving up this privacy. All security guarantees are provided by the handshake protocol described above.

SDK-specific troubleshooting​

This section covers the most common issues encountered during integration and the recommended ways to investigate them.

Unexpected behavior or broken flow​

Check whether any application script is directly manipulating the iFrame in the DOM. The SDK creates and manages the iFrame in the page body, and any external modification — whether to scope, positioning, or attributes — can interfere with the journey's lifecycle and cause unpredictable behavior.

Visual experience different from expected​

Check whether any global stylesheet in the application is overriding properties inside the iFrame. The SDK creates the iFrame and all its internal elements with dynamic IDs and classes prefixed with unico, which significantly reduces the risk of conflict via ID or class selectors. Even so, broad CSS rules — such as tag selectors — can reach elements inside the iFrame and alter the visual experience delivered to the user.

SDK library files modified directly​

Check whether any library file has been modified outside the package manager. The library must be managed exclusively via npm or yarn, with no direct edits to installed files. Manual modifications can produce anomalous behavior that is difficult to reproduce and will prevent Unico support from being able to assist.

Do not keep DevTools open during capture tests​

Unico uses several mechanisms to secure its journeys, one of which detects open DevTools as a potential fraud signal and blocks the submission. Close DevTools before running end-to-end capture tests.

Unsupported integrations

The models described in this documentation — direct access and Journeys SDK — are the only integration approaches officially supported by Unico. Integrations that deviate from these standards may cause unexpected behavior, security flow failures, and journey interruptions, and will not be covered by Unico support.

Examples of unsupported approaches:

  • Embedding the SDK inside a WebView in mobile applications. In these cases, the correct approach is to use the direct access model, opening the journey link directly in the WebView without involving the Journeys SDK.
  • Loading the iFrame directly via an <iframe> HTML tag, without going through the Journeys SDK. The iFrame is an internal implementation detail of the SDK and must not be instantiated manually. The correct approach is to use the Journeys SDK, which manages the iFrame lifecycle securely and within the expected standards.

If there is any doubt about whether an approach is within the supported standard, consult the documentation or contact support before proceeding with the implementation.