0

Similar to Views: how to programmatically change Views title?, I want to update the title of a Views page using logic/data only possible in PHP.

However, I want this to update only the appropriate part of the <title> of the HTML <head> without mirroring the change in the displayed title in the <body>'s <h1 class="page-header">.

To illustrate, imagine a view with some exposed filters that are used for navigating a product catalogue. Currently, every filtering of this page has the same titles:

<title>Products | My site name</title>
...
<h1 class="page-header">Products</h1>

I've written some code requiring access to $view->exposed_input that generates an appropriate string based on exposed filter choices (for example, "red, low cost, good condition"), similar to Using exposed filters as part of the rendered page's title. I want these in the html head title, so each navigable URL has a unique title with appropriate keywords for the content. I don't want them in the <h1>, however, because they're already clearly visible in the exposed filter page UI and I don't want to duplicate the information. I want it to look like this:

<title>Products: red, low cost, good condition | My site name</title>
...
<h1 class="page-header">Products</h1>

Things I've tried:

  • Everything on that linked question applies to both the head and body titles

    <title>Products: red, low cost, good condition | My site name</title>
    ... 
    <h1 class="page-header">Products: red, low cost, good condition</h1>
    
  • drupal_set_title() doesn't work at all from any of the Views hooks I've tried, presumably because the view overrides this further down the line. I've tried:

    • hook_preprocess_views_view
    • hook_views_pre_render
    • hook_views_post_render
  • Setting $vars['head_title'] in hook_preprocess_views_view also doesn't work, presumably for the same reason: Views overrides this.

    • Someone commenting on the hook_views_post_render API page with the exact same problem as me 3 years ago reports that it still doesn't work if you pass the variable to through to hook_preprocess_html and apply it to $vars['head_title'] from there
1

I think what you're looking for is hook_preprocess_HOOK where HOOK is either html, page or both.

  • Just done some tests, hook_preprocess_html can override the view set title, hook_preprocess_page it seems can't; but the next problem is piping the string variable generated in the views hook using views data somewhere it'll be available within hook_preprocess_html. I've tried just attaching it to a custom key on the $vars variable within hook_preprocess_views_view but it's then not present within hook_preprocess_html for some reason. – user56reinstatemonica8 Jul 4 '17 at 19:35
  • Aha, cracked it: using a static variable function with a call that sets the variable in hook_preprocess_views_view (or any Views hook, really) and a call that gets the variable in hook_preprocess_html – user56reinstatemonica8 Jul 4 '17 at 19:46
0

It might be possible to do this through tokens and the Views UI if you have the Metatag module and its Metatag Views sub-module installed; one of the options in the Metatag box it adds to the Views interface is a title builder that applies only to the <head> <title>.

Unfortunately this isn't an option in this example because exposed filter selections aren't currently available as tokens. There is one module to allow this, but it's an unsupported experimental sandbox.


If it's not possible or practical to use tokens, after a lot of experimenting I found something that works on the PHP side:

Example code which can all go in the theme's template.php:

// variable getter and setter function, modified slightly from Clive's
function _something_var($var_name, $new_val = NULL) {
  $vars = &drupal_static(__FUNCTION__, array());

  if ($new_val != NULL) {
    $vars[$var_name] = $new_val;
  }
  return isset($vars[$var_name]) ? $vars[$var_name] : NULL;
}

// set the variable using data from the view object
function something_preprocess_views_view(&$vars) {
  $view = $vars['view'];

  if ( $view->name == 'something' ){
    $title_override = '...'; // do stuff with $view to generate title
    _something_var( 'title_override', $title_override );
  }
}

// get the variable after Views has finished setting its title
function something_preprocess_html(&$variables) {
  $title_override = _something_var( 'title_override' );

  if( $title_override ){
    $variables['head_title'] = $title_override . ' | ' . variable_get('site_name');    
  }
}
  • The example code above has caching issues. Unless you disable the render cache or set the view's caching setting to 'none' the something_preprocess_views_view hook only gets called the first time the page is accessed because the view gets cached for subsequent page views. So your custom page title will only appear on the first page view. – Richard Davies Nov 1 '18 at 20:33

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.