External Links in Menues

As soon as you start digging into ways to make your site speedier and safer and “win” in all the page tests that are out there you will start reading something about “disowning the opening page”. In short: It’s safer to not tell the page you are linking to where your linking came from and to “disown” the page object in Javascript (if it’s on another domain). Read more about it here:

This basically lead me into one bigger issue: My navigation contains links outside of my website. Site optimization tools complained about the links not being safe. I also want them to open in a new tab.

How do I know in my menu template that the link is an external link?

Idea 1: Have a regexp that looks into the value of {{ .URL }} and if it has http(s) in the beginning it’s an external page.

Nope, because: It could be that by some configuration wizardry the link is an internal link. Also, regular expressions are quite error prone for the newbie (and oldie as well). It feels hacked. I am not sure about performance, but (see Idea 3) we don’t need to go this way.

Idea 2: Add a parameter like target to the menu configuration and if it is set to build the link to open external.

Sample:

[[menu.main]]
name = "DNB"
weight = 250
identifier = "dnb"
url = "https://davids-neighbour.com"
pre = "icons/user-tie.svg"
target = "_blank"

then in the menu:

{{ with .target }} target="{{ .Target }}"{{ end }}

Nope, because: I implemented that and it did not work. Finally actually reading the documentation it became clear that the menu items have no custom parameters (like Pages would have in .Page.Params for instance. {{ Trumpvoice }}Sad.{{ end }} - that surely would be a nice feature.

Idea 3 and solution: Reading the documentation I realized that, if set up properly, menu items I define in the config.toml are external. (I initially put all menu items into the config file which is convenient but wrong, because you never know if the current page is the page in the navigation…) Putting ALL internal links into the content files they link to and putting only external pages into config.toml will lead to one interesting thing: The .Page parameter of internal menu items will contain information about the page linked and it will be nil if the menu item was defined inside of config.toml.

Which leads to the following menu template (BS4-safe):

      <ul id="menu-topnavigation" class="nav navbar-nav mr-auto">
        {{ $currentPage := . }}
        {{ range .Site.Menus.main }}
          <li class="nav-item {{if or ($currentPage.IsMenuCurrent "main" .) ($currentPage.HasMenuCurrent "main" .) }} active{{end}}">
            <a href="{{.URL}}"{{if eq .Page nil }} target="_blank" rel="noopener noreferrer"{{ end }} class="nav-link">
              <span class="icon larger light" aria-hidden="true">
                {{ partialCached (print .Pre) .}} 
              </span>&nbsp;
              {{ .Name }}
            </a>
          </li>
        {{ end }}
      </ul>
3 Likes

I use a mixed version

The menus are defined in the central config. The menu pages (where .url points to) have a
menu = "posts" entry in the frontmatter.

My menu partial looks like

{{ $currentPage := $.Page }}{{ $menuName := $.Page.Params.menu }}
{{ range site.Menus.main}}
  <div>
    {{ $this := eq .Identifier $menuName }}
    {{ if $this }}
       {{.Name}}
    {{else}}
        <a href="{{ .URL }}" Title="{{ .Name }}">{{ .Name }}</a>
    {{end}}
  </div>
{{end}}

Hope this give new ideas to you

1 Like

Could you tell me where you’ve dug? “Disown” is bringing up a lot of family law pages, and frankly it’s a bit depressing. :grimacing:

Is there a different term that concept is known by?

No, but if you search for “disown link rel” it comes up with more content. There is a good explanation on Stackoverflow:

The standard is not very understandable and does (not yet?) contain noopener:

https://www.w3.org/TR/html50/links.html#link-type-noreferrer

1 Like

Another solution is to add a custom params field to your menu item.

[menu]
[[menu.main]]
  name = 'Hugo'
  url = 'https://gohugo.io/'
  weight = 10
  [menu.main.params]
    external = true

Then in your template do something like this:

{{ range .Site.Menus.main }}
  <li>
    <a class="{{ if eq $currentPage.RelPermalink .URL }}is-active{{end}}" href="{{.URL}}" {{ if eq .Params.external true }}target="_blank" rel="noopener noreferrer"{{ end }}>
      {{ .Name }}
    </a>
  </li>
{{ end }}