Before Checkout Verification
The Real ID app is currently being reviewed by the BigCommerce App Marketplace team. Until the one-click install is available, please follow these manual setup steps. Contact us to get started.
Before checkout verification requires customers to verify their ID before they can complete their purchase. This prevents orders from unverified customers entirely.
How it works
- Customer adds items to cart and proceeds to checkout
- Before they can enter payment information, the ID verification prompt appears
- Customer must complete verification to continue
- Once verified, they can complete their purchase
Setup
Step 1: Create API Credentials
You'll need to create API credentials in your BigCommerce dashboard:
- Log in to your BigCommerce admin panel
- Go to Settings > API > API Accounts
- Click Create API Account > Create V2/V3 API Token
- Name it "Real ID"
- Under OAuth Scopes, enable the following:
- Customers: Modify
- Orders: Modify
- Products: Read-only
- Storefront API Tokens: Manage
- Carts: Modify
- Information & settings: Read-only
- Click Save
- Important: Copy and save your API credentials (Client ID, Client Secret, and Access Token). You won't be able to see the Access Token again.
Step 2: Save API Credentials in the Real ID App
- Go to app.getverdict.com
- Log in or create an account (contact us if you need access)
- Add your BigCommerce store
- Enter your API credentials from Step 1
- Configure your verification settings
Step 3: Add the Real ID Script
Add the Real ID script to your store using Script Manager:
- In your BigCommerce admin, go to Storefront > Script Manager
- Click Create a Script
- Fill in the following:
- Name: Real ID Verification
- Description: ID verification at checkout
- Location on page: Footer
- Select pages where script will be added: Checkout
- Script category: Essential
- Script type: URL
- Script URL:
https://bc-flow.getverdict.com/assets/index.js - Integrity Hashes:
sha384-tdFB59KDtQw0ZQvz7/se6OY6agJVXCtel1CXzpYxS+3XdPGjmkHBeIqY1NRBk279
- Click Save
BigCommerce requires an integrity hash for scripts running on the checkout page to meet PCI 4.0 6.4.3 security requirements. The hash above verifies the script hasn't been tampered with.
Customer experience
When before checkout verification is enabled:
- Customers shop and add items to cart normally
- When they proceed to checkout, the verification prompt appears
- They must complete ID verification before entering payment details
- Already-verified customers skip the verification step automatically
Frequently Asked Questions
Will this slow down checkout for all customers?
No. Real ID remembers verified customers. Returning customers who have already verified their ID will proceed directly to checkout without seeing the verification prompt again.
Can I require verification only for certain products or orders?
Yes! You can set up triggers based on order value, specific products, customer location, and more. Only orders matching your rules will require verification. See the Rules documentation for details.
What if a customer can't complete verification?
If a customer is unable to verify their ID, they won't be able to complete checkout. You can review failed verification attempts in your Real ID dashboard and contact the customer if needed.
Is this compatible with all BigCommerce themes?
Before checkout verification works with most BigCommerce themes. If you experience any display issues, please contact our support team.
Can customers save their cart and verify later?
Yes. If a customer leaves during verification, their cart is preserved. When they return and try to checkout again, they'll be prompted to complete verification.
Custom Trigger Scripts
For merchants who want custom trigger logic beyond the built-in options, you can create scripts that conditionally trigger ID verification using the Real ID JS SDK.
How Custom Triggers Work
- The Real ID SDK (Script 1) loads on checkout pages
- Your custom script (Script 2) evaluates conditions using BigCommerce Storefront APIs
- If conditions are met, your script calls
RealID.createFlow()to trigger verification
Setup
Script 1 - Add the Real ID SDK (you've already done this in Step 3 above):
- Script type: URL
- URL:
https://bc-flow.getverdict.com/assets/index.js - Pages: Checkout
Script 2 - Add your custom trigger script:
- In BigCommerce admin, go to Storefront > Script Manager
- Click Create a Script
- Fill in the following:
- Name: Real ID Custom Trigger
- Description: Custom ID verification trigger
- Location on page: Footer
- Select pages where script will be added: Checkout
- Script category: Essential
- Script type: Script
- Paste one of the example scripts below
- Click Save
BigCommerce uses a multi-step checkout where elements appear dynamically. The examples below include a waitForSelector helper function that waits for the "Place Order" button to appear before triggering verification.
Each example requires your BigCommerce store hash - a unique identifier for your store. You can find it in:
- Your BigCommerce admin URL:
https://store-{STORE_HASH}.mybigcommerce.com/manage/... - Example: If your URL is
store-abc123xyz.mybigcommerce.com, your store hash isabc123xyz
Replace YOUR_STORE_HASH in the examples below with your actual store hash.
Example 1: Verify All Checkouts
The simplest trigger - requires verification for every checkout.
<script>
// Helper: Wait for an element to appear in the DOM
function waitForSelector(selector, timeoutMs) {
timeoutMs = timeoutMs || 30000;
return new Promise(function(resolve) {
var existing = document.querySelector(selector);
if (existing) {
console.log('Real ID: Element ' + selector + ' already exists');
resolve(existing);
return;
}
console.log('Real ID: Waiting for element ' + selector);
var observer = new MutationObserver(function(mutations, obs) {
var element = document.querySelector(selector);
if (element) {
obs.disconnect();
console.log('Real ID: Element ' + selector + ' found');
resolve(element);
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
setTimeout(function() {
observer.disconnect();
console.log('Real ID: Timeout waiting for ' + selector);
resolve(null);
}, timeoutMs);
});
}
// Real ID - Verify all checkouts
(async function() {
var STORE_HASH = 'YOUR_STORE_HASH'; // Replace with your store hash
console.log('Real ID: Initializing verification for all checkouts');
// Wait for the Place Order button to appear
var placeOrderBtn = await waitForSelector('#checkout-payment-continue');
if (placeOrderBtn) {
console.log('Real ID: Triggering verification flow');
RealID.createFlow({
target: "#checkout-payment-continue",
mode: "modal",
shopName: STORE_HASH
});
} else {
console.log('Real ID: Place Order button not found, skipping verification');
}
})();
</script>
Example 2: Verify Orders Over a Certain Amount
Only trigger verification when cart total exceeds a threshold.
<script>
// Helper: Wait for an element to appear in the DOM
function waitForSelector(selector, timeoutMs) {
timeoutMs = timeoutMs || 30000;
return new Promise(function(resolve) {
var existing = document.querySelector(selector);
if (existing) { resolve(existing); return; }
var observer = new MutationObserver(function(mutations, obs) {
var element = document.querySelector(selector);
if (element) { obs.disconnect(); resolve(element); }
});
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(function() { observer.disconnect(); resolve(null); }, timeoutMs);
});
}
// Real ID - Verify orders over $100
(async function() {
var STORE_HASH = 'YOUR_STORE_HASH'; // Replace with your store hash
var MINIMUM_AMOUNT = 100; // Customize this value
console.log('Real ID: Checking cart total (minimum: $' + MINIMUM_AMOUNT + ')');
try {
var response = await fetch('/api/storefront/carts');
var carts = await response.json();
var cart = carts[0];
if (!cart) {
console.log('Real ID: No cart found');
return;
}
console.log('Real ID: Cart total is $' + cart.cartAmount);
if (cart.cartAmount < MINIMUM_AMOUNT) {
console.log('Real ID: Cart below threshold, skipping verification');
return;
}
console.log('Real ID: Cart exceeds threshold, triggering verification');
// Wait for the Place Order button
var placeOrderBtn = await waitForSelector('#checkout-payment-continue');
if (placeOrderBtn) {
RealID.createFlow({
target: "#checkout-payment-continue",
mode: "modal",
shopName: STORE_HASH
});
}
} catch (e) {
console.error('Real ID: Error checking cart', e);
}
})();
</script>
Example 3: Verify Orders to Specific US States
Only trigger verification for orders shipping to certain states.
<script>
// Helper: Wait for an element to appear in the DOM
function waitForSelector(selector, timeoutMs) {
timeoutMs = timeoutMs || 30000;
return new Promise(function(resolve) {
var existing = document.querySelector(selector);
if (existing) { resolve(existing); return; }
var observer = new MutationObserver(function(mutations, obs) {
var element = document.querySelector(selector);
if (element) { obs.disconnect(); resolve(element); }
});
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(function() { observer.disconnect(); resolve(null); }, timeoutMs);
});
}
// Real ID - Verify orders shipping to specific US states
(async function() {
var STORE_HASH = 'YOUR_STORE_HASH'; // Replace with your store hash
var REQUIRED_STATES = ['CA', 'NY', 'TX']; // Customize this list
console.log('Real ID: Checking shipping state (required: ' + REQUIRED_STATES.join(', ') + ')');
try {
var cartResponse = await fetch('/api/storefront/carts');
var carts = await cartResponse.json();
var cart = carts[0];
if (!cart) {
console.log('Real ID: No cart found');
return;
}
var checkoutResponse = await fetch('/api/storefront/checkouts/' + cart.id);
var checkout = await checkoutResponse.json();
var shippingAddress = checkout.consignments &&
checkout.consignments[0] &&
checkout.consignments[0].shippingAddress;
if (!shippingAddress) {
console.log('Real ID: No shipping address entered yet');
return;
}
console.log('Real ID: Shipping to ' + shippingAddress.stateOrProvinceCode + ', ' + shippingAddress.countryCode);
if (shippingAddress.countryCode !== 'US') {
console.log('Real ID: Non-US order, skipping verification');
return;
}
if (!REQUIRED_STATES.includes(shippingAddress.stateOrProvinceCode)) {
console.log('Real ID: State not in required list, skipping verification');
return;
}
console.log('Real ID: State matches, triggering verification');
// Wait for the Place Order button
var placeOrderBtn = await waitForSelector('#checkout-payment-continue');
if (placeOrderBtn) {
RealID.createFlow({
target: "#checkout-payment-continue",
mode: "modal",
shopName: STORE_HASH
});
}
} catch (e) {
console.error('Real ID: Error checking shipping address', e);
}
})();
</script>
This script runs once when the checkout page loads. For the shipping state check to work, the customer must have already entered their shipping address.
Example 4: Verify Orders with Specific Product Categories
Only trigger verification when the cart contains products from certain categories.
<script>
// Helper: Wait for an element to appear in the DOM
function waitForSelector(selector, timeoutMs) {
timeoutMs = timeoutMs || 30000;
return new Promise(function(resolve) {
var existing = document.querySelector(selector);
if (existing) { resolve(existing); return; }
var observer = new MutationObserver(function(mutations, obs) {
var element = document.querySelector(selector);
if (element) { obs.disconnect(); resolve(element); }
});
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(function() { observer.disconnect(); resolve(null); }, timeoutMs);
});
}
// Real ID - Verify orders containing products from specific categories
(async function() {
var STORE_HASH = 'YOUR_STORE_HASH'; // Replace with your store hash
var REQUIRED_CATEGORY_IDS = [23, 45, 67]; // Customize with your category IDs
console.log('Real ID: Checking product categories (required IDs: ' + REQUIRED_CATEGORY_IDS.join(', ') + ')');
try {
var cartResponse = await fetch('/api/storefront/carts');
var carts = await cartResponse.json();
var cart = carts[0];
if (!cart) {
console.log('Real ID: No cart found');
return;
}
var allItems = (cart.lineItems.physicalItems || [])
.concat(cart.lineItems.digitalItems || []);
var productIds = allItems.map(function(item) { return item.productId; });
if (productIds.length === 0) {
console.log('Real ID: No products in cart');
return;
}
console.log('Real ID: Checking categories for products: ' + productIds.join(', '));
// Check product categories via GraphQL
var query = '{ site { products(entityIds: [' + productIds.join(',') + '], first: 50) { edges { node { entityId categories { edges { node { entityId } } } } } } } }';
var gqlResponse = await fetch('/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: query })
});
var gqlData = await gqlResponse.json();
var products = gqlData.data && gqlData.data.site && gqlData.data.site.products && gqlData.data.site.products.edges || [];
var shouldTrigger = products.some(function(productEdge) {
var categories = productEdge.node.categories && productEdge.node.categories.edges || [];
return categories.some(function(catEdge) {
return REQUIRED_CATEGORY_IDS.includes(catEdge.node.entityId);
});
});
if (!shouldTrigger) {
console.log('Real ID: No products match required categories, skipping verification');
return;
}
console.log('Real ID: Found products in required categories, triggering verification');
// Wait for the Place Order button
var placeOrderBtn = await waitForSelector('#checkout-payment-continue');
if (placeOrderBtn) {
RealID.createFlow({
target: "#checkout-payment-continue",
mode: "modal",
shopName: STORE_HASH
});
}
} catch (e) {
console.error('Real ID: Error checking product categories', e);
}
})();
</script>
To find your category IDs, go to Products > Product Categories in your BigCommerce admin. Click on a category - the ID is shown in the URL (e.g., /manage/categories/23 means the ID is 23).
Example 5: Verify Products with Custom Field
Only trigger verification when the cart contains products that have a specific custom field set.
<script>
// Helper: Wait for an element to appear in the DOM
function waitForSelector(selector, timeoutMs) {
timeoutMs = timeoutMs || 30000;
return new Promise(function(resolve) {
var existing = document.querySelector(selector);
if (existing) { resolve(existing); return; }
var observer = new MutationObserver(function(mutations, obs) {
var element = document.querySelector(selector);
if (element) { obs.disconnect(); resolve(element); }
});
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(function() { observer.disconnect(); resolve(null); }, timeoutMs);
});
}
// Real ID - Verify orders with products that have "id_required" custom field
(async function() {
var STORE_HASH = 'YOUR_STORE_HASH'; // Replace with your store hash
var CUSTOM_FIELD_NAME = 'id_required'; // Customize field name if needed
console.log('Real ID: Checking for products with custom field "' + CUSTOM_FIELD_NAME + '"');
try {
var cartResponse = await fetch('/api/storefront/carts');
var carts = await cartResponse.json();
var cart = carts[0];
if (!cart) {
console.log('Real ID: No cart found');
return;
}
var allItems = (cart.lineItems.physicalItems || [])
.concat(cart.lineItems.digitalItems || []);
var productIds = allItems.map(function(item) { return item.productId; });
if (productIds.length === 0) {
console.log('Real ID: No products in cart');
return;
}
console.log('Real ID: Checking custom fields for products: ' + productIds.join(', '));
// Check product custom fields via GraphQL
var query = '{ site { products(entityIds: [' + productIds.join(',') + '], first: 50) { edges { node { entityId customFields { edges { node { name value } } } } } } } }';
var gqlResponse = await fetch('/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: query })
});
var gqlData = await gqlResponse.json();
var products = gqlData.data && gqlData.data.site && gqlData.data.site.products && gqlData.data.site.products.edges || [];
var shouldTrigger = products.some(function(productEdge) {
var customFields = productEdge.node.customFields && productEdge.node.customFields.edges || [];
return customFields.some(function(fieldEdge) {
return fieldEdge.node.name === CUSTOM_FIELD_NAME &&
fieldEdge.node.value.toLowerCase() === 'true';
});
});
if (!shouldTrigger) {
console.log('Real ID: No products have "' + CUSTOM_FIELD_NAME + '" = true, skipping verification');
return;
}
console.log('Real ID: Found products requiring ID verification, triggering flow');
// Wait for the Place Order button
var placeOrderBtn = await waitForSelector('#checkout-payment-continue');
if (placeOrderBtn) {
RealID.createFlow({
target: "#checkout-payment-continue",
mode: "modal",
shopName: STORE_HASH
});
}
} catch (e) {
console.error('Real ID: Error checking product custom fields', e);
}
})();
</script>
To add a custom field to a product:
- Go to Products > View in BigCommerce admin
- Edit the product
- Scroll to Custom Fields
- Add a field with name
id_requiredand valuetrue - Save the product
Example 6: Specific State AND Product Category (Combined)
Trigger verification only when BOTH conditions are met: shipping to California AND cart contains products from specific categories.
<script>
// Helper: Wait for an element to appear in the DOM
function waitForSelector(selector, timeoutMs) {
timeoutMs = timeoutMs || 30000;
return new Promise(function(resolve) {
var existing = document.querySelector(selector);
if (existing) { resolve(existing); return; }
var observer = new MutationObserver(function(mutations, obs) {
var element = document.querySelector(selector);
if (element) { obs.disconnect(); resolve(element); }
});
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(function() { observer.disconnect(); resolve(null); }, timeoutMs);
});
}
// Real ID - Verify orders shipping to CA with products in specific categories
(async function() {
var STORE_HASH = 'YOUR_STORE_HASH'; // Replace with your store hash
var REQUIRED_STATE = 'CA'; // State code to require verification
var REQUIRED_CATEGORY_IDS = [23, 45, 67]; // Customize with your category IDs
console.log('Real ID: Checking for state=' + REQUIRED_STATE + ' AND categories=' + REQUIRED_CATEGORY_IDS.join(', '));
try {
// Step 1: Check shipping state
var cartResponse = await fetch('/api/storefront/carts');
var carts = await cartResponse.json();
var cart = carts[0];
if (!cart) {
console.log('Real ID: No cart found');
return;
}
var checkoutResponse = await fetch('/api/storefront/checkouts/' + cart.id);
var checkout = await checkoutResponse.json();
var shippingAddress = checkout.consignments &&
checkout.consignments[0] &&
checkout.consignments[0].shippingAddress;
if (!shippingAddress) {
console.log('Real ID: No shipping address entered yet');
return;
}
console.log('Real ID: Shipping to ' + shippingAddress.stateOrProvinceCode + ', ' + shippingAddress.countryCode);
var stateMatches = shippingAddress.countryCode === 'US' &&
shippingAddress.stateOrProvinceCode === REQUIRED_STATE;
if (!stateMatches) {
console.log('Real ID: State does not match ' + REQUIRED_STATE + ', skipping verification');
return;
}
console.log('Real ID: State matches ' + REQUIRED_STATE + ', checking product categories...');
// Step 2: Check product categories
var allItems = (cart.lineItems.physicalItems || [])
.concat(cart.lineItems.digitalItems || []);
var productIds = allItems.map(function(item) { return item.productId; });
if (productIds.length === 0) {
console.log('Real ID: No products in cart');
return;
}
var query = '{ site { products(entityIds: [' + productIds.join(',') + '], first: 50) { edges { node { entityId categories { edges { node { entityId } } } } } } } }';
var gqlResponse = await fetch('/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: query })
});
var gqlData = await gqlResponse.json();
var products = gqlData.data && gqlData.data.site && gqlData.data.site.products && gqlData.data.site.products.edges || [];
var categoryMatches = products.some(function(productEdge) {
var categories = productEdge.node.categories && productEdge.node.categories.edges || [];
return categories.some(function(catEdge) {
return REQUIRED_CATEGORY_IDS.includes(catEdge.node.entityId);
});
});
if (!categoryMatches) {
console.log('Real ID: No products in required categories, skipping verification');
return;
}
console.log('Real ID: Both conditions met! Triggering verification');
// Wait for the Place Order button
var placeOrderBtn = await waitForSelector('#checkout-payment-continue');
if (placeOrderBtn) {
RealID.createFlow({
target: "#checkout-payment-continue",
mode: "modal",
shopName: STORE_HASH
});
}
} catch (e) {
console.error('Real ID: Error checking conditions', e);
}
})();
</script>
Example 7: Specific State AND Custom Field (Combined)
Trigger verification only when BOTH conditions are met: shipping to California AND cart contains products with the id_verification_required custom field.
<script>
// Helper: Wait for an element to appear in the DOM
function waitForSelector(selector, timeoutMs) {
timeoutMs = timeoutMs || 30000;
return new Promise(function(resolve) {
var existing = document.querySelector(selector);
if (existing) { resolve(existing); return; }
var observer = new MutationObserver(function(mutations, obs) {
var element = document.querySelector(selector);
if (element) { obs.disconnect(); resolve(element); }
});
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(function() { observer.disconnect(); resolve(null); }, timeoutMs);
});
}
// Real ID - Verify orders shipping to CA with products that have "id_verification_required" custom field
(async function() {
var STORE_HASH = 'YOUR_STORE_HASH'; // Replace with your store hash
var REQUIRED_STATE = 'CA'; // State code to require verification
var CUSTOM_FIELD_NAME = 'id_verification_required'; // Custom field name
console.log('Real ID: Checking for state=' + REQUIRED_STATE + ' AND custom field="' + CUSTOM_FIELD_NAME + '"');
try {
// Step 1: Check shipping state
var cartResponse = await fetch('/api/storefront/carts');
var carts = await cartResponse.json();
var cart = carts[0];
if (!cart) {
console.log('Real ID: No cart found');
return;
}
var checkoutResponse = await fetch('/api/storefront/checkouts/' + cart.id);
var checkout = await checkoutResponse.json();
var shippingAddress = checkout.consignments &&
checkout.consignments[0] &&
checkout.consignments[0].shippingAddress;
if (!shippingAddress) {
console.log('Real ID: No shipping address entered yet');
return;
}
console.log('Real ID: Shipping to ' + shippingAddress.stateOrProvinceCode + ', ' + shippingAddress.countryCode);
var stateMatches = shippingAddress.countryCode === 'US' &&
shippingAddress.stateOrProvinceCode === REQUIRED_STATE;
if (!stateMatches) {
console.log('Real ID: State does not match ' + REQUIRED_STATE + ', skipping verification');
return;
}
console.log('Real ID: State matches ' + REQUIRED_STATE + ', checking product custom fields...');
// Step 2: Check product custom fields
var allItems = (cart.lineItems.physicalItems || [])
.concat(cart.lineItems.digitalItems || []);
var productIds = allItems.map(function(item) { return item.productId; });
if (productIds.length === 0) {
console.log('Real ID: No products in cart');
return;
}
var query = '{ site { products(entityIds: [' + productIds.join(',') + '], first: 50) { edges { node { entityId customFields { edges { node { name value } } } } } } } }';
var gqlResponse = await fetch('/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: query })
});
var gqlData = await gqlResponse.json();
var products = gqlData.data && gqlData.data.site && gqlData.data.site.products && gqlData.data.site.products.edges || [];
var customFieldMatches = products.some(function(productEdge) {
var customFields = productEdge.node.customFields && productEdge.node.customFields.edges || [];
return customFields.some(function(fieldEdge) {
return fieldEdge.node.name === CUSTOM_FIELD_NAME &&
fieldEdge.node.value.toLowerCase() === 'true';
});
});
if (!customFieldMatches) {
console.log('Real ID: No products have "' + CUSTOM_FIELD_NAME + '" = true, skipping verification');
return;
}
console.log('Real ID: Both conditions met! Triggering verification');
// Wait for the Place Order button
var placeOrderBtn = await waitForSelector('#checkout-payment-continue');
if (placeOrderBtn) {
RealID.createFlow({
target: "#checkout-payment-continue",
mode: "modal",
shopName: STORE_HASH
});
}
} catch (e) {
console.error('Real ID: Error checking conditions', e);
}
})();
</script>
These examples demonstrate AND logic - both conditions must be true. You can adapt this pattern to combine any conditions:
- Change
REQUIRED_STATEto any US state code (e.g., 'NY', 'TX') - Add multiple states by changing the check to
['CA', 'NY'].includes(shippingAddress.stateOrProvinceCode) - Combine with cart total checks by adding
cart.cartAmount >= MINIMUM_AMOUNT
Learn More
For more information about the Real ID JS SDK, including theming options and prepopulating customer data, see our JavaScript SDK documentation.