One of my website clients is a couple of Norwegian language college professors who came to me almost ten years ago for help with their existing LearnDash site that they were using as an online language learning tool that was used along with a textbook they had written. I did some custom LearnDash coding (i.e. custom reports) for them for a few years and eventually they had me build and host two new sites to replace their original site.
In mid-2023 they decided to convert one of their sites to an ecommerce site, charging a minimal fee for two years of access to the LearnDash course they had created. By this time LearnDash was more or less able to handle the course registrations and Stripe was tasked with collecting the fees.
Dealing with spam registrations – round one
Part of the ecommerce conversion process was cleaning out several thousand spam registrations that the site had accumulated over the years. The code I wrote for that purpose checked to see if a user had ever actually started the LearnDash course, and if they hadn’t, they were deleted from the database. Accounts and data for users who had started the course before the access fee was instituted were not deleted, but those users would still need to pay the fee to access and use the course in the future.
This code still runs whenever a WordPress admin page is loaded, and it allows a new registrant fifteen minutes to complete their payment or else it deletes their user account. The logic here is that spammers are not going to pay the access fee and therefore can be safely deleted.
That solution kept the number of spam registrations from accumulating, but it didn’t prevent them from happening in the first place.
Spammers are very efficient at registering fake accounts on virtually any WordPress site that allows user registrations, and this particular site was getting new spam registrations every few minutes. That may not seem like a problem since they’re deleted fifteen minutes later, but it does put an extra load on the server that doesn’t help matters when LearnDash already pushes a server’s limits further than most other types of websites.
A bigger issue is what this was doing to our email delivery. I use Postmark to handle all the emails that my client websites send out, both transactional and broadcast (i.e. newsletter) emails.
Transactional emails are emails such as password recovery emails, which the spambots trigger shortly after registering with either a fake email address or a stolen email address. Many of these emails bounced, and those that went to actual email addresses were often marked as “spam” by whoever owned those email addresses. Those bounces and spam complaints could or would eventually lead to services like Gmail or Yahoo sending our legitimate transactional emails into their users’ spam folders, which had already started happening. Or potentially even worse, being shut down by Postmark for too many bounces and spam complaints. That would be a significant problem.
So I set myself to working out a better solution.
Dealing with spam registrations – round two
Note: I’m going to use the actual URLs from my client’s site in the following explanations rather than create fake URLs such as https://yourdomain.com. It’s simpler that way.
LearnDash has an add-on plugin available called Integrity, which, among several other useful things, adds reCAPTCHA to the LearnDash login and/or registration forms.
That seemed like a logical first step so I installed that plugin and configured it to work with reCAPTCHA.
Unfortunately, what it ended up doing was preventing actual users from being able to log in, and it didn’t seem to prevent spam registrations because spammers are not using the LearnDash registration form.
What it does do, like most security approaches in life, is keep the honest people honest. With that in mind I have kept reCAPTCHA in place on my client’s LearnDash registration form, since so far it has not stopped any legitimate registrations that we know of. You can see that registration form at https://settigang.com/portal-access/?ld_register_id=580.
I should explain that URL. The page https://settigang.com/portal-access/ is a WordPress page. In the LearnDash Registration/Login settings there is a setting for the Registration/Login page. When you tell LearnDash which page to use as the registration and login page, LearnDash appends the parameter for a particular course ID to the end of that page’s URL. In this case, that parameter is ld_register_id=580 because the course ID is 580.
Spammers, on the other hand, go directly to the default WordPress registration form found on any WordPress site that has the setting “Anyone can register” enabled. That registration form is found at the URL https://settigang.com/wp-login.php?action=register.
If you were to click that link right now you would be emulating what a spambot does, and you would see the result of the code I’m going to explain next.
Dealing with spam registrations – round three
My next thought was to block access to https://settigang.com/wp-login.php?action=register using the .htaccess file included in any WordPress installation on an Apache server, normally found in the root directory where WordPress is typically located.
The text, or code, in the Gist below when added to your .htaccess file will block all access to that WordPress registration form.
Gist – Block all access to the WordPress default registration form
That worked, but it worked too well, as it also blocked legitimate registrations from real students. This puzzled me at first because we were using the LearnDash registration form, until I tried to register as a student and kept watching the address bar in my browser.
If you were to fill out and submit the registration form at https://settigang.com/portal-access/?ld_register_id=580 while watching the address bar, you would see the URL https://settigang.com/wp-login.php?action=register appear momentarily before being redirected to https://settigang.com/portal-access/?ld-registered=true&ld_register_id=580 where you could then complete your registration for that course by paying the course access fee.
I realized then that LearnDash is utilizing the default WordPress registration form as part of their registration process.
Dealing with spam registrations – round four
The next idea I had, and the one that worked and is still working, was to add an HTTP_REFERER condition to that .htaccess text.
This next Gist is the final working product. What it’s doing is checking to see if the previous URL is the page with the LearnDash registration form on it. If it isn’t, as in a spambot going directly to that WordPress registration page, the server returns a 403 status code (403 Forbidden).
The result? Zero spam registrations since implementing this seemingly simple fix, while still allowing all legitimate registrations by real people. And as a bonus, the bounce rate and spam reputation for this particular site is now trending back down to zero, where it should be.
Feel free to adapt that .htaccess code for your situation, changing the URL accordingly.
Note: I’ve left the first RewriteCond line in that code but commented out (with an #) as a reminder to me and to you that leaving the LearnDash parameter appended to the referrer URL does not work.
A word about .htaccess
Your .htaccess file is powerful. What you do there affects your entire website. Before making any changes to that file you should have a backup copy, and you should probably even backup your entire website and database.
Having said that, the .htaccess file is not voodoo or black magic. You don’t have to be afraid of it. Experiment and learn!