I want to create a small, custom Drupal 8 module to open all external links in the menu in a new tab, how can I do that?

I think I should use hook_link_alter to do it, but I don't know how to do it so I can select all the external links only?

  • Do you want all the external links, or only the ones in the menu?
    – Eyal
    Dec 18 '16 at 23:11
  • Not an answer but out of interest, what would the general opinion be of using jQuery to do this? Dec 19 '16 at 5:15

Links can be generated in a number of ways, which makes it hard to change consistently. For a single implementation that you want to reach most parts, you should swap the link_generator service with your own subclass. This should catch all menu items and links in general, but wont touch custom markup from wysiwyg. Here you would need to create a custom filter.

The ::generate($text, Url $url) method is what is used to actually create the create the HTML. What you want to do, it to add the _blank target attribute if the url is external.

The code for the link generator subclass, could look like this:

class MyLinkGenerator extends LinkGenerator {
  public function generate($text, Url $url) {
    if ($url->isExternal()) {
      $attributes = $url->getOption('attributes');
      $attributes['target'] = '_blank';
      $url->setOption('attributes', $attributes);
    return parent::generate($text, $url);

I wont go into how to change the class of a service, there is plenty of examples for this here and elsewhere.


If you want to use hook_link_alter you can also simply implement the following code in a module :

 * Implements hook_link_alter().
function mymodule_link_alter(&$vars) {
  if ($vars['options']['external'] == TRUE) {
    $vars['options']['attributes']['target'] = '_blank';
  • I tried to implement a module with the above code, but it crashes. I get a 'Notice: Undefined index: external' on the line of the if-statement. Searching around, I found a similar question (id: 213292). It has a nearly identical code, but the if-statement becomes: 'if ($vars['url']->isExternal())'. If I substitute the if-statement with the one found, code now doesn't crash but it does absolutely nothing. I tried clearing caches, also tried with external links in menu, in content type (via link field) and in the body of a basic page. It does nothing, link opens in same tab. Any clues?
    – thomas
    Oct 27 '18 at 21:14

extlink contrib module for Drupal 8 & 9 (also a D7 version) can do the job.

On the extlink contrib module project page it says:

Configure external links to open in a new window

And there is other functionality, too.

I've just started using this module and from tests so far, it does the job.

In my case it does actually open an external link in a new tab so even though it says new window, it actually opens in a new tab.

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.