Vanilla JavaScript Example
A plain JavaScript class that creates and manages the AgeEvidence verification iframe. No framework dependencies required.
AgeEvidenceWidget Class
The AgeEvidenceWidget class handles iframe creation, postMessage event listening, and cleanup. It accepts configuration options and callback functions.
// AgeEvidence Verification Widget - Vanilla JS
// No framework dependencies required
class AgeEvidenceWidget {
constructor(options) {
this.container = options.container;
this.externalId = options.externalId;
this.apiKey = options.apiKey; // pk_verify_YOUR_KEY
this.level = options.level || 'full_age';
this.theme = options.theme || 'dark';
this.locale = options.locale || 'en';
this.onReady = options.onReady || (() => {});
this.onComplete = options.onComplete || (() => {});
this.onError = options.onError || (() => {});
this.onCancel = options.onCancel || (() => {});
this._handleMessage = this._handleMessage.bind(this);
this._iframe = null;
this.init();
}
init() {
const params = new URLSearchParams({
apiKey: this.apiKey,
externalId: this.externalId,
theme: this.theme,
locale: this.locale,
parentOrigin: window.location.origin,
});
const iframe = document.createElement('iframe');
iframe.src = `https://ageevidence.com/embed/${this.level}?${params}`;
iframe.width = '100%';
iframe.height = '600';
iframe.style.border = 'none';
iframe.style.borderRadius = '12px';
iframe.allow = 'camera';
iframe.setAttribute('frameborder', '0');
this.container.appendChild(iframe);
this._iframe = iframe;
window.addEventListener('message', this._handleMessage);
}
_handleMessage(event) {
// Only trust messages from AgeEvidence
if (event.origin !== 'https://ageevidence.com') return;
const { type, data } = event.data;
switch (type) {
case 'ae:ready':
this.onReady();
break;
case 'ae:complete':
this.onComplete({
verificationId: data.verificationId,
status: data.status,
});
break;
case 'ae:error':
this.onError(data.error);
break;
case 'ae:cancel':
this.onCancel();
break;
}
}
destroy() {
window.removeEventListener('message', this._handleMessage);
if (this._iframe && this._iframe.parentNode) {
this._iframe.parentNode.removeChild(this._iframe);
}
this._iframe = null;
}
}Usage
Create an instance with your API key and user ID. Pass callback functions to handle each verification lifecycle event.
// Usage
const container = document.getElementById('verification-container');
const widget = new AgeEvidenceWidget({
container: container,
externalId: 'user_123',
apiKey: 'pk_verify_YOUR_KEY',
level: 'full_age', // 'age_only' | 'full_age' | 'full_kyc'
theme: 'dark', // 'light' | 'dark' | 'auto'
locale: 'en', // 'en' | 'es' | 'pt' | 'fr'
onReady: () => {
console.log('Widget loaded');
document.getElementById('loading')?.remove();
},
onComplete: (result) => {
console.log('Verification submitted:', result.verificationId);
// Poll status from YOUR backend (which uses the secret key)
pollStatus('user_123');
},
onError: (error) => {
console.error('Verification error:', error);
},
onCancel: () => {
console.log('User cancelled');
widget.destroy();
},
});
// Poll YOUR backend proxy for the result
async function pollStatus(externalId) {
const res = await fetch(`/api/check-verification?externalId=${externalId}`);
const data = await res.json();
if (data.data?.status === 'approved') {
alert('Verification approved!');
widget.destroy();
} else if (data.data?.status === 'rejected') {
alert('Verification rejected.');
widget.destroy();
} else {
// Continue polling (see Status Polling docs for backoff)
setTimeout(() => pollStatus(externalId), 5000);
}
}HTML Template
A minimal HTML page that loads the widget:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Age Verification</title>
</head>
<body>
<h1>Verify Your Age</h1>
<div id="loading">Loading verification widget...</div>
<div id="verification-container"></div>
<script src="ageevidence-widget.js"></script>
<script>
// Initialize the widget (see usage above)
</script>
</body>
</html>Cleanup
Call widget.destroy() to remove the iframe and stop listening for postMessage events. This is important when navigating away from the page in single-page applications or when the user cancels the verification.
Notes
- Replace
pk_verify_YOUR_KEYwith your publishable API key from the dashboard. - The
pollStatusfunction calls your own backend, not the AgeEvidence API directly. - See the Status Polling guide for backoff strategies.
- This class works in all modern browsers (Chrome, Firefox, Safari, Edge).