Yoast SEO in Hugo

I made 3 headers in partial:

  1. header-home.html
  2. header-list.html
  3. header-single.html

header.home.html :

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="profile" href="http://gmpg.org/xfn/11" />
    <link type="text/css" media="all" href="{{ .Site.BaseURL }}wp-content/cache/autoptimize/css/{{ .Site.Params.css }}.css" rel="stylesheet" />

    {{ $pag := .Paginate (where .Data.Pages "Type" "post") }}
    {{ if $pag.HasPrev }}
    <title>{{ .Site.Title }} - page {{ .Paginator.PageNumber }} of {{ .Paginator.TotalPages }} - {{ .Site.Params.subtitle }}</title>
    {{ else }}
    <title>{{ .Site.Title }} - {{ .Site.Params.subtitle }}</title>
    {{ end }}

    <!-- This site is optimized with the Yoast SEO plugin v6.0 - https://yoast.com/wordpress/plugins/seo/ -->

    {{ $pag := .Paginate (where .Data.Pages "Type" "post") }}{{ if $pag.HasPrev }}
    <meta name="robots" content="noindex,follow" />
    {{end}}

    <meta name="description" content="{{ .Site.Params.description }}" />
    {{ $pag := .Paginate (where .Data.Pages "Type" "post") }}
    {{ if $pag.HasPrev }}<link rel="canonical" href="{{ .Paginator.URL | absURL}}" />
    {{ else }}
    <link rel="canonical" href="{{ .Permalink }}" />
    {{end}}

    {{ if .Paginator.HasPrev }}<link rel="prev" href="{{ .Paginator.Prev.URL }}" />{{end}}
    {{ if .Paginator.HasNext }}<link rel="next" href="{{ .Paginator.Next.URL }}" />{{end}}

    <meta property="og:locale" content="en_US" />
    <meta property="og:type" content="website" />

    {{ $pag := .Paginate (where .Data.Pages "Type" "post") }}
    {{ if $pag.HasPrev }}
    <meta property="og:title" content="{{ .Site.Title }} - page {{ .Paginator.PageNumber }} of {{ .Paginator.TotalPages }} - {{ .Site.Params.subtitle }}">
    {{ else }}
    <meta property="og:title" content="{{ .Site.Title }} - {{ .Site.Params.subtitle }}" />
    {{ end }}
    
    <meta property="og:description" content="{{ .Site.Params.description }}" />

    {{ $pag := .Paginate (where .Data.Pages "Type" "post") }}
    {{ if $pag.HasPrev }}
    <meta property="og:url" content="{{ .Paginator.URL | absURL}}" />
    {{ else }}
    <meta property="og:url" content="{{ .Permalink }}" />
    {{end}}

    <meta property="og:site_name" content="{{ .Site.Title }}" />
    <meta name="twitter:card" content="summary" />
    <meta name="twitter:description" content="{{ .Site.Params.description }}" />

    {{ $pag := .Paginate (where .Data.Pages "Type" "post") }}
    {{ if $pag.HasPrev }}
    <meta name="twitter:title" content="{{ .Site.Title }} - page {{ .Paginator.PageNumber }} of {{ .Paginator.TotalPages }} - {{ .Site.Params.subtitle }}">
    {{ else }}
    <meta name="twitter:title" content="{{ .Site.Title }} - {{ .Site.Params.subtitle }}" />
    {{ end }}

    <script type='application/ld+json'>
        {
            "@context": "http:\/\/schema.org",
            "@type": "WebSite",
            "@id": "#website",
            "url": "http:\/\/{{ .Site.Params.url }}\/",
            "name": "Opini",
            "potentialAction": {
                "@type": "SearchAction",
                "target": "http:\/\/{{ .Site.Params.url }}\/?s={search_term_string}",
                "query-input": "required name=search_term_string"
            }
        }

    </script>
    <script type='application/ld+json'>
        {
            "@context": "http:\/\/schema.org",
            "@type": "Person",
            "url": "http:\/\/{{ .Site.Params.url }}\/",
            "sameAs": [],
            "@id": "#person",
            "name": "{{ .Site.Title }}"
        }

    </script>
    <meta name="google-site-verification" content="{{ .Site.Params.gsv }}" />
    <!-- / Yoast SEO plugin. -->

header.list.html

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="profile" href="http://gmpg.org/xfn/11" />
    <link type="text/css" media="all" href="{{ .Site.BaseURL }}wp-content/cache/autoptimize/css/{{ .Site.Params.css }}.css" rel="stylesheet" />

    {{ $pag := .Paginate (where .Data.Pages "Type" "post") }}
    {{ if $pag.HasPrev }}
    <title>{{ .Title }} Archives - page {{ .Paginator.PageNumber }} of {{ .Paginator.TotalPages }} - {{ .Site.Title }}</title>
    {{ else }}
    <title>{{ .Title }} Archives - {{ .Site.Title }}</title>
    {{ end }}

    <!-- This site is optimized with the Yoast SEO plugin v6.0 - https://yoast.com/wordpress/plugins/seo/ -->

    {{ $pag := .Paginate (where .Data.Pages "Type" "post") }}
    {{ if $pag.HasPrev }}<meta name="robots" content="noindex,follow" />{{end}}

    {{ $pag := .Paginate (where .Data.Pages "Type" "post") }}
    {{ if $pag.HasPrev }}<link rel="canonical" href="{{ .Paginator.URL | absURL}}" />
    {{ else }}
    <link rel="canonical" href="{{ .Permalink }}" />
    {{end}}

    {{ if .Paginator.HasPrev }}<link rel="prev" href="{{ .Paginator.Prev.URL }}" />{{end}}
    {{ if .Paginator.HasNext }}<link rel="next" href="{{ .Paginator.Next.URL }}" />{{end}}

    <meta property="og:locale" content="en_US" />
    <meta property="og:type" content="object" />

    {{ $pag := .Paginate (where .Data.Pages "Type" "post") }}
    {{ if $pag.HasPrev }}
    <meta property="og:title" content="{{ .Title }} Archives - page {{ .Paginator.PageNumber }} of {{ .Paginator.TotalPages }} - {{ .Site.Title }}">
    {{ else }}
    <meta property="og:title" content="{{ .Title }} Archives - {{ .Site.Title }}" />
    {{ end }}

    {{ $pag := .Paginate (where .Data.Pages "Type" "post") }}
    {{ if $pag.HasPrev }}
    <meta property="og:url" content="{{ .Paginator.URL | absURL}}" />
    {{ else }}
    <meta property="og:url" content="{{ .Permalink }}" />
    {{end}}
    
    <meta property="og:site_name" content="Opini" />
    <meta name="twitter:card" content="summary" />

    {{ $pag := .Paginate (where .Data.Pages "Type" "post") }}
    {{ if $pag.HasPrev }}
    <meta name="twitter:title" content="{{ .Title }} Archives - page {{ .Paginator.PageNumber }} of {{ .Paginator.TotalPages }} - {{ .Site.Title }}">
    {{ else }}
    <meta name="twitter:title" content="{{ .Title }} Archives - {{ .Site.Title }}" />
    {{ end }}
    <script type='application/ld+json'>
        {
            "@context": "http:\/\/schema.org",
            "@type": "WebSite",
            "@id": "#website",
            "url": "http:\/\/{{ .Site.Params.url }}\/",
            "name": "Opini",
            "potentialAction": {
                "@type": "SearchAction",
                "target": "http:\/\/{{ .Site.Params.url }}\/?s={search_term_string}",
                "query-input": "required name=search_term_string"
            }
        }

    </script>
    <script type='application/ld+json'>
        {
            "@context": "http:\/\/schema.org",
            "@type": "Person",
            "url": "http:\/\/{{ .Site.Params.url }}\/{{ .Data.Plural | urlize }}\/{{ .Title | urlize }}\/",
            "sameAs": [],
            "@id": "#person",
            "name": "Opini"
        }

    </script>
    <meta name="google-site-verification" content="{{ .Site.Params.gsv }}" />
    <!-- / Yoast SEO plugin. -->

header.single.html

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="profile" href="http://gmpg.org/xfn/11" />
    <link type="text/css" media="all" href="{{ .Site.BaseURL }}wp-content/cache/autoptimize/css/{{ .Site.Params.css }}.css" rel="stylesheet" />
    <title>{{ .Title }} - {{ .Site.Title }}</title>

    <!-- This site is optimized with the Yoast SEO plugin v6.0 - https://yoast.com/wordpress/plugins/seo/ -->
    <meta name="description" content="{{ .Params.potongan | truncate 150 }}" />
    <link rel="canonical" href="{{ .Permalink }}" />
    <meta property="og:locale" content="en_US" />
    <meta property="og:type" content="article" />
    <meta property="og:title" content="{{ .Title }} - {{ .Site.Title }}" />
    <meta property="og:description" content="{{ .Params.potongan }}" />
    <meta property="og:url" content="{{ .Permalink }}" />
    <meta property="og:site_name" content="{{ .Title }}" />
    {{ range .Params.calon }}<meta property="article:calon" content="{{ . }}" />{{ end }}
    {{ range .Params.partai }}<meta property="article:partai" content="{{ . }}" />{{ end }}
    {{ range .Params.daerah }}<meta property="article:daerah" content="{{ . }}" />{{ end }}
    <meta property="article:published_time" content="{{ .Date.Format "2006-01-02" }}T{{ .Date.Format "15:04:05" }}+07:00" />
    <meta property="og:image" content="{{ .Site.BaseURL }}wp-content/uploads/{{ .Params.gambar }}.jpg" />
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:description" content="{{ .Params.potongan }}" />
    <meta name="twitter:title" content="{{ .Title }} - {{ .Site.Title }}" />
    <meta name="twitter:image" content="{{ .Site.BaseURL }}wp-content/uploads/{{ .Params.gambar }}.jpg" />
    <script type='application/ld+json'>
        {
            "@context": "http:\/\/schema.org",
            "@type": "WebSite",
            "@id": "#website",
            "url": "http:\/\/{{ .Site.Params.url }}\/",
            "name": "Opini",
            "potentialAction": {
                "@type": "SearchAction",
                "target": "http:\/\/{{ .Site.Params.url }}\/?s={search_term_string}",
                "query-input": "required name=search_term_string"
            }
        }

    </script>
    <script type='application/ld+json'>
        {
            "@context": "http:\/\/schema.org",
            "@type": "Person",
            "url": "http:\/\/{{ .Site.Params.url }}\/{{ .Title | urlize }}\/",
            "sameAs": [],
            "@id": "#person",
            "name": "{{ .Site.Title }}"
        }

    </script>
    <meta name="google-site-verification" content="{{ .Site.Params.gsv }}" />
    <!-- / Yoast SEO plugin. -->
{{ $pag := .Paginate (where .Data.Pages "Type" "post") }}{{ if $pag.HasPrev }}
<meta name="robots" content="noindex,follow" />
{{end}}

I don’t think it’s good practice to use the values noindex,follow for paginated pages.

Does hugo use the correct html automatically or do you have an if statement to include it?

I have everything in a single file with a bunch of conditions:

Agreed, it should be index, follow and then make sure the rel next, rel previous markup is all setup.

Edit: Also, another place people go wrong is having the canonical set for all paginated pages to the first page. These should be set to the respective pages.

Also it’s not really DRY to have 3 different <head> partials.

I can understand why people are doing it. Getting the right context with Go templates is hard.

But I’ll post a tips & tricks on getting the context of Hugo Paginated Pages soon.