Spam bots love to create multiple accounts with the same phone number – or worse, real shoppers accidentally sign up twice. Either way, duplicate phone numbers muddy your data and complicate customer support.
The snippet below pre‑validates mobile numbers on the front‑end and double‑checks server‑side via AJAX, blocking duplicates before they ever hit your database.
🧩 The Code
1. PHP add to functions.php or a custom plugin
/**
* AJAX callback: Check if a phone number is already registered.
*/
add_action( 'wp_ajax_check_phone_registration', 'check_phone_registration' );
add_action( 'wp_ajax_nopriv_check_phone_registration', 'check_phone_registration' );
function check_phone_registration() {
// Strip non‑digits and sanitise.
$phone = preg_replace( '/[^\d]/', '', sanitize_text_field( $_POST['phone'] ) );
// Build variations so +61 and 0‑leading numbers count as the same.
$variations = [ $phone ];
if ( str_starts_with( $phone, '61' ) ) {
$variations[] = '0' . substr( $phone, 2 );
} elseif ( str_starts_with( $phone, '0' ) ) {
$variations[] = '61' . substr( $phone, 1 );
}
global $wpdb;
$found = false;
foreach ( $variations as $v ) {
$user_id = $wpdb->get_var(
$wpdb->prepare(
"SELECT user_id FROM {$wpdb->usermeta}
WHERE meta_key = 'billing_phone'
AND meta_value = %s
LIMIT 1",
$v
)
);
if ( $user_id ) {
$found = true;
break;
}
}
echo $found ? '1' : '0';
wp_die();
}
Tip: Localise your AJAX URL in a small enqueue function or via a snippets plugin:wp_localize_script( 'your-js-handle', 'ajaxData', [ 'url' => admin_url( 'admin-ajax.php' ) ] );
2. JavaScript (enqueue in your theme or via asset bundler)
jQuery(document).ready(function ($) { const phone = $('#billing_phone'); const isDupEl = $('#isRegisterPhone'); /* Hide errors as user types */ phone.on('input', () => { $('.register_phone_error, #billing_phone_error').hide(); }); /* Validate basic format (7‑15 digits) */ function validatePhone() { const digits = phone.val().replace(/\D/g, ''); const valid = digits.length >= 7 && digits.length <= 15; $('#billing_phone_error').toggle(!valid); return valid; } /* AJAX check for duplicates */ async function checkPhoneRegistered() { if (!validatePhone()) return false; const res = await $.post(ajaxData.url, { action: 'check_phone_registration', phone: phone.val() }); isDupEl.val(res); $('.register_phone_error').toggle(res === '1'); return res !== '1'; } /* Debounced duplicate check on input */ let timer; phone.on('input', () => { clearTimeout(timer); timer = setTimeout(checkPhoneRegistered, 500); }); /* Final check on blur / Next‑Step button */ phone.on('blur', checkPhoneRegistered); $('.next-step-btn a[data-current-step="2"]').on('click', async (e) => { if (!(await checkPhoneRegistered())) e.preventDefault(); }); });
📍 Where to Add This
PHP: functions.php of your (child) theme or a dedicated functionality plugin
JS: Enqueued via wp_enqueue_script() in your theme or injected using a plugin like Code Snippets
Remember: Always add scripts after jQuery and localise the ajaxData.url
variable as shown above.
🔍 How It Works
Front‑end:
- Masks/validates the number length and formatting in real time.
- Sends the value to
admin‑ajax.php
only after the user stops typing (500 ms debounce).
Back‑end:
- Strips non‑digit characters and builds Aussie‑friendly variants (
061…
,+61…
,0…
). - Checks
billing_phone
inwp_usermeta
. - Returns 1 if a match exists, 0 otherwise.
UX:
- Shows “Mobile Number already registered” instantly—no page reloads.
- Blocks progression/registration if the phone is taken or the format is bad.
✅ Why You’ll Love It
- Stops duplicate accounts that share the same mobile number.
- Cuts down on spam and bogus registrations.
- Saves customer‑service headaches when merging duplicates later.
🚀 Need Deeper WooCommerce Security & UX Tweaks?
EUX Digital Agency specialises in custom WooCommerce builds, performance tuning, and conversion‑focused UX enhancements—like this one. From one‑off tweaks to full‑scale integrations, we’ve got your back.
📞 Ready for a cleaner, faster store? Talk to us and see what we can do.