I need to specify a prefix static string for all URLs of my Products and Categories. Just like Wordpress Woocommerce permalinks.

For example all of Categories should have product-category prefix in their URL:

  • Cat One: domain.com/product-category/cat-one
  • Cat Two (child of 'Cat One'): domain.com/product-category/cat-one/cat-two

and all of Products should have product URL prefix, no matter what their Category is:

  • Product One: domain.com/product/product-one
  • Product Two: domain.com/product/product-two

I tried to do this solution, but It's for 3 years ago and not working in Magento 2.

Also this extension is for Magento 1.x as you see.

By the way, I'm using Magento 2.1.9 with PHP 7.0.22 and XAMPP 3.2.2.



1 Answer 1


I found a good solution for this situation!

We need to make our custom module for extending Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator class with plugin methods and Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator class with preference class (because we need to change inside of its methods, not change after or before them).

Assume that our custom module created by this documentation, has <Vendor> and <Module> names.

1) So, at first we need to define our plugin and preference class in our etc/di.xml file:

<?xml version="1.0"?>   
  <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">

    <preference for="Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator" type="<Vendor>\<Module>\Model\CatalogUrlRewrite\ProductUrlPathGenerator"/>

    <type name="Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator">
      <plugin name="my_category_url_path_generator" type="<Vendor>\<Module>\Plugin\Model\CategoryUrlPathGenerator" sortOrder="15"/>


2) Add these classes in proper addresses:

a) Our preference class in <Vendor>\<Module>\Model\CatalogUrlRewrite\ProductUrlPathGenerator.php :

--> Change this two constant in this class for your own custom static route: <--

    namespace <Vendor>\<Module>\Model\CatalogUrlRewrite;

    class ProductUrlPathGenerator extends \Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator

        const PRODUCT_PREFIX_ROUTE = 'product';
        const CATEGORY_PREFIX_ROUTE = 'product-category';

         * @param \Magento\Store\Model\StoreManagerInterface $storeManager
         * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
         * @param \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator
         * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
        public function __construct(
            \Magento\Store\Model\StoreManagerInterface $storeManager,
            \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
            \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator,
            \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
        ) {
            parent::__construct($storeManager, $scopeConfig, $categoryUrlPathGenerator, $productRepository);

         * Retrieve Product Url path (with category if exists)
         * @param \Magento\Catalog\Model\Product $product
         * @param \Magento\Catalog\Model\Category $category
         * @return string
        public function getUrlPath($product, $category = null)
            $path = $product->getData('url_path');
            if ($path === null) {
                $path = $product->getUrlKey()
                    ? $this->prepareProductUrlKey($product)
                    : $this->prepareProductDefaultUrlKey($product);

            if ($category !== null) {
                $categoryUrl = str_replace(self::CATEGORY_PREFIX_ROUTE .'/','',$this->categoryUrlPathGenerator->getUrlPath($category));
                $path = $categoryUrl . '/' . $path;

            return self::PRODUCT_PREFIX_ROUTE . '/' . $path;

b ) Our plugin class in <Vendor>\<Module>\Plugin\Model\CategoryUrlPathGenerator.php :

namespace <Vendor>\<Module>\Plugin\Model;

class CategoryUrlPathGenerator
    * Add a static prefix to category URL path
    * @param \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $subject
    * @param $path
    * @return string
    public function afterGetUrlPath(\Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $subject, $path)
        if (strpos($path, \<Vendor>\<Module>\Model\CatalogUrlRewrite\ProductUrlPathGenerator::CATEGORY_PREFIX_ROUTE) === false)
            $path = \<Vendor>\<Module>\Model\CatalogUrlRewrite\ProductUrlPathGenerator::CATEGORY_PREFIX_ROUTE . $path;

        return $path;

3) Run this command:

php bin/magento setup:upgrade

And its DONE!, now you can create products and their categories and you'll see the url rewrites that created with these static url prefixes.

DO NOT forget to change <Vendor>,<Module> with your own custom module names and change the constants of ProductUrlPathGenerator class for change to your custom static prefixes.

Good luck.

  • Hello @Mehran. Can you please let me know why you have used strpos with prefix and path in CategoryUrlPathGenerator plugin? I am not getting it. Otherwise, this solution works fine. Commented Sep 27, 2018 at 9:21
  • 1
    strpos is used to check if the url_path already has the prefix in it and stops it being added when it is already present. Commented May 24, 2022 at 12:58

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.