Skip to main content

JavaScript SDK

You can use the Real ID JavaScript SDK for advanced custom use cases to trigger ID checks without relying on the built-in triggers available in the before checkout flow.

The JS SDK lets you to programmatically require ID verification gates at any time on the frontend of your site. This includes using it as an alternative to platform-specific checkout extensions for implementing ID verification during checkout on any platform — use mode: "modal" to gate a checkout button until the customer has verified their identity.

Getting Started​

If you have the before checkout flow enabled and are working with an Online Storefront page in Shopify or WooCommerce, then SDK will be included automatically.

But if you have no automatic verification enabled or are working on a custom page outside of the online store, then you'll need to install the SDK on your site. Include the script tag to install it:

<script
type="text/javascript"
src="https://verify.getverdict.com/assets/index.js"
></script>

Then this script tag will load the RealID object into your browser window.

Pasting into a Shopify theme instead? See installing on a Shopify theme with Liquid for the snippet form, including how to pass logged-in customer data through Liquid.

tip

You'll need to use an HTTPS server for a secure connection in order to properly load the assets for the SDK as well as access the customers camera during verification.

Authentication​

On Shopify, WooCommerce, and BigCommerce storefronts, the SDK automatically identifies your store — no additional authentication is needed.

For custom websites or any page where the SDK can't auto-detect your store, pass your publicKey to authenticate:

RealID.createFlow({
target: "#real-id-mount",
mode: "full",
publicKey: "pk_your-public-key-here",
});

The publicKey is a client-safe key that identifies your Real ID account. You can find it in your Real ID dashboard under Settings > DevTools.

Keep your keys separate

The publicKey is safe to include in frontend code — it can only be used to create and load ID checks for your account. Your API token (used for the REST API) is a secret and should never be exposed in client-side code.

Creating an ID verification gate​

Real ID supports two separate modes for prompting ID verification from your customers.

You can simply display the ID check as an element, or you can either override a button or element that requires ID verification, such as a checkout or form submission button.

  • full mode - embed the entire ID verification prompt directly in the current page
  • modal mode - replace the target element with an ID verification button, then after the customer is verified or manually approved, show the original element such as a checkout or form submission button again.

full Mode Example​

// Create a new ID verification wizard
RealID.createFlow({
// this will display the ID verification wizard immediately on the target.
target: "#real-id-mount",
mode: "full",
});

You can initialize a new ID verification prompt by using the RealID.createFlow method. This method accepts a target which will be used to replace the target with the ID verification prompt.

After the customer verifies their ID, then they'll be able to see the target element again.

// Create a new ID verification gate
RealID.createFlow({
// override the Checkout button until the customer is verified
target: ".checkout-btn",
mode: "modal",
});

Real ID will automatically replace all elements with an ID verification prompt.

Works on any platform

The JS SDK works on any website — including Shopify, WooCommerce, BigCommerce, and custom-built sites.

Removing the ID verification gate​

You can also remove the ID verification gate by calling RealID.unmount().

This will unmount all Real ID flow instances on your frontend immediately, and will restore the target elements.

// immediately remove the ID gates from the page and restore any hidden elements
RealID.unmount();

Installing on a Shopify theme with Liquid​

On Shopify you have two ways to get the SDK onto a storefront page, and they answer different needs:

Use this when
Real ID app embed — no codeYou want the standard before checkout flow: Real ID finds your checkout buttons and gates them for you.
A Liquid snippet — this sectionYou need the flow somewhere the embed doesn't reach, or with options the settings page doesn't expose — a specific element, a registration form, your own theme overrides.

They coexist. If the app embed is already on, the SDK is on the page and your snippet only needs the createFlow() call.

The snippet​

Save this as snippets/real-id-verification.liquid:

{% doc %}
Renders the Real ID verification flow.

@example
{% render 'real-id-verification' %}
{% enddoc %}

<script src="https://verify.getverdict.com/assets/index.js" defer></script>

<div id="real-id-mount"></div>

<script>
document.addEventListener("DOMContentLoaded", function () {
RealID.createFlow({
target: "#real-id-mount",
mode: "full",
email: {{ customer.email | json }},
firstName: {{ customer.first_name | json }},
lastName: {{ customer.last_name | json }},
phone: {{ customer.phone | json }}
});
});
</script>

Then render it wherever you want verification to appear — from a section, a template, or another snippet:

{% render 'real-id-verification' %}

To gate the cart's checkout button instead of embedding the flow inline, render it from your cart section (sections/main-cart-footer.liquid in Dawn) and switch to modal mode against the button your theme already renders:

RealID.createFlow({
target: 'button[name="checkout"]',
mode: "modal"
});

In modal mode the target element stays hidden until the customer passes, so point it at an element that already exists on the page — not at an empty mount <div>.

Build it in the playground

The SDK Playground has a Shopify Liquid tab on its code panel. Set your options against a mock storefront page, then copy the finished snippet — including where to save it and which section to render it from.

Both the scenario and the snippet language are linkable, so you can point someone straight at the version they need:

LinkOpens
/help/sdk-playground?lang=liquidthe Liquid snippet for the default scenario
/help/sdk-playground?scenario=store-gate&lang=liquidthe Liquid snippet for the store gate
/help/sdk-playground?scenario=registrationthe JavaScript snippet for the registration form

lang accepts js (the default) or liquid. The Copy link button in the playground builds one of these for whatever you're looking at.

Pass Liquid values through json​

Always pipe a Liquid value into the json filter instead of wrapping it in quotes:

email: {{ customer.email | json }}

The filter supplies the quotes and escapes the contents, so a customer named O'Brien can't break out of the string and take your script with it. It also renders null for a logged-out visitor, which the SDK treats the same as leaving the option out — so one snippet works for both logged-in and anonymous visitors with no {% if customer %} branching.

You don't need a public key​

The SDK identifies your store from the storefront page itself, so a Liquid snippet never has to carry a publicKey. Only pass one on a page the SDK can't auto-detect — a custom site outside your Shopify storefront.

Where Liquid can't reach​

Two surfaces aren't themeable with Liquid, so a snippet can't put the flow on them:

  • Checkout — checkout.liquid is unsupported for the Information, Shipping and Payment steps. Use the during checkout flow instead, which runs as a Checkout Extension inside checkout itself.
  • Thank you and Order status — Shopify sunset checkout.liquid and additional scripts on these pages on August 28, 2025. Script tags still run there for non-Plus stores until August 26, 2026, which is also when Real ID's automatic injection into the classic order status page stops working. Use the Real ID checkout app block described in the after checkout flow.
A theme snippet gates presentation, not access

Like the before checkout flow, a Liquid snippet changes what renders in the customer's browser. The page's markup is still in the source and direct URLs still resolve. For an age-restricted catalogue or anything carrying a compliance obligation, enforce the gate server-side with the REST API.

Loading in a specific check​

Only for advanced use cases

Real ID JS SDK will automatically create the ID check and associate it with the currently logged in user for you. You typically do not need to use the REST API to create an ID check manually and pass it to the JS SDK.

Passing an ID check manually overrides this behavior, and it's only recommended for advanced use cases like invalidating past approved ID checks on a custom schedule.

By default, the Real ID JS SDK will create an ID check on behalf of the customer. If the customer is logged in, it will automatically pull in their customer ID and will automatically populate their email address and name into the ID check.

Then if the customer returns to this page later, their ID check will be automatically retrieved based on their browser cookies or account details. Find more details about this process here. This helps by making sure the customer only has a single ID check by default.

However, if you need more control - such as expiring IDs or requiring customers to verify again before a specific event, then you can pass a checkId parameter to load a specific ID check.

You can use our REST API to create a check programmatically, which will return the checkId that you can use to pass to the JS SDK options like so:

RealID.createFlow({
target: "#real-id-mount",
mode: "full",
// always load this specific ID check
checkId: `abc123`,
});
Create checks from the browser

You can also create a check client-side with RealID.createCheck() — it returns the checkId without rendering any UI, so you can pass it to createFlow or redirect the customer to the hosted flow yourself.

Fallback behavior

If checkId is null or an empty string, then the SDK will fallback to the normal behavior of looking up or creating a new ID check based on the currently logged in customer's information.

However, if the checkId is invalid, then a new ID check will not be created and the customer will be prompted to enter in their email address to load their ID check.

For best results, please be certain that the checkId is a valid ID check token or you safely provide a null or empty string.

Loading the customer's current ID check​

If you are passing the customer's ID to the create ID check REST API endpoint, then you can use WooCommerce meta or Shopify metafields to load the customer's check ID:

Use the check_id stored by Real ID on your customers accounts.

<script>
RealID.createFlow({
target: "#real-id-mount",
mode: "full",
// always load this specific ID check
checkId: {{ customer.metafields.real_id.check_id | json }},
});
</script>

The json filter supplies its own quotes and escapes the value — so don't add quotes of your own. For a visitor with no saved check it renders null, which the SDK treats the same as leaving checkId out. See installing on a Shopify theme with Liquid.

External database supported

If you store customer accounts on a database outside of Shopify or WooCommerce, then you can use this method to retrieve the customer's ID check token and render their ID check on your site.

Prepopulate customer details​

You can prepopulate customer information to reduce friction during the verification process. When provided, these fields will be automatically filled in for the customer.

Available Fields​

ParameterTypeDescription
emailstringCustomer's email address
firstNamestringCustomer's first name
lastNamestringCustomer's last name
phonestringCustomer's phone number

Basic Example​

RealID.createFlow({
target: "#real-id-mount",
mode: "full",
email: "[email protected]",
firstName: "John",
lastName: "Doe",
phone: "+1-555-0123",
});

Platform-Specific Examples​

Use Liquid variables to pass customer data from logged-in accounts:

<script>
RealID.createFlow({
target: "#real-id-mount",
mode: "full",
email: {{ customer.email | json }},
firstName: {{ customer.first_name | json }},
lastName: {{ customer.last_name | json }},
phone: {{ customer.phone | json }},
});
</script>

Pipe every Liquid value through json rather than wrapping it in quotes — it escapes the contents, so a name containing an apostrophe can't break your script. For a logged-out visitor each field renders null and the SDK falls back to asking the customer for their details.

Automatic Detection

On Shopify, if you're using Customer Fields by Helium, customer data is automatically extracted without any configuration needed.

On WooCommerce, logged-in customer data is automatically detected from the current user session.

SDK-provided values always take priority over auto-detected values.

Cross-checking addresses​

You can provide billing and shipping address data to enable cross-checking rules that compare the verified ID against order information.

info

For Canadian based merchants, the Shipping Address is also considered for age verification. The shipping province (a.k.a state) and country fields are used to determine which age restrictions are used.

If no shipping address is provided, the issuing province of the verified ID is used.

Available Address Fields​

ParameterTypeDescription
firstNamestringFirst name on the address
lastNamestringLast name on the address
address1stringStreet address line 1
address2stringStreet address line 2 (optional)
citystringCity
statestringState/province code (e.g., "CA", "NY")
countrystring2-letter ISO country code (e.g., "US", "CA")

Example​

RealID.createFlow({
target: "#real-id-mount",
mode: "full",
email: "[email protected]",
firstName: "John",
lastName: "Doe",
billingAddress: {
firstName: "John",
lastName: "Doe",
address1: "123 Main St",
city: "Los Angeles",
state: "CA",
country: "US",
},
shippingAddress: {
firstName: "John",
lastName: "Doe",
address1: "456 Oak Ave",
city: "San Francisco",
state: "CA",
country: "US",
},
});

Supported Cross-Checking Rules​

When address data is provided, the following cross-checking rules can be applied after ID verification:

RuleRequired Fields
Billing Name MatchbillingAddress.firstName, billingAddress.lastName
Shipping Name MatchshippingAddress.firstName, shippingAddress.lastName
Billing Address MatchbillingAddress.address1, city, state, country
Shipping Address MatchshippingAddress.address1, city, state, country
Cross-checking is optional

Both billingAddress and shippingAddress are optional. You can provide one, both, or neither. Cross-checking rules will only run if the corresponding address data is available and the rule is enabled in your shop settings.

Rules​

The rules parameter lets you control verification behavior directly from the SDK. These options override the default server-side behavior for the current flow instance.

Available Rules​

ParameterTypeDefaultDescription
emailLookupbooleantrueWhether to look up prior ID checks by email and prompt 2FA for repeat customers

rules.emailLookup​

By default, when a customer starts an ID verification flow, Real ID checks if there's already a completed or in-progress ID check associated with their email address. If one is found, the customer is prompted to confirm their identity via a 2FA code sent to their email — rather than creating a new check.

Setting emailLookup: false disables this behavior, so every createFlow() call creates a fresh ID check regardless of whether the customer has verified before.

When to use this:

  • You're using the SDK to trigger verification for a specific event (e.g., a high-value purchase) and always want a new check
  • You manage check lifecycle yourself via the REST API and checkId
  • You don't want returning customers to be prompted with a 2FA email challenge
RealID.createFlow({
target: "#real-id-mount",
mode: "full",
email: "[email protected]",
rules: {
emailLookup: false, // always create a new check, never return a prior one
},
});
Default behavior preserved

When rules is omitted or emailLookup is true, the SDK behaves exactly as before — repeat customers are detected by email and prompted to confirm via 2FA. The remember repeat customers flow is unaffected.

Other lookup methods are unaffected

emailLookup: false only skips the email-based duplicate check lookup. If a checkId is passed, that check is still loaded directly. Customer ID lookups (for logged-in Shopify/WooCommerce users) and checkout session lookups are also unaffected.

Theming​

The JS SDK supports theme customization through the theme parameter, allowing you to override default behaviors and content.

Theme Configuration​

RealID.createFlow({
target: "#real-id-mount",
mode: "modal",
// Changing the verified button to redirect to a specific URL
theme: {
verified: {
button: {
content: "Continue to Checkout",
url: "https://yourstore.com/checkout",
},
},
// disabling desktop users from using their desktop camera, and forcing a cross device exchange via a QR code
camera: {
desktop: {
enabled: false,
},
},
},
});

Available Theme Options​

theme.verified.button​

Controls the call-to-action button displayed after successful ID verification.

  • content (string, required): The text displayed on the button
  • url (string, required): The URL to redirect to when the button is clicked

Example:

theme: {
verified: {
button: {
content: "Checkout",
url: "https://mystore.com/checkout"
}
}
}

Default Behavior:

  • If not specified, the button will show platform-specific default text (e.g., "Continue to Checkout" for pre-checkout flows)
  • Without a custom URL, users are redirected to platform-specific default locations (checkout page, order status, etc.)

theme.camera.desktop​

Controls the availability of desktop webcam option during ID verification.

  • enabled (boolean, optional, default: true): Whether to show using a webcam as an option on desktop devices

Example:

theme: {
camera: {
desktop: {
enabled: false; // Hide desktop webcam option, force mobile QR scan
}
}
}

Use Cases:

  • Security-conscious environments: Disable desktop cameras for compliance
  • Mobile-first experience: Encourage better photo quality through mobile capture
  • Technical limitations: When desktop webcam quality is insufficient

Behavior:

  • When enabled: true (default): Desktop users see QR code scan, desktop webcam, and manual upload options
  • When enabled: false: Desktop users only see QR code scan and manual upload options
  • Mobile devices are unaffected by this setting

theme.autoScroll​

Controls whether the SDK automatically scrolls to the verification widget on initial load and between steps.

  • disabled (boolean, optional, default: false): Set to true to prevent all auto-scrolling

Example:

theme: {
autoScroll: {
disabled: true // Prevent auto-scrolling to the widget
}
}

Use Cases:

  • Custom scroll behavior: You manage scroll position yourself after mounting the widget
  • Single-page applications: Avoid unexpected scroll jumps in SPA layouts
  • Inline embeds: The widget is already visible and scrolling would be disorienting

Behavior:

  • When disabled: false (default): The page scrolls to the widget on load and after each verification step
  • When disabled: true: No automatic scrolling occurs — the widget renders in place without affecting scroll position

Theme Priority​

Theme settings follow this priority order (highest to lowest):

  1. JS SDK theme parameter - Passed directly to createFlow()
  2. Shop settings theme - Configured in the Real ID app dashboard
  3. Default platform behavior - Built-in fallbacks

This means JS SDK theme options will always override shop-level theme settings.

Complete Example​

RealID.createFlow({
target: ".checkout-button",
mode: "modal",
theme: {
// Customize the success button
verified: {
button: {
content: "Complete Your Purchase",
url: "https://mystore.com/checkout?verified=true",
},
},
// Disable desktop webcam for security
camera: {
desktop: {
enabled: false,
},
},
// Disable auto-scrolling to the widget
autoScroll: {
disabled: true,
},
},
});

::: Additional customizations available

We can help add additional theme options and customizations. Please contact us if you need additional configuration or settings.

:::

Events​

The JS SDK dispatches custom events on window when an ID check completes. You can listen for these events to trigger your own logic — for example, enabling a checkout button, redirecting the customer, or sending events to your analytics platform.

Available Events​

Event NameWhen It Fires
real-id-check-loadedA check has been loaded or created and is now available — fired before the customer verifies
real-id-check-passedThe customer's ID check completed successfully and passed all rules
real-id-check-failedThe customer's ID check failed automated verification or was sent for manual review

All events are standard CustomEvent instances dispatched on the global window object.

Listening for Events​

Attach a listener to window to react to the verification lifecycle:

window.addEventListener("real-id-check-loaded", (event) => {
const { check } = event.detail;
console.log("ID check available", check.id);
// e.g. record the check ID, populate hidden form fields, fetch related order data
});

window.addEventListener("real-id-check-passed", (event) => {
const { check } = event.detail;
console.log("ID check passed", check.id);
// e.g. enable a checkout button, redirect, or report to analytics
});

window.addEventListener("real-id-check-failed", (event) => {
const { check } = event.detail;
console.log("ID check failed", check.id, "step:", check.step);
// e.g. show a custom error message or route to your support flow
});

All event payloads use snake_case field names to match the REST API response format.

Event Payload​

Each event delivers the same shape on event.detail, matching the REST API GET /api/v1/checks/:checkId envelope:

{
check: {
id: "abc123",
step: "completed", // or "in_review"
shop_name: "my-store.myshopify.com",
platform: "shopify", // "shopify" | "wc" | "bc"
order: {
id: null, // Shopify admin GraphQL id or WC order id
name: null, // order display name / number
},
customer: {
first_name: "Jane",
last_name: "Smith",
email: "[email protected]",
phone: null,
},
rules: {
testing: false, // true when the check is in sandbox mode
signature_required: false,
id_check_type: "idv", // "id" | "idv"
include_back_of_id: false,
selfie_liveness: "straight",
},
result: {
success: true, // false for failed checks, undefined before verification
},
}
}
Private details are not available in the JS SDK

The customer's PII extracted from their ID (document number, date of birth, address, verification scores, photos) is not accessible through the client-side JS SDK. To retrieve this information, use the REST API over a secure server-to-server connection.

real-id-check-loaded​

Fired as soon as the SDK has loaded or created an ID check for the customer. This happens before the customer has captured their ID — it's the earliest point at which a check.id is available.

This event also re-fires after a 2FA confirmation refreshes the check, or after the SDK retrieves the latest state from the API.

Use this event when you want to:

  • Capture the check.id so you can correlate it with your own systems (orders, sessions, analytics)
  • Pre-populate hidden form fields with the check token
  • Detect whether the check is already in a terminal state (e.g., a returning verified customer)
window.addEventListener("real-id-check-loaded", (event) => {
const { check } = event.detail;

// Store the check ID for later reference
document.getElementById("real-id-check-id-input").value = check.id;

// Returning customer who has already verified
if (check.step === "completed" && check.result?.success) {
console.log("Customer already verified");
}
});

real-id-check-passed​

Fired when both conditions are true:

  • check.step === "completed", and
  • check.job.result.success === true

This is the canonical success signal — the ID was verified and any cross-checking rules were satisfied.

Modal mode unmounts before the event fires

In mode: "modal", the SDK unmounts the flow and restores the original target element before dispatching real-id-check-passed. By the time your listener runs, the target (e.g., a checkout button) is already visible again.

real-id-check-failed​

Fired when either condition is true:

  • check.step === "in_review" (the check needs manual merchant review), or
  • check.job.result.success is falsy (automated verification rejected the ID)

Inspect check.step to distinguish between a hard failure and a soft "pending review" state:

window.addEventListener("real-id-check-failed", (event) => {
const { check } = event.detail;

if (check.step === "in_review") {
// Awaiting manual review by the merchant
showMessage("Thanks — your ID is being reviewed. We'll email you shortly.");
} else {
// Automated verification rejected the ID
showMessage("We couldn't verify your ID. Please try again or contact support.");
}
});

Complete Example​

Gate a custom checkout button until the customer passes verification:

<button id="checkout-btn" disabled>Checkout</button>
<div id="real-id-mount"></div>

<script>
RealID.createFlow({
target: "#real-id-mount",
mode: "full",
});

window.addEventListener("real-id-check-passed", () => {
document.getElementById("checkout-btn").disabled = false;
});

window.addEventListener("real-id-check-failed", (event) => {
const { check } = event.detail;
if (check.step === "in_review") {
// Optional: keep the button disabled and inform the customer
alert("Your ID is being reviewed. You'll receive an email once it's approved.");
}
});
</script>

Accessing the current check synchronously​

If you need to read the current check outside of an event handler — for example, in code that runs after the customer has already verified, or to check state on demand — call RealID.getCheck():

const check = RealID.getCheck();

if (check) {
console.log("Current check:", check.id, "step:", check.step, "success:", check.result?.success);
} else {
console.log("No check has been loaded yet");
}

RealID.getCheck() returns the same public check object that's delivered in the events — or null if no check has been loaded in this session yet. It's updated whenever real-id-check-loaded, real-id-check-passed, or real-id-check-failed fires.

Last-write-wins across multiple flows

If a page mounts more than one flow (for example, a "Buy it now" button and a side cart), RealID.getCheck() returns the most recently updated check. The completed check takes precedence over an in-progress one.

Pair the accessor with the load event

For code that loads after the SDK has already started, listen for real-id-check-loaded to be notified of new checks, and use RealID.getCheck() to read state at any point afterward.

Creating a check without UI (createCheck)​

RealID.createCheck() creates an ID check and returns it without rendering any verification UI. Use it when you want to own the experience yourself — for example, on a headless checkout, create the check and then send the customer to the dedicated hosted flow with your own styled button.

const result = await RealID.createCheck({
publicKey: "pk_your-public-key-here",
email: "[email protected]",
});

if (result.status === "verification_required") {
// result.url is the ready-to-use hosted-flow URL for this check
window.open(result.url, "_top");
}

This is the SDK-native equivalent of how the Shopify during-checkout extension works: it creates the check, then links the customer out to the hosted flow. See Responses below for the full set of result.status values.

Authentication

On Shopify, WooCommerce, and BigCommerce storefronts the SDK auto-detects your store. On custom or headless sites, pass your client-safe publicKey (see Authentication).

Options​

ParameterTypeDescription
publicKeystringRequired on custom/headless sites to identify your Real ID account
emailstringCustomer's email address
firstNamestringCustomer's first name
lastNamestringCustomer's last name
phonestringCustomer's phone number
billingAddressobjectBilling address for cross-checking rules
shippingAddressobjectShipping address for cross-checking rules
themeobjectFlow theme (same shape as createFlow). Saved on the check and applied when the customer reaches the hosted flow at result.url. See the note below.
rules.emailLookupbooleanDefaults to false for createCheck — always create a fresh check. Set true to look up returning customers (may require 2FA).
Setting theme on a headless check

createCheck renders no UI, so theme has no immediate effect on the call itself. It's saved on the check and applied when the customer reaches the hosted flow at result.url — where theme.verified.button.url becomes the return URL after verification and theme.verified.button.content sets the button label. See Theming for the full shape.

For your customers' security, only an https:// return URL is honored — other URLs are ignored.

Responses​

createCheck() always resolves to a result object — it never throws for a known outcome. Switch on result.status to decide whether to let the customer continue to checkout or send them to verify:

result.statusPayloadWhat it meansRecommended action
verification_requiredcheck, urlA check was created, or an unfinished one already existsSend the customer to result.url
already_verifiedcheck, urlThe customer has already completed and passed verificationAllow checkout
not_requiredreason?Your rules didn't require verification for this customerAllow checkout
requires_2faemailA returning customer matched by email (only when emailLookup: true)Send them to the hosted flow to confirm via 2FA, or re-call with rules.emailLookup: false
errorcode, message?Shop not found, a server error, or a network errorBlock, or fail-open, per your policy

The check payload uses the same shape as the event payload and RealID.getCheck(). A successful createCheck() also updates RealID.getCheck() and dispatches the real-id-check-loaded event.

Use result.url instead of building the URL yourself

For the two check-bearing statuses, result.url is the ready-to-use hosted-flow URL for that check. It automatically reflects your custom Flow URL (if your shop sets a white-label domain) and the current default flow domain — so you never hardcode verify.getverdict.com.

Already verified vs. needs verification

already_verified is only returned when the existing check is completed and passed (check.step === "completed" and check.result.success === true). Any other existing check — in progress, in review, or failed — resolves as verification_required, so you can send the customer back to finish or view their status.

Example​

const verifyBtn = document.querySelector("#verify-id-btn");

verifyBtn.addEventListener("click", async () => {
const result = await RealID.createCheck({
publicKey: "pk_your-public-key-here",
email: "[email protected]",
firstName: "John",
lastName: "Doe",
});

switch (result.status) {
case "verification_required":
// hand the customer off to the hosted verification flow
window.open(result.url, "_top");
break;
case "already_verified":
case "not_required":
proceedToCheckout(); // let them through
break;
case "requires_2fa":
// returning customer — send them to the hosted flow to confirm, or re-call
// with rules.emailLookup: false to force a brand new check
break;
case "error":
console.error("Real ID:", result.code, result.message);
// block, or fail-open, depending on your risk tolerance
break;
}
});
Prefer to create checks server-side?

If you'd rather keep check creation on your backend, use the secret-key REST API to create a check (POST /api/v1/checks), return the checkId to your frontend, and redirect to https://verify.getverdict.com/{checkId}. Use createCheck() when you want a client-only integration with your public key.

Frequently Asked Questions​

How do I know if the Real ID JS SDK is available in the current page in Shopify?​

Within your browser's JavaScript console, enter in window.RealID. If the result is undefined, then that means you need to install the JS SDK on that page.

Will already verified repeat customers be verified automatically?​

Yes, the SDK will automatically detect if the customer is logged in and has already verified their ID. Or if they are not logged in, then the SDK will find their prior ID check from the customer's email address when they start the flow.

The same methods to remember repeat verified customers for the before checkout flow are used for this SDK.

If you want to disable this behavior and always create a fresh check, use rules.emailLookup: false.

Will my theme and rules be applied?​

Yes, the Real ID JS SDK will automatically apply the rules, content and theme you've set up in the settings page of the app.

Can I use this on any website outside of Shopify & WooCommerce?​

Yes! The JS SDK works on any website. You can use it to implement ID verification gates on BigCommerce, custom-built sites, or any other platform.

Will this work within a Liquid Snippet in my Shopify Theme?​

Yes. See installing on a Shopify theme with Liquid for the full snippet, where to render it from, and how to pass customer data in safely. If the Real ID app embed is already on, the SDK is on the page and you can skip the <script src> line.

Will this work within a Shopify Checkout Extension?​

No, Shopify Checkout Extensions don't allow you to write arbitrary HTML. However, you can use our Shopify checkout app block to require ID verification during checkout, or add the block to the after checkout order status page.

Can I use this on my WordPress site pages?​

Yes, you can add ID verification to any page on your WordPress site, even outside of checkout. Please see our guide here.