0

I am trying to manually set the canonical URL on product pages.

To do so, I extended the Mage_Catalog_Block_Product_View class and modified the _prepareLayout method:

class FKoessler_MyProduct_Block_Product_View extends Mage_Catalog_Block_Product_View
{
  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 'paris_french':
                      $expCatIdStore = 2;
                      break;
                  case 'nimes_french':
                      $expCatIdStore = 3;
                      break;
                  case 'niort_french':
                      $expCatIdStore = 6;
                      break;
              }

              if ($expCatIdStore && $productId) {

                  $headBlock->removeItem('canonical');
                  if ($tmpStoreCode === 'paris_french') {
                      $cannURL = str_replace('/paris', '', $cannURL);
                      $headBlock->addLinkRel('canonical', $cannURL);
                  } elseif ($tmpStoreCode === 'nimes_french') {
                      $cannURL = str_replace('/nimes', '', $cannURL);
                      $headBlock->addLinkRel('canonical', $cannURL);
                  } elseif ($tmpStoreCode === 'niort_french') {
                      $cannURL = str_replace('/niort', '', $cannURL);
                      $headBlock->addLinkRel('canonical', $cannURL);
                  } else {
                      $headBlock->addLinkRel('canonical', $cannURL);
                  }
              }
              //////////////////////////////////// END WITH CANONICAL

          }
      }

      return Mage_Catalog_Block_Product_View::_prepareLayout();
  }

}

The canonical URL that I add manually is properly set.

The problem is that product pages now have two canonical links. The default one linking to the product page and the custom one that I added.

How can I replace the default canonical link instead of adding a new one?

EDIT:

Adding some debugging output, I notice that Magento enters both Mage_Catalog_Block_Product_View::_prepareLayout and FKoessler_MyProduct_Block_Product_View::_prepareLayout multiple times:

[Fri Jun 12 11:15:30.544350 2015] [:error] [pid 9972] [client 127.0.0.1:34926] Entering FKoessler_MyProduct_Block_Product_View::_prepareLayout
[Fri Jun 12 11:15:30.552185 2015] [:error] [pid 9972] [client 127.0.0.1:34926] Entering FKoessler_MyProduct_Block_Product_View::_prepareLayout
[Fri Jun 12 11:15:30.552931 2015] [:error] [pid 9972] [client 127.0.0.1:34926] Entering FKoessler_MyProduct_Block_Product_View::_prepareLayout
[Fri Jun 12 11:15:30.553767 2015] [:error] [pid 9972] [client 127.0.0.1:34926] Entering Mage_Catalog_Block_Product_View::_prepareLayout
[Fri Jun 12 11:15:30.554524 2015] [:error] [pid 9972] [client 127.0.0.1:34926] Entering FKoessler_MyProduct_Block_Product_View::_prepareLayout
[Fri Jun 12 11:15:30.556209 2015] [:error] [pid 9972] [client 127.0.0.1:34926] Entering FKoessler_MyProduct_Block_Product_View::_prepareLayout
[Fri Jun 12 11:15:30.557015 2015] [:error] [pid 9972] [client 127.0.0.1:34926] Entering FKoessler_MyProduct_Block_Product_View::_prepareLayout
[Fri Jun 12 11:15:30.562598 2015] [:error] [pid 9972] [client 127.0.0.1:34926] Entering FKoessler_MyProduct_Block_Product_View::_prepareLayout

That's why the regular Magento canonical link gets added too. How can I prevent that?

1

At the end of your method, you are running return parent::_prepareLayout() which is running the _prepareLayout of Mage_Catalog_Block_Product_View.

Instead, since you re-implemented the method from the catalog/product_view block, you should call the parent's parent _prepareLayout function. To do that, replace that last line of your method with:

return Mage_Catalog_Block_Product_Abstract::_prepareLayout();

This is also so that you don't run the same code twice.
Though, a better solution may be to disable canonical URL from the configuration, and implement your own.

  • class FKoessler_MyProduct_Block_Product_View extends Mage_Catalog_Block_Product_Abstract so return parent::_prepareLayout() is correct, right? – fkoessler Jun 9 '15 at 17:50
  • also, if I disable canonical URL from the configuration, I will loose the regular canonical links on all the other pages, and I want them – fkoessler Jun 9 '15 at 17:50
  • Extending the abstract class works as well, but you will have issues if you need fuctionality from Mage_Catalog_Block_Product_View. This will happen if you added a <rewrite> rule in your config for that block to use yours instead. – Dan Jun 9 '15 at 17:58
  • As for your second comment, you can disable canonical urls just for products. But keep them on for categories. – Dan Jun 9 '15 at 18:01
  • I want to keep on using Magento's canonicals and modify them to always point to the main store, that's why I need to keep canonical URL enabled. – fkoessler Jun 12 '15 at 9:19
1

The problem arises because Magento enters the _prepareLayout methods of both Mage_Catalog_Block_Product_View::_prepareLayout and FKoessler_MyProduct_Block_Product_View::_prepareLayout.. Go figure why

So the trick is to first remove the canonical links with $headBlock->removeItem before adding them back with $headBlock->addLinkRel:

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 'paris_french':
                $expCatIdStore = 2;
                break;
            case 'nimes_french':
                $expCatIdStore = 3;
                break;
            case 'niort_french':
                $expCatIdStore = 6;
                break;
        }

        if ($expCatIdStore && $productId) {
            $headBlock->removeItem('link_rel', $cannURL);
            if ($tmpStoreCode === 'paris_french') {
                $cannURL = str_replace('/paris', '', $cannURL);
                $headBlock->addLinkRel('canonical', $cannURL);
            } elseif ($tmpStoreCode === 'nimes_french') {
                $cannURL = str_replace('/nimes', '', $cannURL);
                $headBlock->addLinkRel('canonical', $cannURL);
            } elseif ($tmpStoreCode === 'niort_french') {
                $cannURL = str_replace('/niort', '', $cannURL);
                $headBlock->addLinkRel('canonical', $cannURL);
            } else {
                $headBlock->addLinkRel('canonical', $cannURL);
            }
        }
        //////////////////////////////////// END WITH CANONICAL

    }
}

return Mage_Catalog_Block_Product_Abstract::_prepareLayout();
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.