Redirect Magento products core URLs to the SEO-friendly version
Enzo PerrottaReading Time: 2 minutes
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:
<?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->generate301Path($product); $targetPath = $this->getProductReverseRequestPath($product, $category); $requestPath = $this->generatePath('target', $product, $category); // First delete old 301 rewrite for the current product to be sure that we'll have only one $this->getResource()->deleteRewrite($requestPath, $category->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' => $category->getStoreId(), 'category_id' => $categoryId, 'product_id' => $product->getId(), 'id_path' => $idPath, 'request_path' => $requestPath, // This will be the core product url catalog/product/view/id/productId 'target_path' => $targetPath, // This will be our SEO friendly url we want to redirect to 'is_system' => 0, 'options' => 'RP' // RP means Rewrite Permanent. It marks this rewrite as a 301 redirection ); $this->getResource()->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')->__('Please specify a product.')); } // generate an recognisable custom id_path return 'custom301/' . $product->getId(); } // This method returns the SEO-friendly URL if specified protected function getProductReverseRequestPath($product, $category) { if ($product->getUrlKey() == '') { $urlKey = $this->getProductModel()->formatUrlKey($product->getName()); } else { $urlKey = $this->getProductModel()->formatUrlKey($product->getUrlKey()); } $storeId = $category->getStoreId(); $suffix = $this->getProductUrlSuffix($storeId); $requestPath = $urlKey; if (strlen($requestPath) > 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.