- Checks at submission
- CAPTCHA per form
- Limits, lists and temporary bans
- Log, dashboard and test
- Covered forms, rules and API
- Options and exemptions
- Multistore, languages and license
- A contact form flooded with messages
- Registrations creating ghost accounts
- A newsletter losing its subscribers
- Product reviews buried under spam
- A business module with its own form
- An agency managing several stores
- Should I remove the CAPTCHA already in my theme?
- Can the module block an order?
- My form is custom. Is it compatible?
- Do I need an account with a CAPTCHA provider?
- Will my customers behind a shared address be blocked?
- Where is the data stored, and for how long?
- What happens if the license expires?
- Does the module guarantee zero spam?
Form anti-spam for PrestaShop: CAPTCHA and bot blocking
The contact form receives messages about crypto, dubious links or โSEO servicesโ written in broken English. Registrations create accounts with implausible addresses. The newsletter list fills with people who never asked to receive it. And yet a CAPTCHA was enabled. That is the problem: a CAPTCHA protects the display of the form, not its processing. A bot that sends a POST request straight to the contact, registration or newsletter controller never loads the widget and drops its message.
Form Anti-Spam: CAPTCHA and Bot Blocking puts a server-side check in front of every protected form. The submission is examined at the start of the request, before PrestaShop or the form's module processes it: a refused submission creates no account, sends no message, subscribes no one and publishes no review. The module works with no third-party account or key by default; an external CAPTCHA remains a choice, form by form.
This guide explains what the module does, how to install it, how to complete a first configuration and how to use it day to day.
Highlights:
- Protection at submission: signed token, trap field, minimum fill time and duplicates, checked before the form is processed
- Limits that hold: sliding window per IP address and per e-mail, temporary bans, block and allow lists
- The CAPTCHA you choose per form: reCAPTCHA v2/v3, Cloudflare Turnstile, hCaptcha or Friendly Captcha, with a key test
- Visibility: observation mode, 30-day dashboard, refusal log with reasons and a โTest my protectionโ tool
- Your forms: the seven native forms, per-controller rules and a PHP API for third-party modules
Discover the module and its plans
Overview
Why a CAPTCHA is not enough
A classic CAPTCHA runs in the visitor's browser. It asks for an action, verifies a token or computes a score, then lets the form go. A bot that knows the controller URL does not need a browser: it sends the expected fields straight to the server. The widget is never loaded, the token is never requested, and the message arrives. This is especially true of contact, registration and newsletter forms, whose controllers are public and easy to identify.
Free modules often cover one provider and a few forms. They offer no rate limit, no log and no way to check that a theme or a third-party module actually displays the protection fields. When spam comes back, all that remains is the message in the inbox, with no explanation.
What the module does
The module hooks into the very start of request processing, once the customer, the store and the language are known, but before the form is processed. It recognises a protected form submission by its controller and its submit field, then applies its checks in a fixed order: exemptions, IP block list, active ban, trap field, token and minimum time, IP rate limit, e-mail checks (block list, rate limit, disposable domain, MX), duplicates, then the CAPTCHA when the form has one.
The first failing check decides the answer. A refused submission is stopped before the native code: nothing is created, nothing is sent, nothing is published. The visitor sees an explicit message, or the generic message you wrote, and the values they typed stay in the form. Refused attempts are counted and logged with their reason.
What the module does not do
The module never filters the order itself: not the cart, not the payment, not the confirmation, not the addresses. The checkout customer form can be protected, with deliberately generous thresholds and no minimum time, so that a sale is never lost. It does not replace a web application firewall, does not block a whole page and does not promise zero spam: a human spammer can still fill in a form correctly. Finally, it helps you limit the data you collect, but it does not certify your GDPR compliance and does not replace legal advice.
The dashboard: allowed and blocked submissions, block rate and a 30-day chart.
Features
Checks at submission
Each protected form receives a signed token, an invisible trap field and a minimum fill time.
- Signed token: built from the form, the store and the time; it expires after 12 hours by default. A form left open too long is refreshed at the first interaction, without the visitor reloading the page.
- Trap field: hidden off-screen, never reachable by keyboard, with a name drawn at random at installation. A bot that fills in every field fills this one too.
- Minimum time: from 0 to 30 seconds depending on the form. Defaults range from 1 second for sign-in to 3 seconds for contact, registration and reviews; checkout stays at 0.
- Duplicates: identical content sent again within the configured window is refused. Only accepted submissions record a fingerprint, so a corrected retry goes through.
- Safety net: while a form has never sent the module fields, a missing token is logged without blocking. The dashboard flags the situation and the test tool checks the page. Once a valid submission has been seen, a missing token is refused.
CAPTCHA per form
When you want an extra verification, choose a provider for a given form:
- Google reCAPTCHA v2, checkbox or invisible
- Google reCAPTCHA v3, with an adjustable score threshold
- Cloudflare Turnstile
- hCaptcha, in normal, compact or invisible mode
- Friendly Captcha
You enter your own keys, the module never prints them back, and a test button checks that they are accepted and that the domain is allowed. By default, the provider script is loaded only on pages that contain a form protected by that provider, at the first interaction with the form: no page without a form pays for the script.
Two settings frame the behaviour:
- If the provider is unreachable, you choose to let the submission through, logged as skipped, or to refuse it.
- Consent can be requested before the script loads, with the Cookies GDPR module or another tool exposing a consent API. Without consent, the form stays protected by the native checks, or shows a message if you chose to ask for consent.
External CAPTCHAs have their own terms and privacy policy. It is up to you to mention them in your policy and to choose the appropriate consent.
Limits, lists and temporary bans
Every submission counts in a sliding window per IP address and per e-mail address, with thresholds set per form. Beyond the threshold, the submission is refused and a strike is recorded. After three strikes in 24 hours, the address is banned for one hour on every protected form; these values are configurable, and a ban can be lifted from the back office. Browsing always stays possible: the module never blocks a page.
Lists accept IPv4 and IPv6 addresses, CIDR ranges, e-mail addresses, domains and wildcard patterns. You can add an entry by hand, import a CSV and export the lists. An address present in both the block list and the allow list is allowed: the allow list wins.
The module also supplies a disposable domain list, which you can extend or trim, and an optional cached MX check to verify that a domain can receive mail.
Log, dashboard and test
The dashboard summarises allowed, blocked, observed, skipped and exempt submissions, the block rate, a 30-day chart, the detail per form and per reason, and the most blocked addresses.
The blocked-attempt log gives, for each refusal, the form, the reason, the date, the masked or hashed address and the e-mail domain. You can block an address or a range, allow an address, block a domain or lift a ban in one click, then export the log to CSV. Entries are purged automatically after 30 days by default.
The Test my protection tool reads the form page as a visitor, checks that the fields, the token and the script are present, sends a direct submission without fields to confirm that it is refused, and checks the keys of the chosen provider. The result stays displayed until the next run.
Every refusal is explained (trap field, sent too fast, block list) and can be handled in one click.
Covered forms, rules and API
The module protects the seven native PrestaShop forms: contact, account creation, sign-in, checkout customer form, forgotten password, newsletter and product reviews. Account creation during checkout is included, with the thresholds of the customer form.
For forms from other modules, two options:
- A per-controller rule, with the form name, the target page or controller, the field that marks the submission and, if needed, its value, the e-mail field, the content fields for duplicates and the expected answer format (page or JSON). You can create up to 20 rules per store. A ready-made rule covers the product availability alerts of ps_emailalerts.
- The PHP API, documented in the module README, so that a module calls the protection fields and the checks from its own code. The form then appears in the list with the name of the calling module.
Checkout targets are refused: the cart, payment, confirmation, addresses and payment controllers cannot be filtered by a rule.
A mode, a CAPTCHA and limits for every form, including rules for other modules.
Options and exemptions
E-mail verification at registration is off by default. When enabled, registration on the account creation page receives a signed, expiring link; the account stays pending until the link is confirmed, can ask for a new link, and cannot sign in before confirmation. The store never holds an account when it does not send e-mails or when sending fails, and a pending account stays freely accessible if the module is disabled or the license expires.
Employees signed in to the back office, search engine crawlers verified by DNS, the customer groups you exempt, addresses on the allow list, signed-in customers depending on the form and scheduled tasks are not checked. These exemptions are set in the configuration, except allowed addresses, which are managed in the lists.
Multistore, languages and license
Settings, forms, rules, log and statistics belong to each store; list entries can belong to one store or be shared. The interface and messages exist in French, English, Spanish, Italian and Polish. The Classic and Hummingbird themes work without modification, no theme file is written and no override is created. Uninstall keeps the data by default, with an option to delete it.
The module works with a valid WePresta license. Without a valid license it disables itself: forms are no longer checked, no CAPTCHA is shown and nothing is logged, so spam can reach them again. Your settings, lists and log are kept, and the module is enabled again as soon as the license is valid.
Installation
- Check the requirements: PrestaShop 1.7.8, 8.0+ or 9.0+, PHP 7.4 or newer.
- Install the module from the Module Manager with the supplied ZIP archive, or copy its folder into
modules/and install it from the module list. - At installation, the seven native forms are created for every store in Protected mode, with no external CAPTCHA and their default thresholds. The disposable domain list is added and the module tables are created.
- Open the module's Configure page and activate your WePresta license. Until the license is valid, the module stays disabled and forms are not checked.
- Schedule the daily maintenance task, using the URL shown in the configuration or the supplied command line. It purges the log, the counters and expired bans.
- Check your employees' permissions: view, manage and data are three separate rights, checked on the server.
First configuration
After installation, do not switch every form to protection immediately. The module ships with reasonable thresholds, but your store has its own habits.
- Activate the license and check that the module state reads โEnabledโ on the dashboard.
- Switch the forms to observation with โObserve allโ. Every check runs, nothing is refused, and the log records what would have been blocked.
- Let it run for a few days, then open the log and the dashboard: the reasons tell you whether blocking would target bots or customers. Pay particular attention to addresses shared by several visitors, such as a company or a mobile carrier.
- Test each form page with โTest my protectionโ. The test confirms that the fields, the token and the script are present, and checks that a direct submission without fields is refused.
- Switch to protection form by form, starting with contact and newsletter, then registration, sign-in and reviews. Leave checkout on its generous thresholds.
- Add a CAPTCHA only if needed, on an exposed form, after entering your keys and checking the test. Start with an invisible variant to avoid adding friction.
- Set up the lists: add your partners' and monitoring tools' addresses to the allow list before tightening the limits.
- Check the scheduled task: without it, the log and counters are not purged and expired bans stay in place.
- Update your privacy policy if you enable an external CAPTCHA, and name the provider you chose.
Day-to-day use
The dashboard is the overview: allowed and blocked submissions, block rate, most targeted forms, most frequent reasons and most blocked addresses. A spike on one form is immediately visible.
The blocked-attempt log is the action view. For each refusal, you can block the address or its range, allow the address, block the e-mail domain or lift a ban. These actions are immediate and apply to every protected form in the store. The log can be exported to CSV for deeper analysis and purged according to the retention period you chose.
The Forms page shows, for each form, its mode, CAPTCHA provider, minimum time, limits, last submission date and fields-seen state. A form that has never seen the module fields is flagged: it often means a theme or a module draws the form differently, and the safety net then prevents lost messages while you fix it.
The Lists page groups the IP lists, e-mail lists, disposable domains and active bans. CSV import accepts a UTF-8 file with the value and note columns, up to 10,000 lines and 2 MB; the report lists added, already present and refused lines.
The Accounts to verify page appears when e-mail verification is on or an account is pending. It lets you resend a link, confirm or delete a pending account.
The Action log page records employee actions: settings changed, forms edited, lists imported, bans lifted. Useful when several people administer the store.
Use cases
A contact form flooded with messages
The contact form receives identical messages every night, often with a link. The theme's CAPTCHA changes nothing: bots post directly. The module refuses submissions without a token, catches the trap field and blocks the addresses that insist. The log shows the reason for each refusal and lets you block a whole range in one click.
Registrations creating ghost accounts
Automated registrations pollute the customer list and distort statistics. The module applies the minimum time, the per-IP and per-e-mail limits, the disposable domain list and, if needed, the MX check. E-mail verification at registration prevents an unconfirmed account from signing in.
A newsletter losing its subscribers
Mass newsletter sign-ups can trigger complaints and damage deliverability. The per-address and per-e-mail limits, duplicate detection and block lists reduce the volume, while the allow list protects your partners' addresses.
Product reviews buried under spam
The review form is exposed and bots know it. The module protects it like the others, with a default minimum time of 3 seconds and a 60-minute duplicate window. The module script disables the empty trap field so that the review form keeps working with its native script.
A business module with its own form
A quote, callback or availability alert module has its own form and controller. A per-controller rule protects it without touching its code; otherwise, the PHP API lets the module call the checks from its own code.
An agency managing several stores
Each store keeps its settings, forms, lists, log and statistics. An agency can apply the same policy without mixing customer data, and check store by store what is actually blocked.
Requirements and limits
- PrestaShop 1.7.8, 8.0+ and 9.0+, on the Classic and Hummingbird themes; PHP 7.4 or newer.
- No paid account is required: native protection works without a key or a subscription. CAPTCHA providers are optional and need their own keys; Cloudflare Turnstile needs a Cloudflare account.
- A daily scheduled task is recommended to purge the log, the counters and expired bans; maintenance can also run on the first visit to the module back office or the first checked submission of the day.
- CAPTCHA verifications, the MX check and crawler verification use outgoing network calls. Without network access, the behaviour chosen for the provider applies and a failed MX check lets the submission through.
- The module cannot promise zero spam: it sharply reduces automated submissions and gives you the means to see and adjust. A human spammer can still get through.
- A limit that is too strict can hinder visitors behind the same address. Use observation mode, allow lists and exemptions before tightening the thresholds.
- The module helps limit the data you collect, but it does not certify GDPR compliance and does not replace legal advice. External CAPTCHAs have their own terms and privacy policy, which you must mention in yours.
FAQ
Should I remove the CAPTCHA already in my theme?
The module does not remove a CAPTCHA added by your theme. You can keep it, but avoid stacking two visible CAPTCHAs on the same form: it adds friction without benefit. If you configure a provider in the module, its script may add to the theme's; check the result on the storefront before enabling it.
Can the module block an order?
No. The module never filters the order itself: not the cart, not the payment, not the confirmation, not the addresses. Only the checkout customer form can be checked, with generous thresholds and no minimum time. Checkout targets are refused in rules.
My form is custom. Is it compatible?
Yes, in two ways. A per-controller rule describes the field that marks the submission and the expected answer format, without modifying the third-party module's code. The PHP API lets the third-party module call the protection fields and the checks from its own code. A form that does not go through an identifiable PrestaShop controller cannot be protected by a rule.
Do I need an account with a CAPTCHA provider?
No. The native checks, the token, the trap field, the minimum time, the limits and the lists work without any account. An account is needed only if you choose an external provider, and each provider has its own terms.
Will my customers behind a shared address be blocked?
An address shared by several visitors can reach the limit faster than an individual address. That is why observation mode, per-form thresholds and the allow list exist. Start by observing, review the submissions that would have been blocked, then adjust the limit or add the address to the allow list if needed.
Where is the data stored, and for how long?
In the module tables, on your server. The log keeps the form, the reason, the date, the masked address or a hashed fingerprint and the e-mail domain, never the full clear address by default. Entries are purged automatically after 30 days by default, with a configurable period. GDPR hooks allow export or erasure, and uninstall keeps the data unless you ask for deletion.
What happens if the license expires?
The module disables itself: forms are no longer checked, no CAPTCHA is shown and nothing is logged, so spam can reach them again. Your settings, lists and log are kept, and the module is enabled again as soon as the license is valid. The store stays accessible in every case.
Does the module guarantee zero spam?
No, and no module can promise that. It sharply reduces automated submissions by stopping requests that did not load the page or do not pass the checks, and it gives you the means to see what is blocked and adjust. A human spammer can still fill in a form correctly; the module replaces neither moderation nor your privacy policy.
Support
For any help, contact us from your WePresta customer area or by e-mail at mail@wepresta.shop, depending on the support option of your plan.
Changelog
Version 1.0.0
- Check every submission on the server before PrestaShop processes the form: signed token, trap field, minimum time and duplicates.
- Protect the seven native forms at installation with no third-party account or key: contact, account creation, sign-in, checkout, password, newsletter and reviews.
- Limit submissions per IP address and per e-mail address with a sliding window configurable per form, and temporarily ban addresses that insist.
- Manage block and allow lists for IPv4 and IPv6 addresses, CIDR ranges, e-mails, domains and wildcard patterns, with CSV import and export.
- Supply a disposable domain list and an optional cached MX check.
- Choose a CAPTCHA per form: reCAPTCHA v2/v3, Cloudflare Turnstile, hCaptcha or Friendly Captcha, with a key test and a defined behaviour when the provider is unreachable.
- Request consent before the provider script loads, with the Cookies GDPR module or a consent API.
- Observe submissions without refusing them, then switch protection on form by form.
- Track allowed, blocked, observed, skipped and exempt submissions, the block rate and a 30-day chart.
- Read the blocked-attempt log with reason, masked address and e-mail domain, act in one click and export to CSV.
- Test a form page with โTest my protectionโ: fields, token, script and a direct submission without fields.
- Add a per-controller rule for a form from another module, with a ready-made rule for ps_emailalerts, or use the PHP API.
- Optionally verify the e-mail at registration with a signed, expiring link, without holding an account when sending fails.
- Exempt employees, verified search engine crawlers, customer groups, allowed addresses, signed-in customers and scheduled tasks.
- Work in multistore, in French, English, Spanish, Italian and Polish, on the Classic and Hummingbird themes.
- Use the module on PrestaShop 1.7.8, 8.0+ and 9.0+ with PHP 7.4 minimum.