Web Measurement Embedded App (WMEA) - v1.0.1
    Preparing search index...

    Integration Details

    This page explains how the Web Measurement Embedded App (WMEA) fits into your application. It primarily focuses on technical integration, but also covers user-facing messages and supported languages.

    The WMEA is integrated directly by initializing the MeasurementEmbeddedApp class. Fetch your credentials first, then call init method which accepts an object of type MeasurementEmbeddedAppOptions.

    import MeasurementEmbeddedApp, {
    faceAttributeValue,
    type Profile,
    type MeasurementEmbeddedAppOptions,
    } from '@nuralogix.ai/web-measurement-embedded-app';

    const { SEX_ASSIGNED_MALE_AT_BIRTH, SMOKER_FALSE, BLOOD_PRESSURE_MEDICATION_FALSE, DIABETES_NONE } =
    faceAttributeValue;
    const measurementApp = new MeasurementEmbeddedApp();

    // Retrieve credentials before init
    // Let's assume fetchStudyId and fetchToken functions
    // call your server endpoints (e.g., /api/studyId, /api/token)
    const studyIdResponse = await fetchStudyId(); // { status: '200', studyId }
    const tokenResponse = await fetchToken(); // { status: '200', token, refreshToken }

    if (studyIdResponse.status === '200' && tokenResponse.status === '200') {
    const container: HTMLDivElement = document.createElement('div');

    // Style the container before passing it to MeasurementEmbeddedApp
    Object.assign(container.style, {
    position: 'fixed',
    top: '60px',
    left: '0',
    width: '100vw',
    height: 'calc(100vh - 60px)',
    });

    const profile: Profile = {
    age: 40,
    heightCm: 180,
    weightKg: 60,
    sex: SEX_ASSIGNED_MALE_AT_BIRTH,
    smoking: SMOKER_FALSE,
    bloodPressureMedication: BLOOD_PRESSURE_MEDICATION_FALSE,
    diabetes: DIABETES_NONE,
    bypassProfile: false,
    };

    const options: MeasurementEmbeddedAppOptions = {
    container,
    appPath: './measurement-app',
    settings: {
    token: tokenResponse.token,
    refreshToken: tokenResponse.refreshToken,
    studyId: studyIdResponse.studyId,
    },
    profile,
    // language: 'en', // [optional] See list of supported languages
    // apiUrl: 'api.na-east.deepaffex.ai', // [optional] for region specific data processing
    // config, // [optional]
    loadError: function (error) {
    console.error('Load error', error);
    },
    };
    }

    Notes:

    1. Profile values must use the exact faceAttributeValue enum values as shown in the example above. If you are collecting demographic info from a form we recommend setting up your form to use these values so you don't have to worry about conversions.

    2. Default Config used if the optional config object is not passed:

    const defaultConfig: Config = {
    checkConstraints: true,
    cameraFacingMode: undefined,
    cameraAutoStart: false,
    measurementAutoStart: false,
    cancelWhenLowSNR: true,
    debugMode: false,
    downloadPayloads: false,
    defaultCameraId: '',
    };

    Config options:

    • checkConstraints (default: true) – enables constraint validation pre-measurement.
    • cameraFacingMode (default: undefined) – use 'user' for front camera or 'environment' for back camera. When set, it takes precedence over defaultCameraId — the camera is selected by facing direction and the browser chooses the device. Leave it unset to select by defaultCameraId (or the browser default).
    • cameraAutoStart (default: false) – automatically starts the camera once permission is granted.
    • measurementAutoStart (default: false) – automatically starts the measurement once constraints are satisfied.
    • cancelWhenLowSNR (default: true) – cancels the measurement if signal-to-noise ratio falls below threshold.
    • debugMode (default: false) – enables verbose logging to the console for debugging purposes.
    • downloadPayloads (default: false) – when enabled, saves payload and metadata binary files for each chunk sent to DeepAffex Cloud so you can send them to NuraLogix for debugging. A 30-second measurement emits 6 chunks (every 5 seconds), generating 2 files per chunk. Ensure your browser allows multiple file downloads and does not block popups.
    • defaultCameraId (default: '') – preferred camera deviceId to use on startup. Used only when cameraFacingMode is not set (a set cameraFacingMode takes precedence). When the camera selector dropdown is shown (desktop), this becomes the default selection. When the dropdown is hidden (mobile, or cameraAutoStart: true), this camera is opened directly. If the supplied ID does not match any connected device, the browser's default camera is used. See Persisting a camera selection below for usage.

    cameraFacingMode takes precedence over defaultCameraId. A defaultCameraId only counts when it is valid — it matches a currently connected camera; an absent, empty, or disconnected ID is treated as unset.

    cameraFacingMode defaultCameraId valid? Camera opened
    set yes selected by facing mode — the browser picks the device; defaultCameraId is ignored
    set no selected by facing mode
    unset yes the defaultCameraId device (exact match)
    unset no the browser default camera (first available)

    Browsers don't always expose enough metadata for WMEA to pick the "right" camera on its own — for example, iPads expose both a standard and an ultra-wide front camera as facingMode: 'user', and there's no standard way to tell them apart. defaultCameraId lets your application drive that choice instead.

    A typical pattern:

    1. Before initializing WMEA, present your own camera picker (e.g. a <select> populated from navigator.mediaDevices.enumerateDevices()). Camera permission must be granted first for device labels to be populated.
    2. Persist the user's chosen deviceId in localStorage (or another store of your choice).
    3. On subsequent visits, read the stored deviceId and pass it to WMEA as config.defaultCameraId when calling init().
    const savedCameraId = localStorage.getItem('preferredCameraId') ?? '';

    await measurementApp.init({
    // …other options
    config: {
    cameraAutoStart: true,
    defaultCameraId: savedCameraId,
    },
    });

    Note that deviceId values are stable per-(origin, browser profile) but change when the user clears site data. If a stored ID is stale (not connected), WMEA opens the browser's default camera — so leave cameraFacingMode unset when relying on defaultCameraId, since a set cameraFacingMode would take precedence over it.

    MeasurementEmbeddedApp.Results | Results are delivered via on.results event handler. A common pattern is to save them to your app state, then navigate to the results page in your application:

    measurementApp.on.results = (results) => {
    // 1) Persist results in your app state
    store.measurement.setResults(results);

    // 2) Navigate to the results page in your SPA
    router.push('/results');
    };

    Note: Results are available immediately upon measurement completion through the event handler. If legal agreement allows, detailed results can be retrieved later using DeepAffex API endpoints.

    Errors are delivered via on.error event handler:

    import { ErrorCodes } from '@nuralogix.ai/web-measurement-embedded-app';
    measurementApp.on.error = (error) => {
    switch (error.code) {
    case ErrorCodes.PROFILE_INFO_NOT_SET:
    console.log('Profile information is not set', error);
    break;
    // Add switch statements for the rest of available ErrorCodes
    default:
    console.log('An unknown error occurred', error);
    }
    };

    For a list of available error codes please see ErrorCodes

    Events are delivered via on.event event handler:

    import { appEvents } from '@nuralogix.ai/web-measurement-embedded-app';

    measurementApp.on.event = (appEvent) => {
    switch (appEvent) {
    case appEvents.APP_LOADED:
    console.log('Application loaded');
    break;
    // Add switch statements for the rest of available app events
    default:
    console.log('An unknown app event occurred', appEvent);
    break;
    }
    };

    For a list of available error codes please see appEvents

    1. Mount event listeners BEFORE init;
    measurementApp.on.event = (appEvent) => {
    switch (appEvent) {
    case appEvents.MEASUREMENT_PREPARED:
    console.log('Credentials are valid!');
    break;
    case appEvents.ASSETS_DOWNLOADED:
    console.log('Assets downloaded, ready to measure!');
    break;
    }
    };

    measurementApp.on.error = (error) => {
    switch (error.code) {
    case ErrorCodes.MEASUREMENT_PREPARE_FAILED:
    console.error('Credentials are invalid or missing');
    console.error('Check your token, refreshToken, or studyId');
    break;
    }
    };
    1. Call init with credentials

    Language selection follows this priority:

    1. Language specified in initialization object
    2. Browser's active language (if supported)
    3. English (default)

    For a list of available supported languages, please see SupportedLanguage

    For a complete list of available methods and properties, please see MeasurementEmbeddedApp