Skip to content

Events

The 404 handling pipeline can be customized using events on NotFoundUriService. These follow Craft's standard event patterns.

Register event handlers in your module or plugin's init() method:

php
use craft\base\Event;
use newism\notfoundredirects\services\NotFoundUriService;

See How It Works for the full pipeline flowchart and event sequence.

EVENT_BEFORE_HANDLE

Fires before the plugin does anything. Cancel to skip plugin handling entirely. Craft will render its normal 404 template.

Event class: newism\notfoundredirects\events\NotFoundUriEvent (extends CancelableEvent)

PropertyTypeDescription
requestcraft\web\RequestThe current request
siteIdintThe current site ID
isValidboolSet to false to cancel

Example: Skip handling for bot probes

Block bots at the edge

For best performance, block known bot probes and junk requests at the web server or CDN level (Nginx, Cloudflare, or a bad bot blocker). A request that never reaches Craft is always faster than one Craft has to process. Use this event for anything that slips through.

php
use newism\notfoundredirects\events\NotFoundUriEvent;

Event::on(
    NotFoundUriService::class,
    NotFoundUriService::EVENT_BEFORE_HANDLE,
    function(NotFoundUriEvent $event) {
        // Don't log or redirect known junk paths
        if (preg_match('#^(wp-|\.env|\.git)#i', $event->request->getPathInfo())) {
            $event->isValid = false;
        }
    }
);

Example: Skip handling for specific file extensions

php
use newism\notfoundredirects\events\NotFoundUriEvent;

Event::on(
    NotFoundUriService::class,
    NotFoundUriService::EVENT_BEFORE_HANDLE,
    function(NotFoundUriEvent $event) {
        // Don't process 404s for image or font files
        if (preg_match('/\.(jpg|png|gif|svg|woff2?|ttf|eot)$/i', $event->request->getPathInfo())) {
            $event->isValid = false;
        }
    }
);

EVENT_DEFINE_URI

Fires after the URI has been extracted from the request. Modify $event->uri to change what the plugin matches against.

The default URI comes from $request->getPathInfo(), which strips the site base URL prefix for multi-site subfolder setups.

Event class: newism\notfoundredirects\events\DefineNotFoundUriEvent (extends Event)

PropertyTypeDescription
requestcraft\web\RequestThe current request
uristringThe URI to match against (mutable)
siteIdintThe current site ID

Example: Preserve query parameters

php
use newism\notfoundredirects\events\DefineNotFoundUriEvent;

Event::on(
    NotFoundUriService::class,
    NotFoundUriService::EVENT_DEFINE_URI,
    function(DefineNotFoundUriEvent $event) {
        $q = $event->request->getQueryParam('q');
        if ($q !== null) {
            $event->uri .= '?q=' . $q;
        }
    }
);

Example: Strip trailing slashes

php
use newism\notfoundredirects\events\DefineNotFoundUriEvent;

Event::on(
    NotFoundUriService::class,
    NotFoundUriService::EVENT_DEFINE_URI,
    function(DefineNotFoundUriEvent $event) {
        $event->uri = rtrim($event->uri, '/');
    }
);

EVENT_BEFORE_REDIRECT

Fires after a matching redirect is found but before the redirect is sent. Modify $event->destinationUrl to change the destination, or cancel to prevent the redirect (the 404 is still logged as handled).

Event class: newism\notfoundredirects\events\BeforeRedirectEvent (extends CancelableEvent)

PropertyTypeDescription
requestcraft\web\RequestThe current request
uristringThe matched URI
redirectRedirectThe matched redirect model
destinationUrlstringThe destination URL (mutable)
isValidboolSet to false to cancel the redirect

Example: Preserve query string on temporary redirects

php
use newism\notfoundredirects\events\BeforeRedirectEvent;

Event::on(
    NotFoundUriService::class,
    NotFoundUriService::EVENT_BEFORE_REDIRECT,
    function(BeforeRedirectEvent $event) {
        if ($event->redirect->statusCode === 302) {
            $params = \Craft::$app->getRequest()->getQueryParams();
            $event->destinationUrl = \craft\helpers\UrlHelper::urlWithParams(
                $event->destinationUrl,
                $params,
            );
        }
    }
);

Example: Add UTM tracking to redirects

php
use newism\notfoundredirects\events\BeforeRedirectEvent;

Event::on(
    NotFoundUriService::class,
    NotFoundUriService::EVENT_BEFORE_REDIRECT,
    function(BeforeRedirectEvent $event) {
        $event->destinationUrl = \craft\helpers\UrlHelper::urlWithParams(
            $event->destinationUrl,
            ['utm_source' => '404-redirect'],
        );
    }
);

EVENT_AFTER_REDIRECT

Fires after the redirect has been sent. This is informational only and you cannot modify the response at this point. Useful for analytics, logging, or sending notifications.

Event class: newism\notfoundredirects\events\AfterRedirectEvent (extends Event)

PropertyTypeDescription
requestcraft\web\RequestThe current request
uristringThe matched URI
redirectRedirectThe matched redirect model
destinationUrlstringThe final destination URL
statusCodeintThe HTTP status code used

Example: Log redirects to an external service

php
use newism\notfoundredirects\events\AfterRedirectEvent;

Event::on(
    NotFoundUriService::class,
    NotFoundUriService::EVENT_AFTER_REDIRECT,
    function(AfterRedirectEvent $event) {
        // Send to your analytics or monitoring service
        MyAnalytics::trackRedirect(
            from: $event->uri,
            to: $event->destinationUrl,
            statusCode: $event->statusCode,
        );
    }
);