Weather vane

Redirect Magento products core URLs to the SEO-friendly version

From a SEO perspective, one of the biggest problem for an eCommerce shop is the duplicate content. There are many ways in which the content might result as duplicate and most of them are related to the URL structure of the catalog.

In our case, Magento allows a user to browse the catalog products pages in two ways: using the core URL and using the SEO-friendly URL.

This is how a core URL looks like:
http://www.example.com/catalog/product/view/id/12345

And this is how a SEO-friendly URL looks like:
http://www.example.com/my-product-page.html

Both URLs are valid, and even without a deep analysis of all the Magento areas and installed plugins, it is easy to find out that Google indexes both version of the same page.

To solve this problem, we can extend the Magento catalog_url indexer process to create programmatically a 301 permanent redirect for each product in the catalog. This way we will be able to bring the users - as well as the search engines crawlers - from the /catalog/product/view/id URL to the SEO-friendly one.

Let's start by creating our basic module files and folder structure.
"Kiwee" will be our namespace and "Redirector" our module name.

Create the required folders and files:

app/code/local/Kiwee/Redirector
app/code/local/Kiwee/Redirector/etc
app/code/local/Kiwee/Redirector/Model

app/etc/modules/Kiwee_Redirector.xml

<?xml version="1.0"?>
<config>
    <modules>
        <Kiwee_Redirector>
            <active>true</active>
            <codePool>local</codePool>
        </Kiwee_Redirector>
    </modules>
</config>

app/code/local/Kiwee/Redirector/etc/config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<config>
    <modules>
        <Kiwee_Redirector>
            <version>0.1.0</version>
        </Kiwee_Redirector>
    </modules>
    <global>
        <models>
            <catalog>
                <rewrite>
                    <url>Kiwee_Redirector_Model_Catalog_Url</url>
                </rewrite>
            </catalog>
        </models>
    </global>
</config>

In the config.xml file we already specified which class of ours will override the Magento app/code/core/Mage/Catalog/Model/Url.php core class.

It is always advisable to extend the Magento core classes rather than editing the core files. Extending Magento classes is the best practice to keep the core secure and to keep a maximum compatibility for future Magento upgrades.

Let's create our main class file to add a logic for our redirects  </span>app/code/local/Kiwee/Redirector/Model/Url.php.

class Kiwee_Redirector_Model_Url extends Mage_Catalog_Model_Url {

    protected function _refreshProductRewrite(Varien_Object $product, Varien_Object $category) {
        // First execute the original Magento code
	parent::_refreshProductRewrite($product, $category);

        // Here we will add the logic to create additional URL rewrites to redirect the core urls to the SEO Friendly ones

        return $this;
    }
}

Now we can add our code, to create additional 301 (permanent) redirects for the products. The final version of the file will be the following:

&lt;?php

class Kiwee_Redirector_Model_Url extends Mage_Catalog_Model_Url {

	protected function _refreshProductRewrite(Varien_Object $product, Varien_Object $category) {

		parent::_refreshProductRewrite($product, $category);
		
		// Execute our code only if SEO Urls are enabled in the backend
		if(Mage::getStoreConfig('web/seo/use_rewrites')) {
		
			// Create a 301 permanent redirect for the core product url if they don't include category
			$idPath = $this-&gt;generate301Path($product);
			$targetPath = $this-&gt;getProductReverseRequestPath($product, $category);
			$requestPath = $this-&gt;generatePath('target', $product, $category);

			// First delete old 301 rewrite for the current product to be sure that we'll have only one
			$this-&gt;getResource()-&gt;deleteRewrite($requestPath, $category-&gt;getStoreId());

			// Create an array to store all the information of the rewrite we are creating
			if (empty($categoryId) || is_null($categoryId)) {
				$rewriteData = array(
					'store_id' =&gt; $category-&gt;getStoreId(),
					'category_id' =&gt; $categoryId,
					'product_id' =&gt; $product-&gt;getId(),
					'id_path' =&gt; $idPath,
					'request_path' =&gt; $requestPath, // This will be the core product url catalog/product/view/id/productId
					'target_path' =&gt; $targetPath, // This will be our SEO friendly url we want to redirect to
					'is_system' =&gt; 0,
					'options' =&gt; 'RP' // RP means Rewrite Permanent. It marks this rewrite as a 301 redirection
				);
	
				$this-&gt;getResource()-&gt;saveRewrite($rewriteData);
			}
		}
		return $this;
	}

	// This method generate an id_path to be associated with the rewrite we are going to create
	protected function generate301Path($product = null) {
		if (!$product) {
			Mage::throwException(Mage::helper('core')-&gt;__('Please specify a product.'));
		}

		// generate an recognisable custom id_path
		return 'custom301/' . $product-&gt;getId();
	}


	// This method returns the SEO-friendly URL if specified
	protected function getProductReverseRequestPath($product, $category) {
		if ($product-&gt;getUrlKey() == '') {
			$urlKey = $this-&gt;getProductModel()-&gt;formatUrlKey($product-&gt;getName());
		} else {
			$urlKey = $this-&gt;getProductModel()-&gt;formatUrlKey($product-&gt;getUrlKey());
		}
		$storeId = $category-&gt;getStoreId();
		$suffix = $this-&gt;getProductUrlSuffix($storeId);
		$requestPath = $urlKey;

		if (strlen($requestPath) &gt; self::MAX_REQUEST_PATH_LENGTH + self::ALLOWED_REQUEST_PATH_OVERFLOW) {
			$requestPath = substr($requestPath, 0, self::MAX_REQUEST_PATH_LENGTH);
		}

		$fullPath = $requestPath . $suffix;

		return $fullPath;
	}

}

Now when we reindex the catalog_url index, Magento will create additional redirects for the products, to always display the page with the SEO-friendly URL.

FacebookTwitterPinterest

Enzo Perrotta

Senior Full Stack Developer

Magento enthusiast, technology addicted and wasabi lover. I embrace the whole eCommerce ecosystem, I’m focused on both, front-end and back-end development.