[Magento] Google SEO-friendly Layered Navigation

Data dodania wpisu: 10-07-2010


It is already known, that Magento's SEO is not amazing. That's the reason why I do some pieces of code to make it better:) Here is an another solution, which allows Magento have different titles and descriptions (metadata) in the category sub-pages while layered navigation is in use. By default, there's no matter how many times we will pass filtering by products attributesmetadata will always remain the same and this is one of the common reason for Google to consider these pages as a duplicate content;)



Just put in the following code into the file:




While using this method, all the active filters names and values of current navigation layer are passed to the variable $layerFilters. In addition, this method supports such values as the sort and pagination variables.

    public $layerFilters;
    public $currentFilters;
    public $orderBy;
    public $currentPage;
    public function getLayersMeta(){

        $this->layerFilters = '';
        $state_block = $this->getLayout()->createBlock("catalog/layer_state");
        $this->currentFilters = $state_block->getActiveFilters();

        if(!empty($this->currentFilters)) {
            foreach($this->currentFilters as $filter) {

                $this->layerFilters .= ($this->layerFilters!='') ? ', '.$filter->getName() : $filter->getName();

                $attribute = Mage::getModel('eav/config')->getAttribute('catalog_product', $filter->getFilter()->getRequestVar());
                foreach($attribute->getSource()->getAllOptions(true, true) as $option) {
                    if($filter->getValue() == $option['value']) {
                        $this->layerFilters .= ' - '.strtr($option['label'],array('"'=>"''"));
            $this->layerFilters = ($this->layerFilters!='') ? $this->__('Shopping by: ').$this->layerFilters.' - ' : '';

        $this->orderBy = '';

        if($this->getRequest()->getParam('order') && $this->getRequest()->getParam('dir')) {
            $this->orderBy .= $this->__('Sort by ').$this->__(htmlspecialchars($this->getRequest()->getParam('order')));
            $this->orderBy .= (htmlspecialchars($this->getRequest()->getParam('dir')) == 'asc') ? ', '.$this->__('ascending') : ', '.$this->__('descending');

        if($this->getRequest()->getParam('limit') && is_numeric($this->getRequest()->getParam('limit'))) {
            $this->orderBy .= (($this->orderBy!='') ? ', ' : $this->__('show')).' '.$this->getRequest()->getParam('limit').' '.$this->__('per page');
        if($this->getRequest()->getParam('p') && is_numeric($this->getRequest()->getParam('p'))) {
            $this->currentPage = $this->__('Page').' '.$this->getRequest()->getParam('p').' - ';

        $this->orderBy = ($this->orderBy!='') ? $this->orderBy.' - ' : '';

        return $this->layerFilters.$this->orderBy.$this->currentPage;


Next step will by slight modification of two methods in the same file (getDescription() oraz getTitle()) in this way:

public function getDescription()
        if (empty($this->_data['description'])) {
            $this->_data['description'] = Mage::getStoreConfig('design/head/default_description');
        return $this->getLayersMeta().$this->_data['description'];


    public function getTitle()
        if (empty($this->_data['title'])) {
            $this->_data['title'] = $this->getDefaultTitle();
        return $this->getLayersMeta().htmlspecialchars(html_entity_decode(trim($this->_data['title']), ENT_QUOTES, 'UTF-8'));


Thankfully, we got absolutely unique metadata in category products list according to layer and sorting filters. Example of usage this modification can be found in an online bike shop 123bikes.eu ie. in category mountain bikes.


There is no problem to use this code to generate random content in a category page (like in 123bikes.eu between category images and product list). That's another unique content for Google :)


Let the Magento SEO power grows up! :)


NOTE: The code above has been developed while v. 1.3.2 was the latest one. I don't know whether it works fully with all the latest Magento's revisions - if anyone can confirm such thing or deliver me the working solution - it would be great. Actually I have no free time to check such thing myself. Any help appreciated (I'll put your credits here and a backlink to your website)! :-)


Hi there.
@Jason M : I confirm.

I have a small problem with this code,it works wonderful,except that im having 2 languages available on my website and this code shows only main-language filter-names. How can i get filters translation ?
Can anyone confirm this works on 1.6.0?
thank for code.

Great post!
@Magento: Did you modify the file in 'core' app directory? Check out, if the filepath you've changed is correct for 'local' app directory ;)
In Magento ver.
display error:
Fatal error: Cannot redeclare Mage_Page_Block_Html_Head::getDescription() in
Thanks for the Information. It helps me a lot.

thanks for this entry. What do you think about the following issue:

1. fixed URL hubs for the layered navigation elements in an specified ordering +
2. the posibility to place special category text for each hub that is builed out of the layered navigation ?

That would be amazing with your edits in common.

All the best,
Thanks for the information. Great post!
Thanks for this tip, I will try to implement it into my Magento Webshop!

Grtz from Holland
Very interessting. But another question: How is it possible to add the canonical tag for categoriesite 2 like "...../junior-bikes/kid-bikes?p=2/". If i enable the canonical tag for categories in magento, it will look like this "...../junior-bikes/kid-bikes" no matter if its categorysite 1, 2, 3 or 500.
hello.I haved translated your article to chinese.Thank you for sharing
"SEO optimization"... do you know what SEO means?
Hi Again,
I think that the price attribute options (the range itself) is not showing in meta. It\'s also not showing in the demo sample you showed as a reference. Any ideas how to show it correctly as the option itself (as this is the most used filter, and it will create a duplicate content issue).
Hi and Thanks,
I've implemented it successfully and it working, but how can I add the actual attribute vlaues to the meta desc/title? Since in the current status, if one clicks on either one of the price ranges, the meta tags are identical since the actual price range (lables) are not inserted... so still it would act as duplicate meta title according to the SE's.
I have tried doing it myself but as I am not a programmer, I could not find the getLabel of the actual attribute and to implement it.

Can you help with that?
Thanks a lot.
Thanks for a great contribution!
I was wondering if / how / what code will also make the same impact while using the layered navigation. I think that the best approach to do this would be according the label of the attribute in the store view ( I'm not a coder, just know how to "dig").
Can you help on this one or is it too complicated (mag
There is NO MISTAKE :)
Magento has three common code "namespaces". These are: community, core and local.
So I must say - you're wrong;)
On the other hand, I've got no idea, why you had a blank screen, however I see, that it's workin' right now in you web store.
I follow your instructions step by step, but after applying modifications and refrshing the cache, i got a beautifull error : admin and frontend are blank :s
Our Magento is a ver., is it something wrong ?

Last thing, there is a mistake on the first step of this tip.
I think the right directory is :
and not
First of all, who told about new URLs in here? :) This article tells about making layered navigation a little bit more efficient for SEO - there is no way to re-generate new links coz these are the content were working on :)
very cool, but how do we get the new links into the google sitemap automaticly?

sure there's no problem with including pagination in the metadata:)

Just put into the getLayersMeta() method a few lines of code:

if($this->getRequest()->getParam('p') &&
is_numeric($this->getRequest()->getParam('p'))) {
$this->currentPage = $this->__('Page').' ';
$this->currentPage .= $this->getRequest()->getParam('p').' - ';

Function in this post is up to date, so copy into your Head.php and have fun with Google:)

Hi there, I read your post and tested the update for layered navigation. It really works well, I am impressed. Thank you.

However I was wondering if you could maybe post some information about how to do the same for pagination variables.

Thanks for the information. Great post!
Comments closed...

DesignEnd on Facebook