Dashboard

Widget Integration Guide

Last Updated: November 30, 2025
Integration Method: JavaScript Widget (Embeddable)

Add VerifyHuman verification to any website with our embeddable JavaScript widgets. No backend required - just copy, paste, and go live.


📋 Table of Contents


Overview

VerifyHuman offers embeddable widgets for all four verification products:

Widget Purpose Best For
VerifyHuman Widget Liveness & bot detection Signup forms, comment sections
VerifyAge Widget Age verification Age-restricted content, e-commerce
VerifyIdentity Widget KYC verification Account verification, marketplaces
VerifyCompliance Widget KYC+ with compliance Financial apps, crypto exchanges

Benefits:


Widget Types

1. VerifyHuman Widget

Basic liveness detection and bot prevention widget.

<script src="https://app.verifyhuman.io/widget.js"></script>
<div id="verifyhuman-widget"></div>

<script>
VerifyHuman.init({
  apiKey: 'vhk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6',
  onSuccess: function(result) {
    console.log('Verified!', result);
  },
  onFailure: function(error) {
    console.error('Failed:', error);
  }
});
</script>

2. VerifyAge Widget

Age verification with two-step flow (selfie → ID if needed).

<script src="https://app.verifyhuman.io/widget-age.js"></script>
<div id="verifyage-widget"></div>

<script>
VerifyAge.init({
  apiKey: 'vhk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6',
  useCase: 'alcohol',
  minAge: 21,
  onSuccess: function(result) {
    console.log('Age verified!', result);
  },
  onFailure: function(error) {
    console.error('Age verification failed:', error);
  }
});
</script>

3. VerifyIdentity Widget

KYC widget with selfie + ID capture.

<script src="https://app.verifyhuman.io/widget-identity.js"></script>
<div id="verifyidentity-widget"></div>

<script>
VerifyIdentity.init({
  apiKey: 'vhk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6',
  requireIdBack: false,  // Optional ID back image
  onSuccess: function(result) {
    console.log('Identity verified!', result);
  },
  onFailure: function(error) {
    console.error('Verification failed:', error);
  }
});
</script>

4. VerifyCompliance Widget

KYC+ widget with integrated compliance screening.

<script src="https://app.verifyhuman.io/widget-compliance.js"></script>
<div id="verifycompliance-widget"></div>

<script>
VerifyCompliance.init({
  apiKey: 'vhk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6',
  requireIdBack: false,
  onSuccess: function(result) {
    if (result.compliance_screening.total_hits === 0) {
      console.log('Cleared!', result);
    } else {
      console.warn('Compliance hits detected:', result.compliance_screening);
    }
  },
  onFailure: function(error) {
    console.error('Verification failed:', error);
  }
});
</script>

Quick Start

Step 1: Include Widget Script

Add the widget script to your HTML <head> or before the closing </body> tag:

<!-- For VerifyHuman -->
<script src="https://app.verifyhuman.io/widget.js"></script>

<!-- For VerifyAge -->
<script src="https://app.verifyhuman.io/widget-age.js"></script>

<!-- For VerifyIdentity -->
<script src="https://app.verifyhuman.io/widget-identity.js"></script>

<!-- For VerifyCompliance -->
<script src="https://app.verifyhuman.io/widget-compliance.js"></script>

Step 2: Add Widget Container

Place the widget container where you want verification to appear:

<div id="verifyhuman-widget"></div>

Step 3: Initialize Widget

Configure and initialize the widget:

<script>
VerifyHuman.init({
  apiKey: 'vhk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6',
  buttonText: 'Verify You\'re Human',
  onSuccess: function(result) {
    // User verified successfully
    document.getElementById('signup-button').disabled = false;
  },
  onFailure: function(error) {
    // Verification failed
    alert('Verification failed: ' + error.message);
  }
});
</script>

Configuration Options

VerifyHuman Widget Options

VerifyHuman.init({
  // Required
  apiKey: 'vhk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6',

  // Optional
  containerId: 'verifyhuman-widget',  // Default: 'verifyhuman-widget'
  buttonText: 'Verify You\'re Human', // Button label
  buttonStyle: 'primary',              // 'primary' | 'secondary' | 'minimal'
  autoOpen: false,                     // Auto-open camera on page load
  showConfidence: false,               // Show confidence score to user
  language: 'en',                      // 'en' | 'es' | 'fr' | 'de'

  // Callbacks
  onSuccess: function(result) { },
  onFailure: function(error) { },
  onClose: function() { },
  onReady: function() { }
});

VerifyAge Widget Options

VerifyAge.init({
  // Required
  apiKey: 'vhk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6',
  useCase: 'alcohol',  // 'adult' | 'alcohol' | 'tobacco' | 'cannabis' | 'gambling' | 'custom'
  minAge: 21,

  // Optional
  containerId: 'verifyage-widget',
  buttonText: 'Verify Your Age',
  buttonStyle: 'primary',
  stateCode: 'CA',                    // For US state-specific compliance
  multiStep: true,                     // Enable multi-step flow (DOB → Selfie → ID)
  allowIdSkip: false,                  // Allow users to skip ID verification
  showAgeEstimate: false,              // Show estimated age to user
  language: 'en',

  // Callbacks
  onSuccess: function(result) { },
  onFailure: function(error) { },
  onStepComplete: function(step, data) { },
  onClose: function() { }
});

VerifyIdentity Widget Options

VerifyIdentity.init({
  // Required
  apiKey: 'vhk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6',

  // Optional
  containerId: 'verifyidentity-widget',
  buttonText: 'Verify Your Identity',
  buttonStyle: 'primary',
  requireIdBack: false,                // Require ID back image
  collectUserData: false,              // Collect name, DOB, address fields
  validateData: false,                 // Validate user input against OCR data
  showExtractedData: false,            // Show extracted data to user
  language: 'en',

  // Callbacks
  onSuccess: function(result) { },
  onFailure: function(error) { },
  onDataExtracted: function(data) { },
  onClose: function() { }
});

VerifyCompliance Widget Options

VerifyCompliance.init({
  // Required
  apiKey: 'vhk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6',

  // Optional
  containerId: 'verifycompliance-widget',
  buttonText: 'Verify Identity & Compliance',
  buttonStyle: 'primary',
  requireIdBack: false,
  collectGender: true,                 // Collect gender for better screening
  autoGenerateReport: false,           // Auto-generate PDF report if hits detected
  reportPassword: 'secure123',         // Password for encrypted PDF
  language: 'en',

  // Callbacks
  onSuccess: function(result) { },
  onFailure: function(error) { },
  onComplianceHit: function(screening) { },
  onReportGenerated: function(report) { },
  onClose: function() { }
});

Callbacks & Events

onSuccess Callback

Called when verification succeeds.

onSuccess: function(result) {
  console.log('Verification ID:', result.verification_id);
  console.log('Status:', result.status);
  console.log('Confidence:', result.confidence);

  // For VerifyAge
  if (result.verified) {
    console.log('Age verified:', result.estimated_age);
  }

  // For VerifyIdentity/Compliance
  if (result.document_data) {
    console.log('Name:', result.document_data.name);
    console.log('DOB:', result.document_data.date_of_birth);
  }

  // For VerifyCompliance
  if (result.compliance_screening) {
    console.log('Compliance status:', result.compliance_screening.status);
    console.log('Hits:', result.compliance_screening.total_hits);
  }
}

onFailure Callback

Called when verification fails.

onFailure: function(error) {
  console.error('Error code:', error.code);
  console.error('Error message:', error.message);

  // Handle specific errors
  switch(error.code) {
    case 'INSUFFICIENT_CREDITS':
      alert('Out of credits. Please upgrade your plan.');
      break;
    case 'INVALID_API_KEY':
      console.error('API key is invalid or inactive');
      break;
    case 'CAMERA_DENIED':
      alert('Please allow camera access to verify.');
      break;
    case 'LOW_CONFIDENCE':
      alert('Verification failed. Please try again with better lighting.');
      break;
    default:
      alert('Verification failed: ' + error.message);
  }
}

onStepComplete Callback (VerifyAge only)

Called when each step of multi-step verification completes.

onStepComplete: function(step, data) {
  console.log('Completed step:', step);  // 'dob' | 'selfie' | 'id'

  if (step === 'dob' && data.underage) {
    // User is underage, verification stopped
    console.log('User is underage:', data.user_age);
  }

  if (step === 'selfie' && data.requires_id) {
    // Selfie age estimation requires ID backup
    console.log('ID verification required');
  }
}

onComplianceHit Callback (VerifyCompliance only)

Called when compliance screening detects hits.

onComplianceHit: function(screening) {
  console.log('Compliance hits detected:', screening.total_hits);
  console.log('Status:', screening.status);  // 'Potential Match'
  console.log('Found records:', screening.found_records);

  // Flag user for manual review
  flagForReview(screening);
}

Styling & Customization

Button Styles

Choose from pre-defined button styles:

// Primary (default) - Blue button
buttonStyle: 'primary'

// Secondary - Gray button
buttonStyle: 'secondary'

// Minimal - Text link style
buttonStyle: 'minimal'

// Custom - Use your own CSS
buttonStyle: 'custom'

Custom CSS

Override widget styles with custom CSS:

<style>
/* Customize button */
.verifyhuman-button {
  background-color: #10b981;
  color: white;
  border-radius: 8px;
  padding: 12px 24px;
  font-size: 16px;
  font-weight: 600;
}

.verifyhuman-button:hover {
  background-color: #059669;
}

/* Customize modal */
.verifyhuman-modal {
  border-radius: 12px;
  box-shadow: 0 10px 40px rgba(0,0,0,0.2);
}

/* Customize video preview */
.verifyhuman-video {
  border-radius: 8px;
  border: 2px solid #10b981;
}
</style>

Dark Mode Support

Widgets automatically detect and adapt to dark mode:

VerifyHuman.init({
  apiKey: 'vhk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6',
  theme: 'auto',  // 'auto' | 'light' | 'dark'
});

Advanced Integration

Signup Form Integration

Require verification before form submission:

<form id="signup-form">
  <input type="email" name="email" placeholder="Email" required>
  <input type="password" name="password" placeholder="Password" required>

  <div id="verifyhuman-widget"></div>

  <button type="submit" id="signup-button" disabled>
    Sign Up
  </button>
</form>

<script>
VerifyHuman.init({
  apiKey: 'vhk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6',
  onSuccess: function(result) {
    // Enable submit button
    document.getElementById('signup-button').disabled = false;

    // Store verification token
    document.getElementById('signup-form').addEventListener('submit', function(e) {
      e.preventDefault();

      // Send verification token with form data
      fetch('/api/signup', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          email: document.querySelector('[name="email"]').value,
          password: document.querySelector('[name="password"]').value,
          verification_token: result.token
        })
      });
    });
  }
});
</script>

Comment Section Integration

Verify users before allowing comments:

<textarea id="comment-text" placeholder="Write your comment..." disabled></textarea>
<button id="comment-submit" disabled>Post Comment</button>

<div id="verifyhuman-widget"></div>

<script>
VerifyHuman.init({
  apiKey: 'vhk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6',
  buttonText: 'Verify to Comment',
  onSuccess: function(result) {
    // Enable comment form
    document.getElementById('comment-text').disabled = false;
    document.getElementById('comment-submit').disabled = false;

    // Store verification ID
    sessionStorage.setItem('verified_user', result.verification_id);
  }
});
</script>

Age-Gated Content

Show content only after age verification:

<div id="age-gate">
  <h2>Age Verification Required</h2>
  <p>You must be 21+ to access this content.</p>
  <div id="verifyage-widget"></div>
</div>

<div id="restricted-content" style="display: none;">
  <!-- Age-restricted content here -->
</div>

<script>
VerifyAge.init({
  apiKey: 'vhk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6',
  useCase: 'alcohol',
  minAge: 21,
  onSuccess: function(result) {
    // Hide age gate
    document.getElementById('age-gate').style.display = 'none';

    // Show restricted content
    document.getElementById('restricted-content').style.display = 'block';

    // Store verification in session
    sessionStorage.setItem('age_verified', 'true');
  }
});

// Check if already verified
if (sessionStorage.getItem('age_verified')) {
  document.getElementById('age-gate').style.display = 'none';
  document.getElementById('restricted-content').style.display = 'block';
}
</script>

Troubleshooting

Widget Not Appearing

Problem: Widget container is empty.

Solutions:

  1. Check that script is loaded: console.log(typeof VerifyHuman)
  2. Verify container ID matches: containerId: 'your-id'
  3. Check browser console for errors
  4. Ensure API key is valid

Camera Not Working

Problem: Camera permission denied or not found.

Solutions:

  1. Check HTTPS: Widgets require HTTPS (except localhost)
  2. Allow camera permission in browser
  3. Test camera: navigator.mediaDevices.getUserMedia({ video: true })
  4. Check for conflicting apps using camera

Verification Failing

Problem: All verifications return FAIL status.

Solutions:

  1. Check API key is active in dashboard
  2. Verify account email is confirmed
  3. Check credits remaining
  4. Test with good lighting and clear face
  5. Check browser console for error details

Styling Issues

Problem: Widget doesn't match site design.

Solutions:

  1. Use buttonStyle: 'custom' for full control
  2. Override CSS classes (see Custom CSS section)
  3. Use theme option to match light/dark mode
  4. Contact support for custom branding (Enterprise)

Browser Support

Widgets support all modern browsers:

Browser Minimum Version
Chrome 60+
Firefox 55+
Safari 11+
Edge 79+
Opera 47+
Samsung Internet 8+

Mobile Support:

Requirements:


Security Considerations

API Key Exposure

Safe: Client-side API keys (vhk-{32chars}) can be exposed in frontend code.

Reason: Keys are scoped to specific products and have built-in rate limiting. They cannot access your account settings or other sensitive data.

Token Validation

Best Practice: Always validate verification tokens on your backend:

// Frontend: Send token to backend
onSuccess: function(result) {
  fetch('/api/validate-verification', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ token: result.token })
  });
}

// Backend: Validate with VerifyHuman
const response = await fetch('https://app.verifyhuman.io/api/validate', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer vhsk-your_api_secret_here',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ token: userToken })
});

CORS & Domain Restrictions

Configure allowed domains in your dashboard:

  1. Go to Dashboard → API Keys
  2. Select your API key
  3. Add Allowed Domains (e.g., yourdomain.com)
  4. Save changes

Support

Need help with widget integration?