Magento – Redirect product url with category path

base-urlcategorycategory-productsproducturl-rewrite

I had a store with category path turned on for product urls. After realising that, it creates duplicate content issues in SEO, I turned it off.
Since product urls (with category path) are already linked in Social Media and Email Campaigns, Google Analytics tracking is showing lots of such visited urls.

Now I am trying to redirect the product with category path to the one having product url key only.
For example:
http://mystore.com/category/sub-category/product.html –> http://mystore.com/product.html
http://mystore.com/category/product.html –> http://mystore.com/product.html

I tried to use the following script which implements the event controller_action_predispatch but it's not working as expected:

public function controllerActionPredispatch(Varien_Event_Observer $observer)
{
    $action         = $observer->getControllerAction();
    $request        = $action->getRequest();
    $requestUrl     = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $request->getRequestUri();
    $fullActionName = $action->getFullActionName();
    $storeId        = Mage::app()->getStore()->getId();

    if (in_array($fullActionName, array('catalog_product_view'))) {
        $product  = Mage::registry('current_product');
        $category = Mage::registry('current_category');
        if ($product && $product->getId() && $category && $category->getId()) {
            $categoryUrlKey = $this->getCategoryUrlKey($category->getId(), $storeId);
            if (empty($categoryUrlKey)) {
                $categoryUrlKey = $category->getUrlKey();
            }

            if (stripos($requestUrl, '/' . $categoryUrlKey . '/') !== false) {
                $urlKey = $this->getProductUrlKey($product->getId(), $storeId);
                if (empty($urlKey)) {
                    $urlKey = $product->getUrlKey();
                }
                $redirectUrl = Mage::getUrl() . trim($urlKey, '/') . '.html';
                $action->getResponse()->setRedirect($redirectUrl, 301);
                $action->getRequest()->setDispatched(true);
                return;
            }
        }
    }
}

public function getCategoryUrlKey($categoryId, $storeId = 0)
{
    $resource   = Mage::getSingleton('core/resource');
    $connection = $resource->getConnection('core_read');
    $sql        = "select value from catalog_category_entity_url_key where entity_id = ? and store_id = ? limit 1";
    $urlKey     = $connection->fetchOne($sql, array($categoryId, $storeId));
    return $urlKey;
}

public function getProductUrlKey($productId, $storeId = 0)
{
    $resource   = Mage::getSingleton('core/resource');
    $connection = $resource->getConnection('core_read');
    $sql        = "select value from catalog_product_entity_url_key where entity_id = ? and store_id = ? limit 1";
    $urlKey     = $connection->fetchOne($sql, array($productId, $storeId));
    return $urlKey;
}

Any idea for the perfect solution?
I am using #Magento #EE version 1.13.

[Edit]
One strange thing is

$action->getResponse()->setRedirect($redirectUrl, 301);
$action->getRequest()->setDispatched(true);

redirection doesn't work in live server but works in localhost.

Best Answer

If you want exclude category url from product url for new product you need enable setting from admin>system>catalog>Catalog>Search engine Optimization> Use Categories Path for Product URLsmake itnoalsoCreate Permanent Redirect for URLs if URL Key Changedityes`

Here some other trick

http://www.doingthing.com/blog/item/1164
http://www.mikesmullin.com/development/use-categories-product-urls-magento-seo-without-duplicate-content/

Here the another process of This task...

Step1: create a backup core_url_rewrite table with table data and it structure.

Step2: create another duplicate table of core_url_rewrite using my query below:

CREATE  TABLE  `core_url_rewrite_dump` (  `url_rewrite_id` int( 10  )  unsigned NOT  NULL  AUTO_INCREMENT  COMMENT  'Rewrite Id',
 `store_id` smallint( 5  )  unsigned NOT  NULL DEFAULT  '0' COMMENT  'Store Id',
 `id_path` varchar( 255  )  DEFAULT NULL  COMMENT  'Id Path',
 `request_path` varchar( 255  )  DEFAULT NULL  COMMENT  'Request Path',
 `target_path` varchar( 255  )  DEFAULT NULL  COMMENT  'Target Path',
 `is_system` smallint( 5  ) unsigned DEFAULT  '1' COMMENT  'Defines is Rewrite System',
 `options` varchar( 255  )  DEFAULT NULL  COMMENT  'Options',
 `description` varchar( 255  )  DEFAULT NULL  COMMENT  'Deascription',
 `category_id` int( 10  ) unsigned  DEFAULT NULL  COMMENT  'Category Id',
 `product_id` int( 10  ) unsigned  DEFAULT NULL  COMMENT  'Product Id',
 PRIMARY  KEY (  `url_rewrite_id`  ) ,
 UNIQUE  KEY  `UNQ_CORE_URL_REWRITE_REQUEST_PATH_STORE_ID` (  `request_path` ,  `store_id`  ) ,
 UNIQUE  KEY  `UNQ_CORE_URL_REWRITE_ID_PATH_IS_SYSTEM_STORE_ID` (  `id_path` ,  `is_system` ,  `store_id`  ) ,
 KEY  `IDX_CORE_URL_REWRITE_TARGET_PATH_STORE_ID` (  `target_path` ,  `store_id`  ) ,
 KEY  `IDX_CORE_URL_REWRITE_ID_PATH` (  `id_path`  ) ,
 KEY  `IDX_CORE_URL_REWRITE_STORE_ID` (  `store_id`  ) ,
 KEY  `FK_CORE_URL_REWRITE_CTGR_ID_CAT_CTGR_ENTT_ENTT_ID` (  `category_id`  ) ,
 KEY  `FK_CORE_URL_REWRITE_PRODUCT_ID_CATALOG_CATEGORY_ENTITY_ENTITY_ID` (  `product_id`  )  ) ENGINE  = InnoDB  DEFAULT CHARSET  = utf8 COMMENT  =  'Url Rewrites';

SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO';

INSERT INTO `core_url_rewrite_dump` SELECT * FROM `magento1702v1`.`core_url_rewrite

Step4:

final run the below code

UPDATE `magento1702v1`.`core_url_rewrite` as p  SET `target_path`=(SELECT rurl.request_path
FROM `core_url_rewrite_dump` as rurl
WHERE rurl.product_id IS NOT NULL
AND rurl.category_id IS NULL 
AND rurl.product_id=p.product_id
LIMIT 0 , 1)  
,`options` = 'RP' 
WHERE p. product_id IS NOT NULL
AND p.category_id  IS NOT NULL 
Related Topic