CheckoutOTP

Email verification with a one-time code (OTP) before WooCommerce checkout. Stop fraud, fake orders and bots.

WordPress 7.1+ WooCommerce 11.2+ HPOS WooCommerce Blocks PHP 8.3+
Version: 1.3.0 Author: Innovedia Pro

1. Introduction

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:

Key idea Verification happens before checkout: the plugin redirects the customer to a verification page and, once the code is confirmed, sends them back to checkout with their email fixed and locked.

2. Requirements

ComponentMinimumTested on
WordPress7.17.1.2
WooCommerce11.211.2.1
PHP8.38.3

3. Installation

  1. Download the checkoutotp.zip package.
  2. In WordPress go to Plugins → Add New → Upload Plugin.
  3. Select the .zip file, click Install Now, then Activate.
  4. On activation, the plugin automatically creates its tables and default settings.
Recommendation After activating, go to WooCommerce → CheckoutOTP to review the settings before opening your store to the public.

4. Initial Setup

Verification happens on a page of your site that contains a shortcode. You only need one page for this.

Step 1 — Create the verification page

  1. Go to Pages → Add New.
  2. Give it a title, for example Order Verification.
  3. In the content, add this shortcode:
[checkoutotp_form]
  1. Publish the page.
Note The plugin automatically detects the page containing the shortcode and redirects unverified customers there. You do not need to configure any URL.
Use only one verification page If there are two or more published pages with the [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.

Step 2 — Set the basic values

In WooCommerce → CheckoutOTP → Settings review, at minimum:

Step 3 — Test

  1. In an incognito window, add a product to the cart and go to checkout.
  2. You should be redirected to the verification page.
  3. Enter your email, receive the code and confirm it.
  4. Once verified, you return to checkout with the email locked and can complete the purchase.

5. How It Works

The customer journey

  1. The customer adds products to the cart and tries to enter checkout.
  2. The plugin redirects them to the verification page ([checkoutotp_form]).
  3. They enter their email and click send → they receive a 6-digit code by email.
  4. They enter the code. If correct, they are verified.
  5. They return to checkout: their email appears fixed and read-only.
  6. They complete the purchase.

When verification is remembered

SituationBehavior
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 onceVerified permanently (user meta). Future purchases do not ask for the code again.
Guest customerA signed cookie is stored (7 days, or 30 if they check "remember me"). Returning within that period, they stay verified.
Important The Verification badge in "My account → Orders" (registered customers only) indicates whether, when that order was created, the buyer was verified. A customer who is already verified will have all their orders marked "Verified" without being asked for the code each time.

Emergency mode

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.

6. The CheckoutOTP Panel

Everything is managed from WooCommerce → CheckoutOTP. The panel has these tabs:

TabWhat it is for
⚙️ SettingsAll configuration options (see section 7).
📋 Setup InstructionsQuick start guide.
📊 StatisticsMetrics: codes sent, successful verifications, failed attempts, blocks.
🛡️ API SecurityProtection against bots and REST API abuse.
📜 HistoryLast 50 security events (sends, verifications, failures, blocks).
🚫 Blocked EmailsTemporarily blocked emails, with a button to unblock them manually.

7. Configuration Options

General OTP Settings

OptionDefaultWhat it does
OTP Expiry Time15 minHow long the code is valid (1–60).
Maximum Failed Attempts5Failures allowed per code before it is invalidated (3–20).
Email Block Threshold10Accumulated failures per email (across codes) before it is blocked (3–50).
Email Block Duration60 minHow long an email stays blocked (5–1440 min).
🚨 Emergency ModeNoTemporarily disables verification (emergencies).
🌐 Site Behind Proxy/CDNNoEnable if your site is behind Cloudflare or a proxy/CDN, to detect the visitor's real IP.

Express Checkout Protection

Hides express payment buttons (PayPal, Google Pay, Apple Pay, Stripe…) from customers who are not yet verified, so they cannot skip verification.

OptionDefaultWhat it does
🔒 Strict ModeNoHides 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.
Keep in mind The visual hiding is a best-effort barrier (it can be bypassed by manipulating the HTML). The real protection against charging without verification on PayPal is applied on the server of your WordPress: the plugin intercepts the express payment request before it is sent to PayPal, so no charge is made. The PayPal server is not involved.

Security Notifications

OptionDefaultWhat it does
Admin Notification Recipients—Emails that receive the alerts (you can add several).
Notify When User is BlockedNoNotifies when an email is blocked after repeated failures.
Notify on Multiple Failed AttemptsNoNotifies when there are several failed attempts.

REST API Security

OptionDefaultWhat it does
Maximum Orders Per Hour5Order limit per hour per IP/email (1–50).
Block Bot User-AgentsNoBlocks requests from known bots by their User-Agent.
Notify on API AbuseNoNotifies on REST API abuse.
Notify on Suspicious OrdersNoNotifies when an order is flagged as suspicious.

Configurable Block Lists

OptionWhat it does
Custom Disposable Email DomainsAdditional 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-AgentsAdditional bot signatures (one per line).
Custom Suspicious NamesSuspicious names (e.g. "test", "asdf") that trigger detection.
Enable Regex PatternsTreats the above lists as regular expressions (advanced).
Built-in disposable domain list The plugin already rejects, with no configuration, these 32 temporary email domains: 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.

Data Maintenance

OptionDefaultWhat it does
Auto Purge LogsYesAutomatically deletes old records.
Log Retention Period30 daysHow many days records are kept (7–365).
On uninstall If you delete the plugin from WordPress (not just deactivate it), it completely removes its data: settings, tables, user metadata, session cookies and scheduled tasks. It leaves no trace in the database.

Design & Colors

Customize the look of the verification form:

Header Background Color Header Text Color Button Background Color Button Text Color

8. Emails & Customization

The 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.

Email templates

The plugin includes two templates:

How to customize without losing changes on update Copy the template into your theme folder, respecting the WooCommerce path:
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.

9. Compatibility

Classic checkout

Compatible with the WooCommerce shortcode checkout.

WooCommerce Blocks

Compatible with the block checkout (Store API), including locking the email field.

HPOS

Compatible with High-Performance Order Storage.

Express payments

Protection for PayPal Express and other express buttons.

Security The OTP code is stored as a SHA-256 hash (never in plain text) and compared securely; verification cookies are signed and are HttpOnly/SameSite=Strict. The verified email is never printed in the HTML of cached pages.
Languages The plugin includes translations into Spanish, Portuguese (Brazil) and French, plus the .pot template so you can translate it into any other language. The base language (source code) is English.

10. Troubleshooting

The code emails are not arriving

The recorded IP is not the customer's (site behind Cloudflare)

Enable the 🌐 Site Behind Proxy/CDN option. Only if your site is actually behind Cloudflare or a proxy/CDN.

The customer still sees checkout without verifying (caching)

The express payment buttons are not hidden

A legitimate customer got blocked

Go to the 🚫 Blocked Emails tab and click Unblock on their row. Blocks also expire on their own according to the configured duration.

The "Verification" column shows "Not verified"

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.

11. FAQ

Does it work with the block checkout?

Yes. Verification, email locking and server-side validation work on both classic and block checkout.

Can I use guest checkout (no account)?

Yes. Guests verify the same way, using a signed cookie.

Is the customer asked for the code on every purchase?

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).

Can I change the verification page?

Yes, any page containing the [checkoutotp_form] shortcode. The plugin detects it automatically.

What happens if I have two or more pages with the shortcode?

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.

What happens if an attacker tries many codes?

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.

Does the plugin slow down the store?

No. It only acts on the checkout and verification pages and adds no heavy queries to the rest of the site.

12. Changelog

1.3.0

1.2.2

1.2.1

1.2.0

1.1.0

1.0.0

13. Privacy & Data

CheckoutOTP keeps its data in your own WordPress database, so you stay in control of it. This is what it handles:

No third parties CheckoutOTP does not send any data to third parties or external services. The verification code email is sent through your own site's mail system (WordPress or the SMTP service you have configured).

Retention and deletion

Recommendation Mention in your store's privacy policy that you verify the customer's email with a one-time code and that a verification cookie is used. Whether that cookie requires consent depends on your country, so check with your legal advisor.

14. Support

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.