> ## Documentation Index
> Fetch the complete documentation index at: https://docs.frankieone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# OCR + Biometrics

> This guide covers implementing a biometrics verification

<Callout icon="star" color="#3DD892" iconType="regular">
  Instead of building your own flow, it's *highly recommended* to fork an existing flow from the public sample codes [found here <Icon icon="arrow-up-right-from-square" size={12} />](https://github.com/FrankieOne/frontend-onesdk-public-sample-codes/)
</Callout>

## Flow Overview

<Steps>
  <Step title="Welcome Screen">
    Initial user greeting and introduction
  </Step>

  <Step title="Consent Screen">
    Capture user consent for data processing
  </Step>

  <Step title="OCR Component">
    Document capture for Identity check
  </Step>

  <Step title="Biometrics Component">
    Biometrics (selfie capture) for facial identity
  </Step>
</Steps>

<Callout icon="star" color="#3DD892" iconType="regular">
  ##### OCR Review Features

  The OCR Review screen automatically extracts data from captured documents and allows users to verify:

  * Personal information (names)
  * Address details
  * Document information
  * Biometric data accuracy
</Callout>

## Implementation Guide

<AccordionGroup>
  <Accordion title="1. Initialize OneSDK">
    ```javascript theme={null}
    const oneSDKInstance = await OneSdk({
      session: sessionObjectFromBackend,
      mode: "production",
      recipe: {
        form: {
          provider: {
            name: "react",
            googleApiKey: '<YOUR_GOOGLE_API_KEY>'
          },
        },
      },
    });
    ```

    <Callout icon="thumbtack" color="#1A6CFF" iconType="regular">
      Replace `<YOUR_GOOGLE_API_KEY>` with your actual Google API key for address autocomplete functionality.
    </Callout>
  </Accordion>

  <Accordion title="2. Configure Components">
    ```javascript theme={null}
    // Set up individual profile
    const oneSdkIndividual = oneSDKInstance.individual();
    oneSdkIndividual.setProfileType("auto");

    // Configure form components
    const welcome = oneSDKInstance.component("form", {
      name: "WELCOME",
      mode: "individual",
      type: "manual",
    });

    const consent = oneSDKInstance.component("form", {
      name: "CONSENT",
      mode: "individual",
      type: "manual",
    });

    const biometrics = oneSdk.component("biometrics");
    const ocr = oneSdk.component("ocr");

    ```
  </Accordion>
</AccordionGroup>

## Event Handling

<CodeGroup>
  ```javascript title="Flow Implementation" theme={null}
  // Welcome screen to Consent screen
  welcome.on("form:welcome:ready", () => {
    consent.mount(appContainer);
  });

  // Consent screen to OCR component
  consent.on("form:consent:ready", async () => {
    ocr.mount(appContainer);
  });

  ocr.on("results", ({ document }) => {
      // Present the details of the document that were detected from the uploaded image or images.
    // Decide whether to proceed to the next stage of the onboarding process
    // depending on whether document verification was successful.
    console.log('ocr results');
    if (document) {
          console.log(`document: ${JSON.stringify(document)}`);
        console.log(document.ocrResult.dateOfBirth);
        //oneSdkIndividual.submit();
        biometrics.mount("#form");
    } else {
          console.log("No document returned");
    }
  });

  biometrics.on("results", ({checkStatus}) => {
      // Decide whether to proceed to the next stage of the onboarding process
    // depending on whether biometrics verification was successful.
    console.log('biometrics results');
    if (checkStatus === 'COMPLETE') {
          console.log(checkStatus);
    } else {
          console.log("no biometrics returned");
    }
  });

  // Initialize flow
  welcome.mount(appContainer);

  ```
</CodeGroup>

## Complete Implementation

<Accordion title="Full Code Example">
  ```javascript theme={null}
  async function loadOneSdk() {
    const appContainer = document.getElementById('form-container');

    // Initialize SDK
    const oneSDKInstance = await OneSdk({
      session: sessionObjectFromBackend,
      mode: "production",
      recipe: {
        form: {
          provider: {
            name: "react",
            googleApiKey: '<YOUR_GOOGLE_API_KEY>'
          },
        },
      },
    });

    // Initialize individual profile
    const oneSdkIndividual = oneSDKInstance.individual();
    oneSdkIndividual.setProfileType("auto");

    // Configure components
    const welcome = oneSDKInstance.component("form", {
      name: "WELCOME",
      mode: "individual",
      type: "manual",
    });

    const consent = oneSDKInstance.component("form", {
      name: "CONSENT",
      mode: "individual",
      type: "manual",
    });

    // Set up event handlers
    welcome.on("form:welcome:ready", () => {
      consent.mount(appContainer);
    });

    // Consent screen to OCR component
    consent.on("form:consent:ready", async () => {
      ocr.mount(appContainer);
    });

    ocr.on("results", ({ document }) => {
        // Present the details of the document that were detected from the uploaded image or images.
      // Decide whether to proceed to the next stage of the onboarding process
      // depending on whether document verification was successful.
      console.log('ocr results');
      if (document) {
            console.log(`document: ${JSON.stringify(document)}`);
          console.log(document.ocrResult.dateOfBirth);
          //oneSdkIndividual.submit();
          biometrics.mount("#form");
      } else {
            console.log("No document returned");
      }
    });

    biometrics.on("results", ({checkStatus}) => {
        // Decide whether to proceed to the next stage of the onboarding process
      // depending on whether biometrics verification was successful.
      console.log('biometrics results');
      if (checkStatus === 'COMPLETE') {
            console.log(checkStatus);
      } else {
            console.log("no biometrics returned");
      }
    });

    // Initialize flow
    welcome.mount(appContainer);
  }
  ```
</Accordion>

## Best Practices

<CardGroup cols={2}>
  <Card title="Error Handling" icon="shield-check">
    Add try-catch blocks around asynchronous operations and SDK calls to handle
    potential errors gracefully.
  </Card>

  <Card title="User Experience" icon="user">
    Provide clear loading states and feedback during document processing and
    verification steps.
  </Card>

  <Card title="Testing" icon="vial">
    Test the flow with various document types and edge cases to ensure robust
    implementation.
  </Card>

  <Card title="Security" icon="lock">
    Ensure secure handling of the session object and API keys.
  </Card>
</CardGroup>

<Callout icon="bell" color="#FFCA16" iconType="regular">
  Remember to handle API key security appropriately. Never expose your Google
  API key directly in client-side code in production environments.
</Callout>
