What can you do to prevent duplicated content of products from different stores?
Recently we’ve received one inquiry to optimize an existing Magento website.
Shortly, there are 2 stores with codes: store1 and store2. Store code is included in the URL.
While we were working on the optimization, the client has reported that some of the products show in both: store1 and store2 but they should be visible only in one of those stores (imagine that you’re on store1 and you see there some related products but from store2).
Additional problem in our case was that there were 2 categories, store1 and store2 (same names for categories as for store codes).
Our ICG (Inchoo Consulting Group) team was on top of the all things that we were doing. When they saw our problem, they instantly noticed what that could mean for client’s SEO!
Shortly, when you’re on one product you could manually change URL from /store1/ to /store2/ and you were able to see the same product, but now in different store (with different theme).
Because search engine could see the same product in store1 and store2 (2 same pages but with different URL – with the same content) it might think that you’re “cheating” and it could position you lower in search results. What search engine could do is to index all products on all stores – duplicated content. To avoid that we needed to “find” proper solution for that.
Basically what we could do here is: a) 301 redirects or b) use canonical URLs. So we needed to ensure for some products from store1 not to be visible in store2.
At the end what we did is that we added 301 redirects for products that should be only visible in one store (if you try somehow to change URL), but if product exists in both stores we added canonical URLs to be on store1 (store1 in our case is more important).
What do you think about this approach for this specific issue?
If you have some similar situation here’s an idea how can you solve particular issue (bellow is sample code how can you solve it). Basically we’ve modified 2 files. One controller (for redirects) and one block (for canonical URLs).
Note: we’ve worked on CE ver.: 1.7.0.1. Don’t change the core files! But, because of simplicity I’ll show you the solution by modifying core files.
Open file app/code/core/Mage/Catalog/controllers/ProductController.php and replace viewAction() with the following content:
public function viewAction()
{
// Get initial data from request
$categoryId = (int) $this->getRequest()->getParam('category', false);
$productId = (int) $this->getRequest()->getParam('id');
$specifyOptions = $this->getRequest()->getParam('options');
/////////////////////////////////////// START WITH 301 REDIRECT
$redirectURL = Mage::getUrl('', array(
'_current' => true,
'_use_rewrite' => true,
));
if ($productId) {
$product = Mage::getModel('catalog/product')->load($productId);
}
$tmpStoreCode = false;
$tmpStoreCode = Mage::app()->getStore()->getCode();
$expCatIdStore= false;
switch ($tmpStoreCode) {
case 'store1':
$expCatIdStore = 1;
break;
case 'store2':
$expCatIdStore = 100;
break;
}
if ($expCatIdStore && $productId) {
$catIds = array();
try {
$catIds = $product->getCategoryIds();
} catch (Exception $e) {
//Mage::log or similar
}
$productIsInStore1 = false;
$productIsInStore2 = false;
// imagine that store code store1 represents category_id=1 and
// store with code store2 represents category_id=100
if (in_array(1, $catIds)) {
$productIsInStore1 = true;
}
if (in_array(100, $catIds)) {
$productIsInStore2 = true;
}
// if product should be in both stores don't do any redirect
if ( !($productIsInStore1 && $productIsInStore2) ) {
if ($productIsInStore2 && $tmpStoreCode === 'store1') {
$redirectURL = str_replace('example.com/store1/', 'example.com/store2/', $redirectURL);
header ('HTTP/1.1 301 Moved Permanently');
header ('Location: ' . $redirectURL);
exit;
} elseif ($productIsInStore1 && $tmpStoreCode === 'store2') {
$redirectURL = str_replace('example.com/store2/', 'example.com/store1/', $redirectURL);
header ('HTTP/1.1 301 Moved Permanently');
header ('Location: ' . $redirectURL);
exit;
}
}
}
/////////////////////////////////////// END WITH 301 REDIRECT
// Prepare helper and params
$viewHelper = Mage::helper('catalog/product_view');
$params = new Varien_Object();
$params->setCategoryId($categoryId);
$params->setSpecifyOptions($specifyOptions);
// Render page
try {
$viewHelper->prepareAndRender($productId, $this, $params);
} catch (Exception $e) {
if ($e->getCode() == $viewHelper->ERR_NO_PRODUCT_LOADED) {
if (isset($_GET['store']) && !$this->getResponse()->isRedirect()) {
$this->_redirect('');
} elseif (!$this->getResponse()->isRedirect()) {
$this->_forward('noRoute');
}
} else {
Mage::logException($e);
$this->_forward('noRoute');
}
}
}
Additionally, to use canonical URLs for products that should be in both categories but, perhaps, show to search engine that it’s in only one (for example store1) category change _prepareLayout() method with the following content
Open file app/code/core/Mage/Catalog/Block/Product/View.php
protected function _prepareLayout()
{
$this->getLayout()->createBlock('catalog/breadcrumbs');
$headBlock = $this->getLayout()->getBlock('head');
if ($headBlock) {
$product = $this->getProduct();
$title = $product->getMetaTitle();
if ($title) {
$headBlock->setTitle($title);
}
$keyword = $product->getMetaKeyword();
$currentCategory = Mage::registry('current_category');
if ($keyword) {
$headBlock->setKeywords($keyword);
} elseif($currentCategory) {
$headBlock->setKeywords($product->getName());
}
$description = $product->getMetaDescription();
if ($description) {
$headBlock->setDescription( ($description) );
} else {
$headBlock->setDescription(Mage::helper('core/string')->substr($product->getDescription(), 0, 255));
}
if ($this->helper('catalog/product')->canUseCanonicalTag()) {
$params = array('_ignore_category'=>true);
/////////////////////////////////////// START WITH CANONICAL
$cannURL = $product->getUrlModel()->getUrl($product, $params);
$productId = (int) $this->getRequest()->getParam('id');
$tmpStoreCode = false;
$tmpStoreCode = Mage::app()->getStore()->getCode();
$expCatIdStore = false;
switch ($tmpStoreCode) {
case 'store1':
$expCatIdStore = 1;
break;
case 'store2':
$expCatIdStore = 100;
break;
}
if ($expCatIdStore && $productId) {
$catIds = array();
try {
$catIds = $product->getCategoryIds();
} catch (Exception $e) {
//die silently
}
$productIsInBoth = false;
if ( in_array(1, $catIds) && in_array(100, $catIds) ) {
$productIsInBoth = true;
}
if ($productIsInBoth && $tmpStoreCode === 'store2') {
$cannURL = str_replace('example.com/store2/', 'example.com/store1/', $cannURL);
}
}
$headBlock->addLinkRel('canonical', $cannURL);
//////////////////////////////////// END WITH CANONICAL
//$headBlock->addLinkRel('canonical', $product->getUrlModel()->getUrl($product, $params));
}
}
return parent::_prepareLayout();
}
And that’s about it.
The post 301 redirects vs canonical links in Magento appeared first on Inchoo.