CheckoutOTP adds an email verification layer before customers reach the WooCommerce checkout. The buyer enters their email, receives a 6-digit code and confirms it. Only then can they complete the purchase.
With it you can:
| Component | Minimum | Tested on |
|---|---|---|
| WordPress | 7.1 | 7.1.2 |
| WooCommerce | 11.2 | 11.2.1 |
| PHP | 8.3 | 8.3 |
checkoutotp.zip package..zip file, click Install Now, then Activate.Verification happens on a page of your site that contains a shortcode. You only need one page for this.
[checkoutotp_form]
[checkoutotp_form] shortcode, the plugin always redirects to the most recent one (the last published or updated). The others will still show the form if visited directly, but they will never be the redirect target. To avoid confusion (for example, editing a page that is not the one in use), keep a single active page with the shortcode and leave the others as draft or in the trash.
In WooCommerce → CheckoutOTP → Settings review, at minimum:
[checkoutotp_form]).| Situation | Behavior |
|---|---|
| First checkout after installing the plugin (administrators, existing customers, newly registered accounts) | Everyone verifies once, with no exceptions. There is no automatic bypass for being logged in or for having an older account. |
| Customer with an account, already verified once | Verified permanently (user meta). Future purchases do not ask for the code again. |
| Guest customer | A signed cookie is stored (7 days, or 30 if they check "remember me"). Returning within that period, they stay verified. |
If email delivery fails, Emergency Mode temporarily disables verification so you do not lose sales. Use it only as a one-off fix and disable it as soon as possible.
Everything is managed from WooCommerce → CheckoutOTP. The panel has these tabs:
| Tab | What it is for |
|---|---|
| ⚙️ Settings | All configuration options (see section 7). |
| 📋 Setup Instructions | Quick start guide. |
| 📊 Statistics | Metrics: codes sent, successful verifications, failed attempts, blocks. |
| 🛡️ API Security | Protection against bots and REST API abuse. |
| 📜 History | Last 50 security events (sends, verifications, failures, blocks). |
| 🚫 Blocked Emails | Temporarily blocked emails, with a button to unblock them manually. |
| Option | Default | What it does |
|---|---|---|
| OTP Expiry Time | 15 min | How long the code is valid (1–60). |
| Maximum Failed Attempts | 5 | Failures allowed per code before it is invalidated (3–20). |
| Email Block Threshold | 10 | Accumulated failures per email (across codes) before it is blocked (3–50). |
| Email Block Duration | 60 min | How long an email stays blocked (5–1440 min). |
| 🚨 Emergency Mode | No | Temporarily disables verification (emergencies). |
| 🌐 Site Behind Proxy/CDN | No | Enable if your site is behind Cloudflare or a proxy/CDN, to detect the visitor's real IP. |
Hides express payment buttons (PayPal, Google Pay, Apple Pay, Stripe…) from customers who are not yet verified, so they cannot skip verification.
| Option | Default | What it does |
|---|---|---|
| 🔒 Strict Mode | No | Hides express payment buttons using generic CSS patterns (more aggressive). |
| Custom CSS Selectors | — | Extra CSS selectors from your theme/plugins (one per line) to hide specific buttons. |
| Option | Default | What it does |
|---|---|---|
| Admin Notification Recipients | — | Emails that receive the alerts (you can add several). |
| Notify When User is Blocked | No | Notifies when an email is blocked after repeated failures. |
| Notify on Multiple Failed Attempts | No | Notifies when there are several failed attempts. |
| Option | Default | What it does |
|---|---|---|
| Maximum Orders Per Hour | 5 | Order limit per hour per IP/email (1–50). |
| Block Bot User-Agents | No | Blocks requests from known bots by their User-Agent. |
| Notify on API Abuse | No | Notifies on REST API abuse. |
| Notify on Suspicious Orders | No | Notifies when an order is flagged as suspicious. |
| Option | What it does |
|---|---|
| Custom Disposable Email Domains | Additional temporary email domains you want to reject (one per line). They are added to the built-in list of 32 domains; they do not replace it. |
| Custom Suspicious User-Agents | Additional bot signatures (one per line). |
| Custom Suspicious Names | Suspicious names (e.g. "test", "asdf") that trigger detection. |
| Enable Regex Patterns | Treats the above lists as regular expressions (advanced). |
tempmail.com, guerrillamail.com, 10minutemail.com, throwaway.email, mailinator.com, maildrop.cc, temp-mail.org, fakeinbox.com, trashmail.com, yopmail.com, getnada.com, mailnesia.com, sharklasers.com, guerrillamail.info, grr.la, guerrillamail.biz, spam4.me, mailcatch.com, emailondeck.com, mohmal.com, mintemail.com, mytrashmail.com, tempr.email, disposablemail.com, throwawaymail.com, spamgourmet.com, mailexpire.com, tempinbox.com, dispostable.com, getairmail.com, mailnator.com and tempail.com.
The Custom Disposable Email Domains field adds domains to this list, never replaces it.
| Option | Default | What it does |
|---|---|---|
| Auto Purge Logs | Yes | Automatically deletes old records. |
| Log Retention Period | 30 days | How many days records are kept (7–365). |
Customize the look of the verification form:
Header Background Color Header Text Color Button Background Color Button Text ColorThe OTP code is sent as a WooCommerce email, so it appears in WooCommerce → Settings → Emails under the name CheckoutOTP. From there you can change the subject, heading and footer, and even disable it.
The plugin includes two templates:
templates/emails/checkoutotp-otp.php — HTML version.templates/emails/plain/checkoutotp-otp.php — plain text version.your-theme/woocommerce/emails/checkoutotp-otp.php
(for the plain text version, your-theme/woocommerce/emails/plain/checkoutotp-otp.php). WordPress will use your copy instead of the plugin's.
Compatible with the WooCommerce shortcode checkout.
Compatible with the block checkout (Store API), including locking the email field.
Compatible with High-Performance Order Storage.
Protection for PayPal Express and other express buttons.
HttpOnly/SameSite=Strict. The verified email is never printed in the HTML of cached pages.
.pot template so you can translate it into any other language. The base language (source code) is English.
wp_mail(). If your server is not properly configured, install an SMTP plugin (WP Mail SMTP, Post SMTP, etc.) and test it.Enable the 🌐 Site Behind Proxy/CDN option. Only if your site is actually behind Cloudflare or a proxy/CDN.
Go to the 🚫 Blocked Emails tab and click Unblock on their row. Blocks also expire on their own according to the configured duration.
It means that order was created without a recorded verification (for example, a manual order created by the administrator, or created before installing the plugin). This is the correct behavior.
Yes. Verification, email locking and server-side validation work on both classic and block checkout.
Yes. Guests verify the same way, using a signed cookie.
No. Everyone (administrators, existing customers, newly registered accounts) verifies only once on their next checkout. After that, they are remembered (account: permanently; guest: 7 or 30-day cookie). To force a new verification, a guest only needs to wait for the cookie to expire; on an account, you would need to remove the user's verification mark (advanced).
Yes, any page containing the [checkoutotp_form] shortcode. The plugin detects it automatically.
The plugin always redirects to the most recent one. The others still show the form if visited directly, but they are not the redirect target. Recommendation: use a single active page with the shortcode and leave the others as draft or trash.
Each code allows a limited number of attempts. In addition, the plugin counts failures per email and temporarily blocks the address once the configured threshold is exceeded.
No. It only acts on the checkout and verification pages and adds no heavy queries to the rest of the site.
.pot template to add more languages.CheckoutOTP keeps its data in your own WordPress database, so you stay in control of it. This is what it handles:
If you have questions or issues, open a ticket in our support center including the plugin version, the WordPress/WooCommerce version and a description of the problem.