diff --git a/en/extras/formit/formit.ajax.md b/en/extras/formit/formit.ajax.md
new file mode 100644
index 00000000..9ce31b42
--- /dev/null
+++ b/en/extras/formit/formit.ajax.md
@@ -0,0 +1,220 @@
+---
+title: "AJAX Form Submission"
+---
+
+## AJAX Form Submission
+
+FormIt can submit forms via AJAX without a full page reload. Validation errors, success messages, and redirects are all handled client-side through a built-in JavaScript library.
+
+## Setup
+
+To enable AJAX support, set the `formit.frontend_js` system setting:
+
+| Setting | Value |
+|---|---|
+| `formit.frontend_js` | `js/web/formit.js` |
+
+This registers the FormIt JavaScript file and configures the AJAX endpoint URL automatically.
+
+## How It Works
+
+1. The FormIt snippet stores its configuration (hooks, validation rules, etc.) in a server-side session/cache and outputs an MD5 hash as the `[[!+fi.ajaxToken]]` placeholder.
+2. You place this hash into a `data-formit-ajax-token` attribute on your `
+```
+
+> **Note:** The `action` attribute is kept as a fallback for when JavaScript is disabled. In AJAX mode the form is submitted to `action.php` instead.
+
+### Data Attributes Reference
+
+| Attribute | Element | Description |
+|---|---|---|
+| `data-formit-ajax-token` | `` | Activates AJAX mode. Value must be `[[!+fi.ajaxToken]]`. |
+| `data-formit-error="fieldname"` | `` | Displays the validation error for a specific field. The JS fills `innerHTML` with the error text. |
+| `data-formit-validation-error-message` | `` | Displays the general validation error message (equivalent of `[[!+fi.validation_error_message]]`). |
+| `data-formit-success-message` | `
` | Displays the success message (from `&successMessage` property). |
+| `data-formit-error-message` | `
` | Displays hooks error message (from `[[!+fi.error_message]]`). |
+
+All `data-formit-error` and message elements are cleared before each submission.
+
+## JavaScript API
+
+### Auto-initialization
+
+Forms with the `data-formit-ajax-token` attribute are automatically initialized on `DOMContentLoaded`. No extra JavaScript is needed for basic usage.
+
+## JavaScript Events
+
+The form element dispatches `CustomEvent`s that you can listen to with `addEventListener`. All events bubble.
+
+| Event | Cancelable | `event.detail` | Description |
+|---|---|---|---|
+| `formit:beforesubmit` | Yes | `{ form }` | Fired before the AJAX request. Call `event.preventDefault()` to cancel. |
+| `formit:success` | No | `{ data }` | Fired on successful submission. |
+| `formit:error` | No | `{ data }` | Fired when validation fails. |
+| `formit:complete` | No | `{}` | Fired after every request (success or error). |
+| `formit:redirect` | Yes | `{ url }` | Fired before redirect. Call `event.preventDefault()` to cancel. |
+
+Example:
+
+``` javascript
+document.getElementById('my-form').addEventListener('formit:success', function (e) {
+ alert('Thank you! Your form has been submitted.');
+});
+```
+
+## Redirect Handling
+
+When the `redirect` hook is used, AJAX mode does **not** perform a server-side redirect. Instead:
+
+1. The server returns a `redirect_url` field in the JSON response.
+2. The JS dispatches a cancelable `formit:redirect` event.
+3. If not canceled (via `event.preventDefault()` or `onRedirect` returning `false`), the JS sets `window.location.href` to the redirect URL.
+
+This lets you intercept the redirect and handle it your own way (e.g., load content via AJAX, show a thank-you message in place, etc.).
+
+## CSS Loading State
+
+During an AJAX request:
+
+- The `formit-loading` CSS class is added to the `
` element.
+- All `[type="submit"]` buttons inside the form are set to `disabled`.
+
+Both are removed when the request completes.
+
+You can use this to style a loading indicator:
+
+``` css
+.formit-loading {
+ opacity: 0.6;
+ pointer-events: none;
+}
+```
+
+## JSON Response Structure
+
+For advanced use cases, the AJAX endpoint returns a JSON object with this structure:
+
+``` json
+{
+ "success": true,
+ "message": "Success message or error message",
+ "redirect_url": "https://example.com/thank-you",
+ "placeholders": {
+ "error.name": "This field is required. ",
+ "error.email": "Please enter a valid email. ",
+ "validation_error_message": "A form validation error occurred.
",
+ "successMessage": "Form submitted successfully."
+ }
+}
+```
+
+| Field | Type | Description |
+|---|---|---|
+| `success` | Boolean | `true` if the form passed all validation and hooks succeeded. |
+| `message` | String | Success or error message. |
+| `redirect_url` | String | Present only when the `redirect` hook is active. |
+| `placeholders` | Object | All FormIt placeholders (with the `fi.` prefix stripped). Field errors are under `error.fieldname`. |
+
+## See Also
+
+1. [FormIt.Hooks](extras/formit/formit.hooks)
+ 1. [FormIt.Hooks.email](extras/formit/formit.hooks/email)
+ 2. [FormIt.Hooks.FormItAutoResponder](extras/formit/formit.hooks/formitautoresponder)
+ 3. [FormIt.Hooks.math](extras/formit/formit.hooks/math)
+ 4. [FormIt.Hooks.recaptcha](extras/formit/formit.hooks/recaptcha)
+ 5. [FormIt.Hooks.redirect](extras/formit/formit.hooks/redirect)
+ 6. [FormIt.Hooks.spam](extras/formit/formit.hooks/spam)
+ 7. [FormIt.Hooks.FormItSaveForm](extras/formit/formit.hooks/formitsaveform)
+2. [FormIt.Validators](extras/formit/formit.validators)
+3. [FormIt.FormItRetriever](extras/formit/formit.formitretriever)
+4. [FormIt.Tutorials and Examples](extras/formit/formit.tutorials-and-examples)
+ 1. [FormIt.Examples.Custom Hook](extras/formit/formit.tutorials-and-examples/examples.custom-hook)
+ 2. [FormIt.Examples.Simple Contact Page](extras/formit/formit.tutorials-and-examples/examples.simple-contact-page)
+ 3. [FormIt.Handling Selects, Checkboxes and Radios](extras/formit/formit.tutorials-and-examples/handling-selects,-checkboxes-and-radios)
+ 4. [FormIt.Using a Blank NoSpam Field](extras/formit/formit.tutorials-and-examples/using-a-blank-nospam-field)
+5. [FormIt.FormItCountryOptions](extras/formit/formit.formitcountryoptions)
+6. [FormIt.FormItStateOptions](extras/formit/formit.formitstateoptions)
diff --git a/en/extras/formit/formit.hooks/recaptcha.md b/en/extras/formit/formit.hooks/recaptcha.md
index 5442c0e6..410fe25d 100644
--- a/en/extras/formit/formit.hooks/recaptcha.md
+++ b/en/extras/formit/formit.hooks/recaptcha.md
@@ -6,35 +6,47 @@ _old_uri: "revo/formit/formit.hooks/formit.hooks.recaptcha"
## The recaptcha hook
-The recaptcha hook will enable reCaptcha support for FormIt forms.
+The recaptcha hook enables reCAPTCHA v3 support for FormIt forms. reCAPTCHA v3 works invisibly in the background — no checkbox or challenge is shown to the user. Google returns a score (0.0–1.0) indicating how likely the submission is from a human; submissions below the minimum score are rejected.
+
+## Requirements
+
+- A reCAPTCHA v3 site key and secret key from [https://www.google.com/recaptcha](https://www.google.com/recaptcha)
+- FormIt's frontend JS enabled via the `formit.frontend_js` system setting (set to `js/web/formit.js`)
## Usage
-First off, add "recaptcha" to your &hooks parameter in your FormIt call. Then you'll need to include the following placeholders in your form:
+Add `recaptcha` to your `&hooks` parameter:
``` php
+[[!FormIt?
+ &hooks=`recaptcha,email`
+]]
+```
+
+Add the reCAPTCHA placeholder and the error placeholder to your form:
+
+``` html
[[+formit.recaptcha_html]]
[[!+fi.error.recaptcha]]
```
-The first placeholder is where the reCaptcha form will be rendered; the 2nd is the error message (if any) for reCaptcha.
+`[[+formit.recaptcha_html]]` renders two hidden fields (`g-recaptcha-response` and `g-recaptcha-action`) required for v3. FormIt automatically loads the Google reCAPTCHA script and executes the token request on form submit.
-Finally, you'll need to setup your reCaptcha private and public keys in System Settings. The settings available for reCaptcha are:
+## System Settings
-| Name | Description |
-| ------------------------------ | -------------------------------------------------------------------- |
-| formit.recaptcha\_public\_key | Your reCaptcha public key. |
-| formit.recaptcha\_private\_key | Your reCaptcha private key. |
-| formit.recaptcha\_use\_ssl | Whether or not to use SSL for reCaptcha requests. Defaults to false. |
+Configure your keys in **System Settings** under the `formit_recaptcha` area:
-## Available Properties
+| Setting | Description | Default |
+| --- | --- | --- |
+| `formit.recaptcha_site_key` | Your reCAPTCHA v3 site key (public). | |
+| `formit.recaptcha_secret_key` | Your reCAPTCHA v3 secret key (private). | |
+| `formit.recaptcha_min_score` | Minimum score to accept a submission (0.0–1.0). | `0.5` |
-The reCaptcha hook has a few extra configuration options:
+## Available Properties
-| Name | Description | Default |
-| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
-| recaptchaJs | A JSON object to pass into the RecaptchaOptions var, which configures the reCaptcha widget. See the official reCaptcha docs for more information. | {} |
-| recaptchaTheme | The recaptcha theme to use. | clean |
+| Name | Description | Default |
+| --- | --- | --- |
+| `recaptchaAction` | Action name sent to Google with the token request. Visible in the reCAPTCHA admin dashboard. | `submit` |
## See Also
diff --git a/en/extras/formit/formit.tutorials-and-examples/examples.simple-contact-page.md b/en/extras/formit/formit.tutorials-and-examples/examples.simple-contact-page.md
index 14acbd74..caf7a783 100644
--- a/en/extras/formit/formit.tutorials-and-examples/examples.simple-contact-page.md
+++ b/en/extras/formit/formit.tutorials-and-examples/examples.simple-contact-page.md
@@ -4,25 +4,21 @@ _old_id: "851"
_old_uri: "revo/formit/formit.tutorials-and-examples/formit.examples.simple-contact-page"
---
-Here we will give a simple example of Contact page.
+Here we will give a simple example of a Contact page.
-We presume that you have already installed Formit component via [Package Management](developing-in-modx/advanced-development/package-management "Package Management") and got acquainted Formit [How To Use](/extras/formit#how-to-use "How To Use") section.
+We presume that you have already installed FormIt via [Package Management](developing-in-modx/advanced-development/package-management "Package Management") and read the [How To Use](/extras/formit#how-to-use "How To Use") section.
-This example Contact form will validate input data, send an email and finally redirect to Resource with ID 123.
+This example form validates input data, sends an email, and redirects to a resource with ID 123.
-Validation process (see how it works [here](extras/formit/formit.validators), in short - each hook executes some kind of logic, if successful - transfers processing to the next hook ) in this example does the following: also strip tags from the message, validate the email as a real email address, and make sure none of the fields are blank. All this is specified in &validate parameter.
+Validation (see [FormIt Validators](extras/formit/formit.validators)) in this example strips tags from the message, validates the email address, and requires all fields to be filled in.
-And finally, we want [reCaptcha](https://www.google.com/recaptcha/about/) support. We've already setup our public and private keys for reCaptcha via the following System Settings:
+It also uses [reCAPTCHA v3](https://www.google.com/recaptcha/about/) support. Set up your keys in System Settings:
-- formit.recaptcha\_public\_key
-- formit.recaptcha\_private\_key
+- `formit.recaptcha_site_key`
+- `formit.recaptcha_secret_key`
## Snippet Tag
-You can call this snippet anywhere: inside template, chunk, page content body, or even call programmatically via [runSnippet](extending-modx/modx-class/reference/modx.runsnippet).
-
-There is only one condition - Formit must be launched on the page where data from Contact form below will be sent (see "action" field value).
-
``` php
[[!FormIt?
&hooks=`recaptcha,email,redirect`
@@ -40,75 +36,70 @@ There is only one condition - Formit must be launched on the page where data fro
]]
```
-> Please make sure that emailFrom is set to `[[++emailsender]]`, otherwise the email field of the form will be taken. This is now causing issues as most hosters no longer send mails with a `from` from unknown domains.
+> Make sure `emailFrom` is set to `[[++emailsender]]`, otherwise the form's email field will be used as the sender — most hosting providers will reject or block such emails.
## Contact Form
-This HTML code must be called on website page where you want to see Contact Form. "Action" field value points to the page where the snippet call is located, in our case we call it on the same page, so we use [~ tag](building-sites/tag-syntax/common#default-resource-content-field-tags) to generate a link for the current page.
-
``` html
Contact Form
-[[!+fi.validation_error_message:notempty=`[[!+fi.validation_error_message]]
`]]
-
+ [[!+fi.validation_error_message]]
+ [[!+fi.successMessage]]
+ [[!+fi.error_message]]
+
-
- Name:
- [[!+fi.error.name]]
-
-
-
-
- Email:
- [[!+fi.error.email]]
-
-
-
-
- Subject:
- [[!+fi.error.subject]]
-
-
-
-
- Message:
- [[!+fi.error.text]]
-
- [[!+fi.text]]
-
-
- Numbers:[[+fi.error.numbers]]
-
+
+ Name:
+
+ [[!+fi.error.name]]
+
+
+
+ Email:
+
+ [[!+fi.error.email]]
+
+
+
+ Subject:
+
+ [[!+fi.error.subject]]
+
+
+
+ Message:
+ [[!+fi.text]]
+ [[!+fi.error.text]]
+
+
+
+ Numbers:
+
Select an option...
One
Two
Three
-
+ [[!+fi.error.numbers]]
+
-
- Colors:[[!+fi.error.colors]]
+
+
+
+ [[+formit.recaptcha_html]]
+ [[!+fi.error.recaptcha]]
+