I am using the guest entries plugin and i get specific spam on a contact form. So I have edited the controller to test the message for certain words coming thru the message eg "SEO", "marketing". When these words are found I then return to prevent saving.

I've tested this locally with a duplicate of the spam message and it works. However in the real world the spam messages are still getting through my hacky word filter. My addition is below. Im not so much looking for comment on the code - though very welcome - but wondering how can they keep getting through?

        // Fire an 'onBeforeSave' event
        $event = new SaveEvent(['entry' => $entry]);
        $this->trigger(self::EVENT_BEFORE_SAVE_ENTRY, $event);

        if (!$event->isValid) {
            return $this->_returnError($settings, $entry);

        if(preg_match('(marketing|eric|SEO|Hacked|Bitcoin|AI|ai|FREE|CLICK|LINK|links|marketing|traffic|Eric|http://skytrafficpro.com|boost|technology|Visitor )', $entry->contactMessage) === 1) {

            Craft::info('Guest entry submission spam detected.'.$entry->contactEmail, __METHOD__);

            Craft::info('Guest entry submission spam detected.'.$entry->contactMessage, __METHOD__);

            return $this->_returnSuccess($entry, true);

        } else {

            if ($event->isSpam) {
                Craft::info('Guest entry submission suspected to be spam.', __METHOD__);
                // Pretend it worked.
                return $this->_returnSuccess($entry, true);

            // Try to save it
            if ($sectionSettings->runValidation) {

            if (!Craft::$app->getElements()->saveElement($entry)) {
                return $this->_returnError($settings, $entry);

            return $this->_returnSuccess($entry);

  • 2
    Not sure what you're asking about here – is your problem that messages with your blacklisted words are still getting through? Or are you looking for better ways to detect spam messages that don't include the blacklisted words? Also, where is this code placed, in a controller? Why are you triggering the save event manually instead of just hooking into the save event that is triggered by the elements service?
    – MoritzLost
    Feb 1, 2023 at 13:47
  • Yes messages with blacklisted words are still getting thru but didnt when tested locally. Code is hacked in where save function is called
    – joomkit
    Feb 2, 2023 at 14:28

1 Answer 1


Don't hack your code into Craft's source files. You very rarely want to modify vendor code, so that dependencies can always be cleanly installed using Composer. Instead, use an event to hook into the EVENT_BEFORE_SAVE_ENTRY event and add your spam checking logic there. You can use the event code generator to get started with some code examples. Put your code in a custom module.

In the code you posted above, you can see that the plugin triggers the event and checks $event->isSpam. You can use this in your hook - if the submission is caught by your spam filter, set $event->isSpam = true; and the plugin will block the submission.

A blacklist of words will only get you so far, you'll never catch everything with it. A slightly more robust way to check for spam is a security question. Those won't help you against targeted spam, but is very effective for your run-of-the-mill bot spam. Put a question like this in your form:

What city are our company headquarters located in?
You can find the answer on our contact page

This will be easy to answer for humans, but not so much for bots (at least most simple bots, advanced bots that utilize machine learning might still get through).

Then define a list of correct answers (make sure to accept all possible spellings) and only let submissions through that include the correct answer. This has proven very effective for many sites I've worked on, while being quite simple to implement. It also doesn't require any external CAPTCHA service, those are problematic in regards to data privacy (and basically impossible to use in the EU in a GDPR-compliant way).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.