Velo Tutorial: Using reCAPTCHA to Protect Data Submission

Visit the Velo by Wix website to onboard and continue learning.

This article explains how to use Google's reCAPTCHA tool to protect data submission from spammers and hackers. We'll show you how to use reCAPTCHA with Velo to protect data sent from a custom input form to a database collection.

You can adapt this tutorial to protect other restricted operations with reCAPTCHA, such as logging in to a private area of your site or displaying private content.

Notes

  • You can protect Wix Forms with reCAPTCHA without using any code.
  • The reCAPTCHA element does not offer protection for data submission performed via a dataset. To protect data submission with reCAPTCHA, you must use code to perform the data operation (for example, insert() or save()).

Typical CAPTCHA Lifecycle

Before adding a reCAPTCHA element to your site, it's important to understand the typical CAPTCHA validation lifecycle:

  1. A button that triggers data insertion is disabled, pending CAPTCHA verification.
  2. A site visitor enters data in the input elements and completes the CAPTCHA challenge. One of the following occurs:
    • Verification: The CAPTCHA is verified and a CAPTCHA token is generated. Enable the disabled button.
    • Error: reCAPTCHA loses connection with the CAPTCHA provider. Instruct the site visitor to try again later. Return to Step 1.
  3. The submit button is enabled. One of the following occurs:
    • Click: The site visitor clicks the button, triggering a backend function that checks whether the generated token is valid (authorized).
    • Timeout: The site visitor did not click within 120 seconds of token generation, causing the token to expire. When timeout occurs, the reCAPTCHA automatically resets and displays a message asking the site visitor to redo the challenge. Disable the submit button. Return to Step 1.
  4. One of the following occurs:
    • Authorization: CAPTCHA token is valid. Perform the data insertion in the backend function. Reset the reCAPTCHA element for future operations.
    • Error: Token fails authorization or the data insertion fails. Reset the reCAPTCHA element and ask the visitor to redo the challenge. Return to Step 1.

Important To ensure complete protection, you must include backend authorization as a mandatory step of the CAPTCHA validation lifecycle.

Summary

In our site we added the following:

  • Input elements, a reCAPTCHA element, a submit button, and a text element to display messages.
  • A database collection to store the data entered in the input elements.

Then we added code to do the following:

  1. After a site visitor enters data in the input elements and successfully completes the CAPTCHA challenge, enable the initially disabled submit button.
  2. When a site visitor clicks the submit button, authorize the generated CAPTCHA token (check whether it's valid). 
  3. If the token is valid, insert the input data in the database collection and display a success message.
  4. If verification or authorization fail, or the CAPTCHA token times out, reset the reCAPTCHA element and display an error message.

Step 1: Set Up the Site

We added the following elements to our Home page:

  • Input elements for name and email
  • reCAPTCHA
  • A submit button
  • Text for success and error messages

We added a web method called submitHandler.web.js to our backend code. We also added a database collection called MailingList to store the names and email addresses of site visitors who sign up.

We made sure the submit button was initially disabled by clearing the Enabled checkbox in the Properties & Events panel. We also made sure the text element for success and error messages was initially hidden by selecting Hidden in the Properties & Events panel.

Step 2: Import the processSubmission Function from the Backend

On our Home page, we start by importing the backend function we use to authorize the CAPTCHA token and perform the data insertion. See Step 7 to learn more about the backend function.

Copy
1
import { processSubmission } from 'backend/submitHandler.web';

Note To see all the code for this example in a single block, scroll down to the end of the tutorial.

Step 3: Create the onVerified Event Handler

Site visitors enter their contact details in the input elements and complete the CAPTCHA challenge. In the onReady function on our Home page, we added an event handler that runs when the CAPTCHA challenge is successfully completed and the CAPTCHA is verified.

Copy
1
$w("#captcha").onVerified(() => {
2
$w("#messageText").hide();
3
$w("#submitButton").enable();
4
})

Understanding the Code

Line 2: Hide any previous success or error messages.
Line 3: Enable the previously disabled submit button so the site visitor can complete the submission.

Note When the CAPTCHA is verified, a CAPTCHA token (used for authorization) is automatically generated.

Step 4: Create the Submit Button onClick Event Handler

In the onReady function on our Home page, we added an event handler that runs when a site visitor clicks the submit button.

Copy
1
$w("#submitButton").onClick(() => {
2
3
let submitRequestData = {
4
"token": $w("#captcha").token,
5
"data": {
6
"name": $w("#nameInput").value,
7
"email": $w("#emailInput").value
8
}
9
}
10
11
processSubmission(submitRequestData)
12
.then( () => {
13
$w("#captcha").reset();
14
$w("#submitButton").disable();
15
$w("#messageText").text = "Data successfully submitted";
16
$w("#messageText").show();
17
})
18
.catch( () => {
19
$w("#captcha").reset();
20
$w("#submitButton").disable();
21
$w("#messageText").text = "Something went wrong. Redo the reCAPTCHA challenge.";
22
$w("#messageText").show();
23
})
24
})

Understanding the Code

Lines 3-7: Prepare the submit request data. The request data includes the CAPTCHA token generated when the captcha was verified, and the data entered in the input elements.
Line 11: Call the processSubmission backend function with the prepared submit request data. The processSubmission function tries to authorize the token. If backend authorization is successful, the data is inserted into the MailingList collection.
Lines 12-16: If authorization and data insertion are successful, display a success message and restart the CAPTCHA lifecycle for future submissions by resetting the reCAPTCHA element and disabling the submit button.
Lines 18-22: If authorization or data insertion fail in the backend, restart the CAPTCHA lifecycle by resetting the reCAPTCHA, disabling the submit button, and displaying an error message instructing the site visitor to try again.

Step 5: Create the CAPTCHA onError Event Handler

If the reCAPTCHA element loses connection with the provider when the site visitor attempts to complete the CAPTCHA challenge, the reCAPTCHA element automatically resets and the onError event handler displays a temporary message asking the site visitor to try again later.

Copy
1
$w("#captcha").onError(() => {
2
$w("#messageText").text = "The reCAPTCHA element lost connection with the CAPTCHA provider. Try again later.";
3
$w("#messageText").show()
4
.then(() => {
5
$w("#messageText").hide("fade", {"delay": 10000});
6
} );
7
})

Understanding the Code

Line 2: Set the message text to an error message that instructs the site visitor to try again later.
Line 3: Show the message.
Line 5: Hide the message after 10 seconds.

Step 6: Create the reCAPTCHA onTimeout Event Handler

If the submit does not occur within 120 seconds of completing the CAPTCHA challenge, the generated token expires. When the token expires, the reCAPTCHA element automatically resets and displays a message asking the site visitor to redo the challenge. We just need to disable the submit button in the onTimeout event handler.

Copy
1
$w("#captcha").onTimeout(() => {
2
$w("#submitButton").disable();
3
})

Step 7: Create the processSubmission Function in the Backend

The processSubmission backend function checks whether the CAPTCHA token is valid. If authorization is successful (token is valid), the input data is inserted into the MailingList collection. If authorization fails, an exception is thrown that is handled on the client side (see Line 18 of Step 4).

Copy
1
import { Permissions, webMethod } from 'wix-web-module';
2
import wixCaptcha from 'wix-captcha-backend';
3
import wixData from 'wix-data';
4
5
export const processSubmission = webMethod(Permissions.Anyone, (submitRequestData) => {
6
return wixCaptcha.authorize(submitRequestData.token)
7
.then(() => {
8
return wixData.insert("MailingList", submitRequestData.data);
9
});
10
});

Understanding the Code

Lines 1-2: Import the permissions and webMethod from the 'wix-web-module'. Then import the modules we need to work with CAPTCHA in the backend and with data.
Line 4: The processSubmission function takes the web method and its permissions, and a submitRequestData parameter, including the generated CAPTCHA token and the input data to insert into the collection.
Line 5: Call the authorize() function with the CAPTCHA token. authorize() checks the validity of the token and if the token is valid, returns a Promise that resolves to a success message.
Lines 6-7: If authorization succeeds, insert the data into the MailingList collection.

Learn More

Example Code

Here is the complete code for this example:

Client-Side Code

Copy
1
import { processSubmission } from 'backend/submitHandler.web';
2
3
$w.onReady(function () {
4
5
$w("#captcha").onVerified(() => {
6
$w("#messageText").hide();
7
$w("#submitButton").enable();
8
})
9
10
$w("#submitButton").onClick(() => {
11
let submitRequestData = {
12
"token": $w("#captcha").token,
13
"data": {
14
"name": $w("#nameInput").value,
15
"email": $w("#emailInput").value
16
}
17
}
18
processSubmission(submitRequestData)
19
.then( () => {
20
$w("#captcha").reset();
21
$w("#submitButton").disable();
22
$w("#messageText").text = "Data successfully submitted";
23
$w("#messageText").show();
24
})
25
.catch( () => {
26
$w("#captcha").reset();
27
$w("#submitButton").disable();
28
$w("#messageText").text = "Something went wrong. Redo the captcha challenge.";
29
$w("#messageText").show();
30
})
31
})
32
33
$w("#captcha").onError(() => {
34
$w("#messageText").text = "The reCAPTCHA element lost connection with the CAPTCHA provider. Try again later.";
35
$w("#messageText").show()
36
.then(() => {
37
$w("#messageText").hide("fade", {"delay": 10000});
38
} );
39
})
40
41
$w("#captcha").onTimeout(() => {
42
$w("#submitButton").disable();
43
})
44
});

Backend Code

Copy
1
import { Permissions, webMethod } from 'wix-web-module';
2
import wixCaptcha from 'wix-captcha-backend';
3
import wixData from 'wix-data';
4
5
export const processSubmission = webMethod(Permissions.Anyone, (submitRequestData) => {
6
return wixCaptcha.authorize(submitRequestData.token)
7
.then(() => {
8
return wixData.insert("MailingList", submitRequestData.data);
9
});
10
});
Was this helpful?
Yes
No