Is there an existing solution to add the rel="next" and link rel="prev" to paginated views? It seems to be a best practice suggested by Google for indexing.

I have looked around and cannot find a reference to an existing solution. Any assistance would be appreciated.

Comments

merlinofchaos’s picture

Status: Active » Fixed

Presumably you mean the pager links? For the most part that's handled by Drupal's own theme('pager') unless you're using the mini pager, which is theme('views_mini_pager') and can be modified simply by implementing the correct theme function and adding what is needed to the links.

sammyframson’s picture

Thanks for your prompt reply. I am actually talking about adding the <link rel="next" a href="/example?page=2"> to the head for SEO purposes as an alternative to the canonical meta data. In reference to the Google Webmaster best practice shown here: http://googlewebmastercentral.blogspot.co.uk/2011/09/pagination-with-rel....

On the first page, http://www.example.com/article?story=abc&page=1, you’d include in the <head> section:
<link rel="next" href="http://www.example.com/article?story=abc&page=2" />

On the second page, http://www.example.com/article?story=abc&page=2:

<link rel="prev" href="http://www.example.com/article?story=abc&page=1" />
<link rel="next" href="http://www.example.com/article?story=abc&page=3" />

Maybe I am asking in the wrong place and this would be more appropriate for a module like nodewords?

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

MartinSpence’s picture

Did you get sorted with this?

What was the solution?

Thanks
M

Seven_Six_Two’s picture

There is similar functionality needed for Pagination module, so perhaps this should be done elsewhere? I'm not sure if it merits an individual module, but how about a call to drupal_add_html_head()?

skat’s picture

subscribing

pixelsweatshop’s picture

skat use the follow button at the top of the thread to follow issues.

lfboulanger’s picture

I found a way to do it with hook_views_post_execute() :

function bl_various_views_post_execute(&$view) {
    if ($view->pager['use_pager'] == '1') {
        $current_page = $view->pager['current_page'];
        $items_per_page = $view->pager['items_per_page'];

        $lastItemViewed = ($current_page * $items_per_page) + $items_per_page;

        global $base_url;

        if ($current_page != 0) {
            // add rel="prev" link
            $url = $_SERVER['REQUEST_URI'];
            $url = bl_various_setPageInURL($url, $current_page - 1, $current_page);
            $url = $base_url . $url;
            drupal_set_html_head('<link rel="prev" href="' . $url . '" />');
        }

        if ($view->total_rows > $lastItemViewed) {
            // Add rel="next" link
            $url = $_SERVER['REQUEST_URI'];
            $url = bl_various_setPageInURL($url, $current_page + 1, $current_page);
            $url = $base_url . $url;
            drupal_set_html_head('<link rel="next" href="' . $url . '" />');
        }
    }
}

function bl_various_setPageInURL($url, $page, $curPage) {


    if ($curPage == 0) {
        if (strpos($url, '?') !== FALSE) {
            $url .= '&page=' . $page;
        } else {
            $url .= '?page=' . $page;
        }
    } else {
        if ($page != 0) {
            $url = str_replace('page=' . $curPage, 'page=' . $page, $url);
        } else {
            $url = str_replace('page=' . $curPage, '', $url);
            if (substr($url, -1) === '?') {
                $url = str_replace('?', '', $url);
            }
        }
    }

    return $url;
}
nlisgo’s picture

Issue summary: View changes

Here's a solution for D7:


/**
 * Implements hook_views_post_execute().
 *
 * If there is a pager display output rel links
 * @see https://support.google.com/webmasters/answer/1663744?hl=en
 */
function elife_core_views_post_execute(&$view) {
  // @todo - this solution only works if we can expect one pager per page.
  if ($view->display[$view->current_display]->handler->use_pager()) {
    $current_page = $view->query->pager->current_page;
    $items_per_page = $view->query->pager->options['items_per_page'];
    $last_item_viewed = ($current_page * $items_per_page) + $items_per_page;
    // Prepare link rel=prev if current page > 0.
    if ($current_page > 0) {
      if ($current_page > 1) {
        $parameters = array(
          'page' => $current_page - 1,
        );
      }
      else {
        $parameters = array();
      }
      $query = drupal_get_query_parameters($parameters, array());
      if ($query_pager = pager_get_query_parameters()) {
        $query = array_merge($query, $query_pager);
      }
      $head_link = array(
        'rel' => 'prev',
        'href' => url(
          $_GET['q'],
          array(
            'query' => $query,
          )
        ),
      );
      drupal_add_html_head_link($head_link);
    }
    // Prepare link rel=next if more pages available.
    if ($view->query->pager->total_items > $last_item_viewed) {
      $parameters = array(
        'page' => $current_page + 1,
      );
      $query = drupal_get_query_parameters($parameters, array());
      if ($query_pager = pager_get_query_parameters()) {
        $query = array_merge($query, $query_pager);
      }
      $head_link = array(
        'rel' => 'next',
        'href' => url(
          $_GET['q'],
          array(
            'query' => $query,
          )
        ),
      );
      drupal_add_html_head_link($head_link);
    }
  }
}

nlisgo’s picture

This is the final solution that I went with. The abstraction of the mymodule_core_set_rel_links and mymodule_core_prep_rel_links makes the code more testable and reusable.


/**
 * Implements hook_views_post_execute().
 *
 * If there is a pager display output rel links
 * @see https://support.google.com/webmasters/answer/1663744?hl=en
 */
function mymodule_views_post_execute(&$view) {
  // @todo - only works if we can expect one pager per page.
  if ($view->display[$view->current_display]->handler->use_pager()) {
    $current_page = $view->query->pager->current_page;
    $items_per_page = $view->query->pager->options['items_per_page'];
    $last_item_viewed = ($current_page * $items_per_page) + $items_per_page;
    $total_items = $view->query->pager->total_items;
    mymodule_set_rel_links(current_path(), $current_page, $last_item_viewed, $total_items);
  }
}

/**
 * Set the rel links in html head.
 *
 * @param string $current_path
 *   Path of current page.
 * @param int $current_page
 *   The current page number starts with 0.
 * @param int $last_item_viewed
 *   The number of the last item on display on this page.
 * @param int $total_items
 *   The total number of items in the results.
 */
function mymodule_set_rel_links($current_path, $current_page, $last_item_viewed, $total_items) {
  $head_links = mymodule_prep_rel_links($current_path, $current_page, $last_item_viewed, $total_items);
  foreach ($head_links as $head_link) {
    drupal_add_html_head_link($head_link);
  }
}

/**
 * Prepare the rel links for html head.
 *
 * @see mymodule_set_rel_links()
 *
 * @param string $current_path
 *   Path of current page.
 * @param int $current_page
 *   The current page number starts with 0.
 * @param int $last_item_viewed
 *   The number of the last item on display on this page.
 * @param int $total_items
 *   The total number of items in the results.
 *
 * @return array
 *   Array of rel links to add to html head.
 */
function mymodule_prep_rel_links($current_path, $current_page, $last_item_viewed, $total_items) {
  // Prepare link rel=prev if current page > 0.
  $head_links = array();
  if ($current_page > 0) {
    if ($current_page > 1) {
      $parameters = array(
        'page' => $current_page - 1,
      );
    }
    else {
      $parameters = array();
    }
    $query = drupal_get_query_parameters($parameters, array());
    if ($query_pager = pager_get_query_parameters()) {
      $query = array_merge($query, $query_pager);
    }
    $head_link = array(
      'rel' => 'prev',
      'href' => url(
        $current_path,
        array(
          'query' => $query,
        )
      ),
    );
    $head_links[] = $head_link;
  }
  // Prepare link rel=next if more pages available.
  if ($total_items > $last_item_viewed) {
    $parameters = array(
      'page' => $current_page + 1,
    );
    $query = drupal_get_query_parameters($parameters, array());
    if ($query_pager = pager_get_query_parameters()) {
      $query = array_merge($query, $query_pager);
    }
    $head_link = array(
      'rel' => 'next',
      'href' => url(
        $current_path,
        array(
          'query' => $query,
        )
      ),
    );
    $head_links[] = $head_link;
  }

  return $head_links;
}
nlisgo’s picture

Version: 6.x-3.0-rc3 » 7.x-3.x-dev
Status: Closed (fixed) » Active

I wanted to see if there was any appetite to take this task. We have some examples of implementations.

Although views is not the only module that uses pagination, it is not the case that we would want the rel links introduced into the head for all paginated content. If for instances the main content of the page is not a listing but there is a block in the sidebar with a pager we would not want that blocks' next and previous links to be considered the next and previous content relevant to this page.

If we have a view that is a page display with pagination then it may be appropriate to assume that we would want the next and previous content to be the pages accessed by the next and previous link of that view.

So, the feature I am proposing is that we automatically introduced the
and
into the head if the view display is page. And we allow the user to deselect this as an option in the pager interface.

For other view displays the default is to have this option deselected and we introduce it if the user makes the decision to select it in the pager interface.

merlinofchaos’s picture

I think the 'correct' way to do this would be:

1) Implement this as a separate module.
2) Implement a new pager plugin, presumably as a child of views_plugin_pager_full.
3) Handle all of your stuff from within the pager plugin rather than as a views hook.
4) Put your module up in contrib where all can benefit from it if it is a feature they want.

nlisgo’s picture

I can't argue with that. It was really only to test the waters. I needed to implement it on our site and the solution in #8 helped me out and it would be a shame if a solution can't be contributed back in some way. The majority of use cases would be in a views pager.

Feel free to close. Happy to contribute as a separate module if no desire to implement it here.

nlisgo’s picture

Status: Active » Closed (won't fix)

Just rushed together a module that can do what is described in #12. Not sure on the name yet: nextprev_links. Will post module up to d.o. shortly. It's on github for now.

https://github.com/nlisgo/nextprev_links

larsmw’s picture

This #14 seems to work nicely. Is there a version here on d.o yet?

nlisgo’s picture

@larsmw I've posted it as a sandbox project. I'm stalling from posting as a full project until I'm happy with the name of the module. Please give feedback on the module name and anything else.

https://www.drupal.org/sandbox/nlisgo/2361421

bewilled’s picture

#14 didn't work for me for views+search api

heyyo’s picture

I would like to use your code for an infinite pager provided by views_infinite_scroll or views_show_more.
Any guideline is welcome.

nlisgo’s picture

@heyyo - if views_infinite_scroll and views_show_more offer their own pager plugins then patches to their module will need to be made to add the option to output the the rel next and prev links. The next step would be to raise an issue on those projects, if one doesn't exist already, to request this enhancement. Add a reference to my sandbox project as a possible solution.

The weakness of the module that I have developed is that it prepares a new pager plugin rather than extend the existing pager plugins to introduce this option. I don't know that this is a possibility, I have an odea of how to make it work but I want to make sure that I do it in the best way possible and it will continue to work well with ctools for exporting and importing views.

This is why I initially proposed that it be added to the views project itself because that seemed to be the approach that made the ux make most sense. You enable my module and you just get new options for pagers.

@bewilled if you could provide more information I could try to off you some support.

tanmoy1981’s picture

I solved this by using theme_pager_link().
Here follows the solution.

function YOURTHEME_pager_link($variables) {
  $text = $variables['text'];
  $page_new = $variables['page_new'];
  $element = $variables['element'];
  $parameters = $variables['parameters'];
  $attributes = $variables['attributes'];

  $page = isset($_GET['page']) ? $_GET['page'] : '';
  if ($new_page = implode(',', pager_load_array($page_new[$element], $element, explode(',', $page)))) {
    $parameters['page'] = $new_page;
  }

  $query = array();
  if (count($parameters)) {
    $query = drupal_get_query_parameters($parameters, array());
  }
  if ($query_pager = pager_get_query_parameters()) {
    $query = array_merge($query, $query_pager);
  }

  // Set each pager link title.
  if (!isset($attributes['title'])) {
    static $titles = NULL;
    if (!isset($titles)) {
      $titles = array(
        t('« first') => t('Go to first page'),
        t('‹ previous') => t('Go to previous page'),
        t('next ›') => t('Go to next page'),
        t('last »') => t('Go to last page'),
      );
    }
    if (isset($titles[$text])) {
      $attributes['title'] = $titles[$text];
    }
    elseif (is_numeric($text)) {
      $attributes['title'] = t('Go to page @number', array('@number' => $text));
    }
    // Add rel attribute.
    if ($text == t('‹ previous')) {
      $attributes['rel'] = 'prev';
    }
    elseif ($text == t('next ›')) {
      $attributes['rel'] = 'next';
    }
  }

  // @todo l() cannot be used here, since it adds an 'active' class based on the
  //   path only (which is always the current path for pager links). Apparently,
  //   none of the pager links is active at any time - but it should still be
  //   possible to use l() here.
  // @see http://drupal.org/node/1410574
  $attributes['href'] = url($_GET['q'], array('query' => $query));
  return '<a' . drupal_attributes($attributes) . '>' . check_plain($text) . '</a>';
}
flocondetoile’s picture

solution in #10 works fine
thanks @nlisgo

cakka’s picture

solution #10 work good
you only need to write a new module or add the codes to your custom module

tr-drupal’s picture

Hi all,

I'm not a drupal developer, so no idea what to do with #10. Is this the latest status of this issue? How far is the sandbox module in #16? Still nothing final / stable?

mgifford’s picture

Why can't this be part of Views? Is there any reason for it to be a module rather than just part?

Just looking for a better explanation for "Closed (won't fix)".

nlisgo’s picture

@mgifford see #12

vaccinemedia’s picture

#10 does not work if you have the metatag module installed

phandolin’s picture

One more request for this feature. I have metatags installed and cannot get this to work. Thanks!

sagesolutions’s picture

I also have metatags module installed, and this module conflicts with metatags, and doesnt output the head link(s).

vaccinemedia’s picture

If you need prev / next links see this alternative solution: https://www.drupal.org/node/2502453

nlisgo’s picture

I will see if I can do an update to that module over the next couple of days so it doesn't conflict with the metatag module :)

nlisgo’s picture

If you are having issues with the nextprev_links module working with metatags module please head over to the following issue to add clear recreate steps and to test a possible fix when I post it up later:

#2613216: Module doesn't work with metatags module enabled

swilmes’s picture

Hi, just wondering if anyone had a way to add the tags rel="next" and rel="prev" tags to search pages? The code above here works great for views but not for searches through the Search API. Thanks!

glass.dimly’s picture

Version: 7.x-3.x-dev » 8.x-3.x-dev
Category: Feature request » Bug report
Status: Closed (won't fix) » Active

I'm with @mgifford on this. I think this should be a part of Views core because it's a part of Google's official recommendations for pagination.

Source:

Use rel="next" and rel="prev" links to indicate the relationship between component URLs. This markup provides a strong hint to Google that you would like us to treat these pages as a logical sequence, thus consolidating their linking properties and usually sending searchers to the first page.

I'm therefore re-opening this and classifying as a bug rather than a feature on version 8x where development is more active because as it stands Views pagination is not conformant with Google's SEO best practices. Module maintainers may disagree and change the status of this ticket.

Lendude’s picture

Title: Adding rel="next" and rel="prev" to paginated views » Adding rel="next" and rel="prev" metatags to paginated views pages
Project: Views (for Drupal 7) » Drupal core
Version: 8.x-3.x-dev » 8.2.x-dev
Component: page displays » views.module
Category: Bug report » Feature request

Moving to the right queue.

Views pagination is not conformant with Google's SEO best practices

Since core doesn't provide any metatags, I'm pretty sure this isn't enough to make this a bug.

Issues I see just from the top of my head:
- Multiple pagers on a single page (multiple Views blocks on a page with a page View! Fun!)
- Ajaxified pagers, what to do? (crawlers with javascript support vs. crawlers without? head doesn't match content after using the pager?)

I would say contrib along the lines of what @nlisgo did in #14/#16 sounds like the way to go to me.

But I can totally see the use cases for this, so lets leave it open as a feature request, who knows....

nlisgo’s picture

Thanks for this intervention @Lendude. I'm happy for this to live in contrib at present but will propose that it be adopted into core if and when we address some of the issues in your comment. It was really good to meet you at Dev Days last week.

milodesc’s picture

RE #19:

if views_infinite_scroll... offer their own pager plugins...

it does.

then patches to their module will need to be made to add the option to output the the rel next and prev links. The next step would be to raise an issue on those projects, if one doesn't exist already, to request this enhancement. Add a reference to my sandbox project as a possible solution.

there is an issue for Views Infinite Scroll here: https://www.drupal.org/node/2283415

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

TechnoTim2010’s picture

Hi

I took a completely different approach to this, mainly because we need a solution for multiple websites, each built different ways with some pages created in views, some as node listings, some as Taxonomy Term pages and some as Search and Apache Solr search results.

So I created a token that calculates the value for the url part of the metatag link and specifically the page numbers or not for the rel="prev" rel="next" metatags.
This can then be added into to the metatags settings as a token and used as is.

However it does not work on any Taxonomy Term pages and even when overridden by Views, and I have ascertained that the global $pager_total_items and by derivation the $pager_total variables are empty.

I cannot fathom why they are empty and since one site only has Taxonomy term pages as paged pages this is a pain.

When I have it cleaned up will share the code for this token, I think its a cleaner approach, but need a solution for Taxonomy Terms.

regards

Tim

benjen’s picture

@TechnoTim2010: Would you please share your solution (even if it still does not support all view types)? I would appreaciate this!
Thank you.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

rahul_sankrit’s picture

Thanks nlisgo , #10 is working good as expected for me.

In my case, I have created a custom module and implemented that code.

DiDebru’s picture

I achieved this with this hook in D8.2.7

/**
 * Implements hook_page_attachments_alter().
 */
function my_module_base_page_attachments_alter(array &$attachments) {  
  global $pager_total, $pager_page_array;
  $current_path = Url::fromRoute('<current>');
  $path = $current_path->toString();
  if ($path == '/startseite') {
    $path = '/';
  }
  if ($pager_page_array[0] == 1) {
    $prev = '';
  }
  else {
    $prev = '?page=' . $page = $pager_page_array[0] - 1;
  }
  if ($pager_page_array[0] == 0) {
    $attachments['#attached']['html_head'][] = [[
      '#type' => 'html_tag',
      '#tag' => 'link',
      '#attributes' => [
        'rel' => 'next',
        'href' => $path . '?page=' . $next = $pager_page_array[0]+1,
      ],
    ], 'rel_next_first'];
  }
  if ($pager_page_array[0] != 0 && $pager_page_array[0]+1 != $pager_total[0]) {
    $attachments['#attached']['html_head'][] = [[
      '#type' => 'html_tag',
      '#tag' => 'link',
      '#attributes' => [
        'rel' => 'next',
        'href' => $path . '?page=' . $next = $pager_page_array[0]+1,
      ],
    ], 'rel_next'];
    $attachments['#attached']['html_head'][] = [[
      '#type' => 'html_tag',
      '#tag' => 'link',
      '#attributes' => [
        'rel' => 'prev',
        'href' => $path . $prev,
      ],
    ], 'rel_prev'];
  }
  if ($pager_page_array[0]+1 == $pager_total[0]) {
    $attachments['#attached']['html_head'][] = [[
      '#type' => 'html_tag',
      '#tag' => 'link',
      '#attributes' => [
        'rel' => 'prev',
        'href' => $path . $prev,
      ],
    ], 'rel_prev_last'];
  }  
}
semjuel’s picture

Solution #42 works great, thanks @Insasse!

burshyn’s picture

burshyn’s picture

Solution # 10 works fine with drupal 7!
Thanks @nlisgo!

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

kamy@cool’s picture

I tried #20 but it haven't affected the head section of the page, So I made a bit change in the code and it worked in D7
//implement this hook in template.php

function theme_name_pager_link($variables) {

$text = $variables['text'];
$page_new = $variables['page_new'];
$element = $variables['element'];
$parameters = $variables['parameters'];
$attributes = $variables['attributes'];

$page = isset($_GET['page']) ? $_GET['page'] : '';
if ($new_page = implode(',', pager_load_array($page_new[$element], $element, explode(',', $page)))) {
$parameters['page'] = $new_page;
}

$query = array();
if (count($parameters)) {
$query = drupal_get_query_parameters($parameters, array());
}
if ($query_pager = pager_get_query_parameters()) {
$query = array_merge($query, $query_pager);
}

// Set each pager link title.
if (!isset($attributes['title'])) {
static $titles = NULL;
if (!isset($titles)) {
$titles = array(
t('« first') => t('Go to first page'),
t('‹ previous') => t('Go to previous page'),
t('next ›') => t('Go to next page'),
t('last »') => t('Go to last page'),
);
}
if (isset($titles[$text])) {
$attributes['title'] = $titles[$text];
}
elseif (is_numeric($text)) {
$attributes['title'] = t('Go to page @number', array('@number' => $text));
}
// Add rel attribute.
if ($text == t('‹ previous')) {
$attributes['rel'] = 'prev';
drupal_add_html_head_link(array('rel' => 'prev', 'href' => url($_GET['q'], array('query' => $query))));
}
elseif ($text == t('next ›')) {
$attributes['rel'] = 'next';
drupal_add_html_head_link(array('rel' => 'next', 'href' => url($_GET['q'], array('query' => $query))));
}
}

// @todo l() cannot be used here, since it adds an 'active' class based on the
// path only (which is always the current path for pager links). Apparently,
// none of the pager links is active at any time - but it should still be
// possible to use l() here.
// @see http://drupal.org/node/1410574
$attributes['href'] = url($_GET['q'], array('query' => $query));
return '' . check_plain($text) . '';
}

codechefmarc’s picture

#10 works perfectly! Thank you!

Jaesin’s picture

The following works for me in D8.

/**
 * Implements hook_preprocess_pager().
 */
function example_preprocess_pager(&$pager) {
  $current_path = \Drupal\Core\Url::fromRoute('<current>');
  $path = $current_path->toString();

  // Correct for first page actually being page 0.
  $current_page = $pager['current'] - 1;
  // Parse the last page link to get the total number of pages.
  $total_pages = preg_replace('/^.*page=(\d+).*$/', '$1', $pager['items']['last']['href']);

  // Use the base path if on page 2 otherwise `page={{current_page-1}}`.
  $prev_href = ($current_page == 1 ? $path : ($current_page > 1 ? $path . '?page=' . ($current_page-1) : NULL));
  $next_href = $current_page < $total_pages ? $path . '?page=' . ($current_page + 1) : NULL;

  // Add The prev rel link.
  if ($prev_href) {
    $pager['#attached']['html_head_link'][] = [
      [
        'rel' => 'prev',
        'href' => $prev_href,
      ],
      TRUE,
    ];
  }

  // Add the next rel link.
  if ($next_href) {
    $pager['#attached']['html_head_link'][] = [
      [
        'rel' => 'next',
        'href' => $next_href,
      ],
      TRUE,
    ];
  }
}

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

nikhileshpaul’s picture

Solution #42 works perfectly. Thanks.
For solution #49, @Jaesin can you explain how are you able to get the hook hook_preprocess_pager. I don't think such a hook exists

vinyl_roads’s picture

#42 seems to work but I had to replace :

$current_path = Url::fromRoute('<current>');

By

$current_path = \Drupal\Core\Url::fromRoute('<current>');

And I need to disable cache in Views otherwise the module didn’t update the attribute.

p4trizio’s picture

#42 & #49 works fine for me as long as big_pipe is not enabled
Does anybody have the same problem as mine?

EDIT: The pager is in a Views block

Mikhail Stebenkov’s picture

del.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Joe Huggans’s picture

#49 worked for me

Joe Huggans’s picture

I have just found an error which occurs when using #49 - Undefined index: last, from this line in the code.

$total_pages = preg_replace('/^.*page=(\d+).*$/', '$1', $pager['items']['last']['href']);

This line gets the number of pages from looking at the value in the last href pager link, however $pager['items']['pages'] can be used to get this value instead, since $pager['items']['last' doesn't exist for me, so I have replaced this line with -

$total_pages = count($pager['items']['pages']) - 1;

Lendude’s picture

Can we mark this 'closed (outdated)'? Happy to leave this open if people still find this relevant, but the odds of getting this into core have not gone up.
https://yoast.com/google-doesnt-use-rel-prev-next-for-pagination/

jordan8037310’s picture

While Google doesn't use rel prev/next for pagination, most other search engines do.

[1] reference: https://www.searchenginejournal.com/seo-friendly-pagination/275557/ - Reference the Tweet from a Bing search developer who claims they still use this markup.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Frank Pfabigan’s picture

this thread is important for seo aspects. read more about "seo-friendly pagination". altough google says that prev-/next isn't used anymore, google does not index all the paginated pages as you can see in google-searchconsole.
google treats a paginated page the same as a "normal" page.

so a paginated page also must have:

  1. a unique title (result page 2 [page title] | [site:name])
  2. a unique canonical url: mysite.com/cases/cases-page-2
  3. an automated meta-description (not duplicate to root description) would be super
  4. prev / next metatags would be nice (for other se than google)
  5. robots.txt must fit the above circumstances

please give us the tools to unleash the power of paginated pages that are not in the index :-)
this involves views, drupal-core, breadcrumb, metatag module, token module and some other.

to ensure that everybody involved has the same knowledge-base, i suggest this lecture:
https://www.searchenginejournal.com/technical-seo/pagination/#close

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Dubs’s picture

Thanks @Jaesin for the code in #49. Here's a slightly different approach which uses the items and links already in the pager: -

/**
 * Implements hook_preprocess_pager().
 */
function example_preprocess_pager(&$pager) {
  try {
    $url = \Drupal\Core\Url::fromRoute('<current>');
    $url->setOption('absolute', TRUE);
    $path = $url->toString();
    $items = [
      'prev' => 'previous',
      'next' => 'next',
    ];
    foreach ($items as $rel => $item) {
      if (!empty($pager['items'][$item])) {
        $pager['#attached']['html_head_link'][] = [
          [
            'rel' => $rel,
            'href' => $path . $pager['items'][$item]['href'],
          ],
          TRUE,
        ];
      }
    }
  }
  catch (\Throwable $ex) {
    // do nothing, but don't crash out
  }
}
prudloff’s picture

#64 was not working for us because the view block was using a lazy builder.
We had to do something like this to make it work: https://www.drupal.org/project/drupal/issues/2769953#comment-12561253

prudloff’s picture

Since this looks like it could useful to other people, I create a contrib module for this: https://www.drupal.org/project/pager_metadata

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Lendude’s picture

Status: Active » Closed (outdated)

Since there is a contrib module for this, and Google stopped using this years ago, I going to close this as outdated. If somebody has any new information that this is still something we should do in core, feel free to reopen this.

Thanks everybody that helped others that needed this over the years!