Add an Age‑Verification Gate (DOB) to an UltraCart StoreFront

Add an Age‑Verification Gate (DOB) to an UltraCart StoreFront

Overview

This tutorial shows how to add a simple, theme‑level age‑verification gate to your UltraCart StoreFront. Shoppers are prompted for their date of birth (DOB) and must meet a configurable age threshold (e.g., 18, 21). The collected DOB is stored in Custom Field 7 on the order (field name CustomField7) for later review and reporting.

Note: UltraCart does not provide a built‑in age‑verification feature. The approach below is a lightweight, client‑side solution appropriate for basic gating. If you need compliance‑grade verification (e.g., KBA, document checks), integrate a third‑party verification provider and record their result in a custom field.


What You’ll Need

  • Access to the StoreFront Visual Builder

  • Permission to edit the Footer area of your theme

  • Basic comfort copying/pasting code


1) Name Custom Field 7 (one‑time)

  1. In the UltraCart back office, navigate: Operations → Order Management → Custom Fields.

  2. Locate Custom Field 7 and label it clearly (e.g., “Customer DOB (YYYY‑MM‑DD)”).

  3. Save.

Tip: There are ten order custom fields available. Use consistent naming across stores/environments.


2) Add the Age Gate Script in the Visual Builder Footer

You’ll add a small script that:

  • Shows a full‑screen, centered modal asking for the shopper’s DOB.

  • Checks if the shopper meets your threshold (default 18; adjustable).

  • Stores DOB in localStorage to avoid re‑prompting on every page.

  • Blocks access if under‑age and redirects to /age-restricted.

  1. From the UltraCart back office, open your StoreFront host.

  2. Browse your store and click the Visual Builder editor.

  3. In Visual Builder, open the Footer section.

  4. Add an HTML element in the footer.

  5. Open the element’s editor and switch to Source mode by clicking the <> button (top‑left of the editor).

  6. Paste the script below and Save.

<!-- Simple Age Verification (DOB) — UltraCart Visual Builder Footer --> <script> (function () { // ------------------ CONFIG ------------------ var AGE_THRESHOLD = 18; // Adjust to 18, 19, 21, etc. var STORAGE_KEY = 'uc_birthdate'; // localStorage key (YYYY-MM-DD) var BLOCK_PATH = '/age-restricted'; // Page shown to underage visitors // -------------------------------------------- // Utilities function parseISODate(iso) { var p = (iso || '').split('-'); if (p.length !== 3) return null; var y = +p[0], m = +p[1] - 1, d = +p[2]; var dt = new Date(y, m, d); return isNaN(dt.getTime()) ? null : dt; } function calcAge(dob) { var t = new Date(); var age = t.getFullYear() - dob.getFullYear(); var m = t.getMonth() - dob.getMonth(); if (m < 0 || (m === 0 && t.getDate() < dob.getDate())) age--; return age; } // Inject CSS so the modal always appears centered and blocks the page var css = ` .uc-age-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.6); z-index: 2147483647; display: flex; align-items: center; justify-content: center; } .uc-age-modal { background: #fff; max-width: 420px; width: 92%; padding: 20px; border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,.25); font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial; text-align: center; } .uc-age-modal h2 { margin: 0 0 8px; font-size: 1.25rem; } .uc-age-modal p { margin: 0 0 12px; line-height: 1.4; } .uc-age-modal input, .uc-age-modal button { padding: 10px; border-radius: 8px; border: 1px solid #ccc; } .uc-age-modal input { width: 100%; } .uc-age-modal .primary { border: 0; margin-top: 10px; cursor: pointer; } .uc-age-error { color: #b30000; font-size: .9rem; margin-top: 8px; } `; var style = document.createElement('style'); style.textContent = css; document.head.appendChild(style); function setBodyScrollLocked(lock) { try { if (lock) { document.documentElement.style.overflow = 'hidden'; document.body.style.overflow = 'hidden'; } else { document.documentElement.style.overflow = ''; document.body.style.overflow = ''; } } catch (e) {} } function buildModal(denied) { var overlay = document.createElement('div'); overlay.className = 'uc-age-overlay'; overlay.setAttribute('role', 'dialog'); overlay.setAttribute('aria-modal', 'true'); overlay.innerHTML = '<div class="uc-age-modal" id="uc-age-modal">' + (denied ? '<h2>Access Restricted</h2>' + '<p>Sorry, you must meet the minimum age requirement to continue.</p>' + '<button class="primary" id="uc-age-leave">OK</button>' : '<h2>Please confirm your age</h2>' + '<p>Enter your date of birth to continue.</p>' + '<input id="uc-dob" type="date" max="">' + '<button class="primary" id="uc-age-continue">Continue</button>' + '<div class="uc-age-error" id="uc-age-error" style="display:none;"></div>' ) + '</div>'; document.body.appendChild(overlay); setBodyScrollLocked(true); if (!denied) { var dobInput = overlay.querySelector('#uc-dob'); var continueBtn = overlay.querySelector('#uc-age-continue'); var err = overlay.querySelector('#uc-age-error'); dobInput.max = new Date().toISOString().slice(0,10); dobInput.focus(); continueBtn.addEventListener('click', function(){ var iso = dobInput.value; // YYYY-MM-DD (browser-native) var dob = parseISODate(iso); if (!dob) { err.textContent = 'Please enter a valid date.'; err.style.display='block'; return; } if (calcAge(dob) < AGE_THRESHOLD) { document.body.removeChild(overlay); setBodyScrollLocked(false); buildModal(true); return; } try { localStorage.setItem(STORAGE_KEY, iso); } catch(e) {} document.body.removeChild(overlay); setBodyScrollLocked(false); }); } else { var leaveBtn = overlay.querySelector('#uc-age-leave'); leaveBtn.focus(); leaveBtn.addEventListener('click', function(){ if (BLOCK_PATH && BLOCK_PATH !== location.pathname) { location.href = BLOCK_PATH; } }); } } function runAgeGate() { var saved = null; try { saved = localStorage.getItem(STORAGE_KEY); } catch(e) {} if (!saved) { buildModal(false); return; } var dob = parseISODate(saved); if (!dob || calcAge(dob) < AGE_THRESHOLD) { buildModal(true); } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', runAgeGate); } else { runAgeGate(); } })(); </script>

Prerequisite: Always paste into the HTML element in Source mode (<>) to avoid WYSIWYG formatting issues.
Tip: Keep AGE_THRESHOLD and BLOCK_PATH at the top for easy changes later.


3) Create the /age‑restricted Page (Under‑Age Landing)

Shoppers who fail the check are redirected to /age-restricted. Create that page so the redirect works and communicates clearly.

  1. In Visual Builder, add a new page.

  2. Set the URL/slug to age-restricted.

  3. (Optional) Exclude the page from navigation menus.

  4. Add the following content (you can style it to match your brand):

Recommended copy:

Access Restricted
Our products and content are intended for customers [set your minimum age; e.g., 18+].

If you are under the required age, you may not access this section of our website.

If you believe you were sent here in error, please return to the home page and try again, or contact our support team.

  • Minimum age: 18 years (unless otherwise stated)

  • Why this page? We must comply with regulations and company policy that restrict access to age‑sensitive content.

Return to Home

Tip: You can include links to policies or help resources. If you change the threshold (e.g., 21+), update the copy accordingly.


4) Capture DOB into Order Custom Field 7 (field name CustomField7)

Add a hidden input to a checkout page (Contact or Payment page) and copy the saved DOB into it so it’s submitted with the order.

  1. In Visual Builder, open your checkout page template (e.g., Contact or Payment).

  2. Add this hidden field inside the checkout form:

<input type="hidden" id="uc-custom-field-7" name="CustomField7" value="">
  1. Below it, add this small script to copy the DOB from localStorage:

<script> (function(){ var STORAGE_KEY = 'uc_birthdate'; function setDOB() { try { var dob = localStorage.getItem(STORAGE_KEY); // YYYY-MM-DD var fld = document.getElementById('uc-custom-field-7') || document.querySelector('input[name="CustomField7"]'); if (dob && fld) { fld.value = dob; } } catch(e) {} } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', setDOB); } else { setDOB(); } })(); </script>

Warning: Do not rename name="CustomField7". UltraCart maps that to Order Custom Field 7.


5) Test the Flow

  1. Open the storefront in a fresh session (incognito or clear site data).

  2. Confirm the age modal appears immediately and blocks scrolling.

  3. Enter a DOB under the threshold → you should be redirected to /age-restricted.

  4. Enter a DOB meeting the threshold → the modal closes and you can browse.

  5. Place a test order and verify Custom Field 7 contains the DOB in YYYY‑MM‑DD format on the order.


Age-Verification.jpg

 

Expected Outcome

  • The modal appears centered on top of the page at load and blocks interaction until answered.

  • Under‑age visitors are redirected to /age‑restricted.

  • Qualified visitors continue browsing without repeated prompts (until they clear site data).

  • Orders include the DOB in Custom Field 7 for reporting/review.


Troubleshooting

  • Modal appears “at the bottom”
    Ensure the CSS injection is present (look for .uc-age-overlay { position: fixed; inset: 0; } and a very high z-index).

  • DOB not saving to the order
    Confirm the hidden field name is exactly CustomField7 and the copy script is present on the checkout page that submits.

  • Visitors can scroll the page behind the modal
    The script locks scrolling while the modal is open. If your theme overrides it, add body, html { overflow: hidden !important; } while the overlay exists.

  • Redirect page 404
    Make sure you created the page at the exact path /age-restricted and published it.

Warning: Client‑side checks can be bypassed. For regulated products (alcohol, vape, etc.), use a compliant verification provider and log the verification result server‑side.

Related Documentation