Ergoport Integration Guide
Ergoport is a privacy-preserving age verification transmission layer. One script tag. Your platform receives a boolean. No identity data stored.
Quickstart
Add one script tag to your age gate. That is the entire integration.
<!-- Add to your age gate page --> <script src="https://cdn.ergoport.com/widget.js" data-key="pk_live_YOUR_PLATFORM_KEY" data-email-hash="OPTIONAL_SHA256_EMAIL_HASH" data-session-id="OPTIONAL_SESSION_ID" ></script>
Listen for the verified postMessage event to receive the signal:
window.addEventListener("message", function(e) { // Always verify origin if (e.origin !== "https://cdn.ergoport.com") return; const { event, verified, human_verified, app_confirmed, method } = e.data; if (event === "verified" && verified === true) { // Age verified — lift your age gate grantAccess(); } });
Platform Types
Your platform type is set at onboarding and tied to your API key. The widget reads it on load — you cannot change it at runtime.
Widget Parameters
| Parameter | Required | Description |
|---|---|---|
data-key |
required | Your platform API key. Begins with pk_live_. Never use your secret key in the widget. |
data-email-hash |
optional | SHA-256 of the normalised email: SHA256(lowercase(trim(email))). Enables identity-linked flows. Omit for anon flow. |
data-consent-ts |
optional | Unix timestamp of prior consent. Include for returning user re-verification flows. Omit on first-time verification. |
data-session-id |
optional | Your own session identifier. Anon flows only. Ergoport echoes it back in the postMessage. Never stored against a user. |
SHA256(lowercase(trim(email))). Do not send the raw email. Do not use a different hashing algorithm or your users will not be matched.
PostMessage Events
The widget communicates exclusively via window.postMessage. Always validate the origin before processing.
event: "verified"
Fired when a user successfully completes verification. This is the primary event you handle.
HEAA Flow
HEAA App only. User enters a TOTP code from the Ergoport app. Highest assurance level. Required for UK Online Safety Act primary priority content.
verified: true, app_confirmed: true, human_verified: true, method: "totp_app"Non-HEAA Flow
Standard Three verification paths. User chooses based on what they have available. Platform decides which signals it accepts.
| Path | How | app_confirmed | method |
|---|---|---|---|
| Ergoport app | Enter session code in app | true | session_code_app |
| ergoport.com/verify | Log in on mweb, enter code | false | session_code_mweb |
| Email OTP | OTP sent to email on file | false | email_otp |
data-email-hash. Without it, the widget shows session code paths only. No email OTP option is shown for anon flows.
Anon Flow
Triggered when no data-email-hash is passed. No identity claimed. Returns human_verified: true only. Both HEAA and Non-HEAA platforms can use this for bot detection / CAPTCHA replacement.
<!-- No email hash — triggers anon flow --> <script src="https://cdn.ergoport.com/widget.js" data-key="pk_live_YOUR_PLATFORM_KEY" data-session-id="your_internal_session_123" ></script> // Response will include: // { verified: false, human_verified: true, // session_id: "your_internal_session_123", // expires_at: 1234567890 }
Signal Reference
| Flow | verified | human_verified | app_confirmed | method |
|---|---|---|---|---|
| HEAA — new user | true | true | true | totp_app |
| HEAA — returning | true | true | true | totp_app |
| HEAA — anon | false | true | true | session_code_app |
| Standard — app | true | true | true | session_code_app |
| Standard — mweb | true | true | false | session_code_mweb |
| Standard — email OTP | true | true | false | email_otp |
| Standard — anon (app) | false | true | true | session_code_app |
| Standard — anon (mweb) | false | true | false | session_code_mweb |
Email Hash Standard
Ergoport uses a standardised lookup hash format. Your backend must produce this exactly or users will not be matched.
// Step 1: normalise const normalized = email.toLowerCase().trim(); // Step 2: SHA-256 hash const encoder = new TextEncoder(); const data = encoder.encode(normalized); const hashBuffer = await crypto.subtle.digest("SHA-256", data); const hashArray = Array.from(new Uint8Array(hashBuffer)); const emailHash = hashArray .map(b => b.toString(16).padStart(2, "0")) .join(""); // Pass as data-email-hash
Security Notes
| Requirement | Detail |
|---|---|
| Validate postMessage origin | Always check e.origin === "https://cdn.ergoport.com" before processing any message. |
| Never expose secret key | Your sk_live_ key is for server-to-server calls only. Never include it in frontend code or the widget. |
| Session codes are single-use | Each session code is invalidated immediately after successful verification. The same code cannot be reused. |
| Enforce expires_at server-side | Ergoport issues tokens with expires_at. Your platform is responsible for enforcing expiry and re-surfacing the widget when needed. |
| No raw emails | Never send raw email addresses to Ergoport. Pass SHA256(lowercase(trim(email))) only. Ergoport never stores raw emails. |
Compliance Coverage
| Jurisdiction | Regulation | Status |
|---|---|---|
| 🇬🇧 United Kingdom | Online Safety Act — HEAA | ● Live — Lewis Silkin opinion |
| 🇮🇹 Italy | AGCOM Caivano Decree — Double Anonymity | ● AGCOM certification in progress |
| 🇺🇸 Texas + 23 states | HB 1181 and mirror state laws | ● US counsel opinion in progress |
| 🇪🇺 European Union | DSA Article 28 + eIDAS 2.0 | ● EU relying party — 2027 |