Magento – Magento SEO implement rel=”prev” and rel=”next” meta tags

catalogmagento2paginationproductsseo

I'm attempting to improve SEO for my product catalog by implementing the <link rel='next' href='..'> and <link rel='prev' href='..'> head meta tags for catalog pages with several pages of items.

After searching around quite a bit, I found the following solution [Source] but no way to accomplish the same task in Magento 2.

How can I accomplish the same thing in Magento 2?

$actionName = $this->getAction()->getFullActionName();
if ($actionName == 'catalog_category_view') // Category Page
{
    $category = Mage::registry('current_category');
    $prodCol = $category->getProductCollection()->addAttributeToFilter('status', 1)->addAttributeToFilter('visibility', array('in' => array(Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_CATALOG, Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH)));
    $tool = $this->getLayout()->createBlock('page/html_pager')->setLimit($this->getLayout()->createBlock('catalog/product_list_toolbar')->getLimit())->setCollection($prodCol);
    $linkPrev = false;
    $linkNext = false;
    if ($tool->getCollection()->getSelectCountSql()) {
        if ($tool->getLastPageNum() > 1) {
            if (!$tool->isFirstPage()) {
                $linkPrev = true;
                if ($tool->getCurrentPage() == 2) {
                    $url = explode('?', $tool->getPreviousPageUrl());
                    $prevUrl = @$url[0];
                }
                else {
                    $prevUrl = $tool->getPreviousPageUrl();
                }
            }
            if (!$tool->isLastPage()) {
                $linkNext = true;
                $nextUrl = $tool->getNextPageUrl();
            }
        }
    }
    if ($linkPrev) echo '<link rel="prev" href="' . $prevUrl . '" />';
    if ($linkNext) echo '<link rel="next" href="' . $nextUrl . '" />';
}

Best Answer

I've found a workaround for magento2 to accomplish this, which I've published here, but for the sake of it being here should the gist go somewhere, I'll include the code below.

Basically, we just create a block that we include for catalog_category_view that checks the current selected category, and tries its best to figure out the paging.

There were some strange bugs in using the pager itself to generate the urls in which for some reason it wouldn't go past a certain page number if we had the limiting somewhat low (eg: 8 per page), and thus, workarounds were made.

If anyone has any suggestions or ways to improve this, i'd love to hear about it, but this works for now.

<?php

namespace Revival\Seo\Block;

use Magento\Framework\View\Element\Template;

/**
 * To make this appear in the header for the catalog, you'd need to add this as a block in ${THEME_DIR}/Magento_Catalog/layout/catalog_category_view.xml
 *
 * EG:
 *
 * <?xml version="1.0"?>
 * <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
 *  <body>
 *      <referenceBlock name="head.additional">
 *          <block class="Revival\Seo\Block\HeaderPagination" name="pagination" template="pagination.phtml">
 *          </block>
 *      </referenceBlock>
 *  </body>
 * </page>
 *
 * All that the phtml really does is call $this->getPageHeaders(), omitted for brevity.
 *
 */

class HeaderPagination extends \Magento\Framework\View\Element\Template {

    /** @var $registry \Magento\Framework\Registry */
    public $registry = null;
    /** @var  $catalog \Magento\Catalog\Model\Category */
    public $category = null;
    /** @var  $logger \Psr\Log\LoggerInterface */
    public $logger = null;
    /** @var $context \Magento\Framework\View\Element\Template\Context */
    public $context = null;
    /** @var $toolbar \Magento\Catalog\Block\Product\ProductList\Toolbar; */
    public $toolbar = null;
    /** @var $pager \Magento\Theme\Block\Html\Pager */
    public $pager = null;
    public function __construct(Template\Context $context, array $data = [],\Magento\Framework\Registry $registry, \Magento\Catalog\Block\Product\ProductList\Toolbar $toolbar, \Magento\Theme\Block\Html\Pager $pager)
    {
        parent::__construct($context, $data);
        if($registry == null){
            $this->_logger->debug("[!] Received null registry from DI!");
        }
        $this->context = $context;
        $this->registry = $registry;
        $this->category = $registry->registry('current_category');
        $this->toolbar = $toolbar;
        $this->pager = $pager;
    }


    public function getPageHeaders(){
        //set pager and toolbar to use same collection, make sure they're both in agreement as to page limiting
        $this->toolbar->setCollection($this->category->getProductCollection());
        $tool = $this->pager->setCollection($this->category->getProductCollection());
        $tool->setShowPerPage($this->toolbar->getLimit());
        $has_prev_page = $has_next_page = false;
        $next_page_url = $prev_page_url = '';

        //calculate last page, round down to nearest int, 4.9 pages still means only 4 pages.
        $last_page =  intval((($this->category->getProductCollection()->count() - 1) / $this->toolbar->getLimit()) + 1);
        $current_page = $this->toolbar->getCurrentPage();

        //don't show a previous page on the first page, or if the last page is 1.
        if($current_page != 1 && $this->toolbar->getLastPageNum() != 1){
            $has_prev_page = true;
            $params = $this->getRequest()->getParams();
            //remove ?id param for category identification.
            $params['id'] = null;
            $params[$tool->getPageVarName()] = $current_page-1;
            $prev_page_url = $this->toolbar->getPagerUrl($params);
            //$prev_page_url = $tool->getPreviousPageUrl();
        }
        //if our page isn't the last page, show the next one.
        if($current_page != $last_page){
            $has_next_page = true;
            $params = $this->getRequest()->getParams();
            //remove ?id param for category identification.
            $params['id'] = null;
            $params[$tool->getPageVarName()] = $current_page+1;
            $next_page_url = $this->toolbar->getPagerUrl($params);
            //$next_page_url = $tool->getNextPageUrl();
        }
        if($has_prev_page){
            echo "<link rel='prev' href='{$prev_page_url}'>". PHP_EOL;
        }
        if($has_next_page){
            echo "<link rel='next' href='{$next_page_url}'>". PHP_EOL;
        }
    }
}