If I have disabled any product then it will redirect to 404. But I want to redirect that product url from 404 not found page to the category url in which this product is assigned.

That means I want to redirect to the related category of that 404 not found(Product url).

How can I achieve this in magento 2.3?

1 Answer 1


First Create a custom module https://www.mageplaza.com/magento-2-module-development/

now follow below steps to achieve this


<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        <tab id="test" translate="label" sortOrder="200">
            <label>Product Redirect</label>
        <section id="test2" translate="label" type="text" sortOrder="110" showInDefault="1" showInWebsite="1" showInStore="1">
            <label>Disabled Products Redirect</label>
            <group id="disabled_products_redirect" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>Redirection Message</label>
                <field id="redirection_message" translate="label comment" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
                    <label>Message for users who try to go to a disabled product URL</label>
                    <comment>Leave empty if you want the defaul message: "The product you tried to view is not available but here are some other options instead"</comment>


<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    <type name="Magento\Catalog\Controller\Product\View">
        <plugin name="test_disabled_products_redirect" type="Vendor\Module\Plugin\ProductsRedirect"/>


namespace Vendor\Module\Plugin;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Api\CategoryRepositoryInterface;
use Magento\Framework\Message\ManagerInterface;
use Magento\Framework\Controller\Result\RedirectFactory;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\Request\Http;
use \Magento\Catalog\Controller\Product as ProductController;

class ProductsRedirect
    private $productRepository;
    private $categoryInterface;
    private $messageManager;
    private $resultRedirectFactory;
    private $scopeConfig;
    private $request;
    public function __construct(
        ProductRepositoryInterface $productRepository,
        CategoryRepositoryInterface $categoryInterface,
        ManagerInterface $messageManager,
        RedirectFactory $resultRedirectFactory,
        ScopeConfigInterface $scopeConfig,
        Http $request
    ) {
        $this->productRepository = $productRepository;
        $this->categoryInterface = $categoryInterface;
        $this->messageManager = $messageManager;
        $this->resultRedirectFactory = $resultRedirectFactory;
        $this->scopeConfig = $scopeConfig;
        $this->request = $request;
     * @param ProductController $subject
    public function aroundExecute(ProductController $subject, callable $proceed)
        $productId = (int) $this->request->getParam('id');
        $product =  $this->productRepository->getById($productId);
        if ($product->isDisabled()) {
            $cats = $product->getCategoryIds();
            if ($cats) {
                try {
                    $firstCategoryId = $cats[0];
                    $category = $this->categoryInterface->get($firstCategoryId);
                    if ($category->getIsActive()) {
                        $message = $this->getMessage();
                        $categoryUrl = $category->getUrl();
                        $resultRedirect = $this->resultRedirectFactory->create();
                        return $resultRedirect->setPath($categoryUrl);
                    } else {
                        // TODO consider cases where category can't be displayed, maybe check other categories
                        throw new \Magento\Framework\Exception\LocalizedException(__('First category is not active'));
                } catch (\Exception $e) {
                    return $proceed();
        return $proceed();
    private function getMessage()
        $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE;
        $message =  $this->scopeConfig->getValue(
        if (!$message) {
            $message = __('The product you tried to view is not available but here are some other options instead');
        return $message;
  • what will be the use of system.xml here? Commented Jul 29, 2020 at 10:45
  • setting up custom message you can remove it if you dont need it
    – Pramod
    Commented Jul 29, 2020 at 10:48
  • moreover you can customize the code to suite your requirements you can remove the getMessage() function
    – Pramod
    Commented Jul 29, 2020 at 10:49
  • Thanks this is working....one more thing if product is not found in the website then what will be do? Commented Jul 29, 2020 at 11:10
  • please ask a different question someone might have done that and if this worked for you then accept so that other finds it helpful
    – Pramod
    Commented Jul 29, 2020 at 11:11

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.