Is there any way you can use Wix Code to prevent duplicate contacts (same email) for my custom registration page?
top of page
Important forum update
This forum is migrating to one unified Wix community forum starting July 26th, and will be read-only during the process.
Wishlist Page is the official platform for requesting new features. You can vote, comment, and track the status of the requested features.
bottom of page
I believe that the answers above only show how to search for duplicates, but they do so after the member is already signed up as they use wixUsers.currentuser. The point here is to avoid signing up the users. Also, there's no need for a custom database, as the email is stored in the members database.
This is how I solved it:
Search for existing email in backend (might make more sense to put this in a hook, but the "add hook" interface does not provide a pre-insert hook for the membersData. I'm not sure whether there's a reason and whether it's possible)
// Filename: backend/reg.jsw (web modules need to have a .jsw extension) import wixUsers from 'wix-users-backend'; import wixData from 'wix-data'; function searchForSignupDuplicateEmails(emailToCheck) { let options = { "suppressAuth": true, }; return wixData.query("Members/PrivateMembersData") .eq("loginEmail", emailToCheck) .find(options) .then((results) => { return results.items.length; }) .catch((err) => { return Promise.reject(err); }); } export function doRegistration(email, password, userName) { let tryNameLowerCase = userName.toLowerCase(); return searchForSignupDuplicateEmails(email) .then((emailDupeCheckResult) => { if (emailDupeCheckResult > 0) { return Promise.reject("This email is already in use"); } }) // else //no duplicate email or username found, proceed to do registration .then(() => { return wixUsers.register(email, password, { "contactInfo": { "emails": emails, "labels": labels } }) }) .catch((err) => { return { "succeeded": false, "returnMessage": err }; }); }
And here's code to process that reply and display error messages in the lightbox. Note the names of the $w entities which are likely not the same as yours, and you need to replace with yours. Also, I added error messages in the lightbox which are hidden by default, and only get shown when relevant ($w('#emailUsedErrorText').show() and $w('#errorText').show())
import wixUsers from 'wix-users'; import wixLocation from "wix-location"; import { doRegistration } from 'backend/reg'; import wixWindow from 'wix-window'; //you might not need some of these imports $w.onReady(function () { $w('#submit').onClick(() => { doRegistration($w('#email').value, $w('#password').value, $w('#inputUserName').value) .then((result) => { if (result.succeeded === true) { wixLocation.to("/after-signup-location"); } else { if (result.succeeded === false) { if (result.returnMessage === "This email is already in use") { $w('#emailUsedErrorText').show(); } else { $w('#errorText').show(); } } else { $w('#errorText').show(); } } }) .catch((err) => { $w('#errorText').show(); }); }); });
Hello, I have built a custom registration page as outlined here: https://support.totallycodable.com/en/article/custom-registration-for-site-login. It works as designed for brand new people and email addresses, however I am having a hard time with duplicate contact entries if someone enters an existing email address.
If a potential member enters an email address that is already in the site contacts and clicks submit, the lightbox stays up for that person as though nothing has happened but the contact is inserted into the wix contacts function anyway, creating a duplicate contact with the same email address and first/last name. It does not however create another site member, which is good.
My biggest concern is the potential member who stays stuck on the custom registration page rather than getting taken to the next location as outlined in the code. Is there a way to insert error messages into this custom registration flow? And, if so, how can I use the code outlined earlier in this thread to make that happen? Does that go inside the lightbox code or in the back-end? Please note, I already have a data.js file in the backend as outlined here to prevent duplicates on profile update: https://codequeen.wixsite.com/membership-dashboard. I am using this create/update profile flow once the user has an account on the site, and this is working well also.
For reference, my code from the custom registration lightbox is as follows:
import wixUsers from 'wix-users'; import wixWindow from 'wix-window'; import wixLocation from 'wix-location'; import wixData from 'wix-data'; $w.onReady(function () { $w("#registerButton").onClick( (event) => { let email = $w("#email").value; let password = $w("#password").value; let first = $w("#firstName").value; let last = $w("#lastName").value; wixUsers.register(email, password, { contactInfo: { "firstName": first, "lastName": last } } ) .then( (result) => { let resultStatus = result.status; wixWindow.lightbox.close(); wixLocation.to("/join-wrcra-2"); } ); } ); }); Thank you!
Hio Brett:
find() will return an array of items that it gets from your .eq() query.
You should test the res.totalCount to see if it is greater than 0 to determine if you have an existing record better yet you should test greater than 1 also as that would be a coding error [;-)] and you would need to figure out how you let duplicates in in the first place.
So I've proposed some changes below that use the Promises from these calls more effectively. By returning a function call that returns a Promise you can cascade .then() calls at the same level in your code and terminate the string with a catch for exceptions. You can then use the exception catch for dealing with all errors so when you have a logic error you simply throw and error (exception) which terminates the code flow and jumps you to the catch.
import wixData from 'wix-data'; let user = wixUsers.currentUser; user.getEmail() .then( (email) => { let userEmail = email; // "user@something.com" // ******* Return the query find() and handle the then at the same level // as getEmail. Then use catch foone catch for all errors return wixData.query('contactInfo') .eq('#email', userEmail) .find(); }) .then((res) => { if(res.totalCount > 1) { // Internal Error more than one entry exists throw Error('Internal Error - more than one entry exists'); } else if (res.totalCount === 1) { throw Error('Duplicate user found, returning'); } //insert to collection here (no duplicate found) return wixData.insert("contactInfo",userEmail); }) .catch((error) => { //below is error messages to show $w('#error').show(); $w('#errorBig').show(); $w('#errorText').show(); $w('#errorBubble').show(); console.log(error); } );
Hope this is helpful. At a minimum you need to check the totalCount :-)
Hello Brett,
Try following this guide on doing this here: https://www.wix.com/code/home/forum/community-discussion/search-for-duplicate-entires
What may be the problem is that #email is not a field in your database. Go to your collection, click view properties of the email field, and get the fieldValue. This is what should be there instead of #email.
Best,
Majd
So, I put the code in, but the message does not work. Here is my code:
import wixData from 'wix-data'; let user = wixUsers.currentUser; user.getEmail() .then( (email) => { let userEmail = email; // "user@something.com" wixData.query('contactInfo') .eq('#email', userEmail) .find() .then((res) => { if(res) { console.log('Duplicate user found, returning'); //below is error messages to show $w('#error').show(); $w('#erroBig').show(); $w('#errorText').show(); $w('#errorBubble').show(); } else { wixData.insert("contactInfo",userEmail) } //insert to collection here (no duplicate found) }) } );
Brett,
It would look like this:
PS. Make sure to change .eq('emailField', userEmail) --> the emailField value here to your actual database field value.
import wixUsers from 'wix-users'; let user = wixUsers.currentUser; user.getEmail() .then( (email) => { let userEmail = email; // "user@something.com" wixData.query('YourCollectionName') .eq('emailField', userEmail) .find() .then((res) => { if(res) { console.log('Duplicate user found, returning'); //below is error messages to show $w('#error').show(); $w('#errorText').show(); } //insert to collection here (no duplicate found) }) } );
Hope this helps,
Majd
Thanks for the help, Majd and Mustafa. The detection works, but I just need help with showing an error message. I believe it might just be the brackets.
Here is what I have. It says I have an error on the last line.
let user = wixUsers.currentUser; user.getEmail() .then( (email) => { let userEmail = email; // "user@something.com" wixData.query('contactInfo') .eq('#email', userEmail) .find() .then((res) => { if(res) { return console.log('Duplicate user found, returning'); //add error message to show or redirect here if ('Duplicate user found, returning') { $w('#error').show(); $w('#errorText').show(); } //insert to collection here (no duplicate found) } } );
Hi Brett,
Adding to what Majd said, it would be a good idea to put a Hook before insert. Take a look HERE to see how it works. Best, Mustafa
Hello Brett,
Yea here is how to do it:
1. Get current user email
2. Query collection you are storing all the contacts in for that email
3. If query returns something prevent registration(Redirect to another page, show error message, etc..)
4. If query did not return something, insert into collection normally
Here is a template of how to do it with code:
import wixUsers from 'wix-users'; // ... let user = wixUsers.currentUser; user.getEmail() .then( (email) => { let userEmail = email; // "user@something.com" wixData.query('YourCollectionName') .eq('emailField', userEmail) .find() .then((res) => { if(res) { return console.log('Duplicate user found, returning'); //add error message to show or redirect here } //insert to collection here (no duplicate found) }) } );
Hope this helps,
Majd