Schema Markup For Hugo

August 5, 2017
Implementing rich snippets (structured data) using JSON-LD

Rick Snippets (structured data)

There are 2 main ways to implement schema markup: JSON-LD and Microdata. Personally I prefer JSON-LD because the implementation is clearner where all data in written is json format at one specific section of HTML. Microdata is implemented within html tags througout the entire HTML page.

baseof.html

To implement rich snippets in Hugo, we need to edit layouts/_default/baseof.html. Look for the head to insert the template code within.

...
<head>
  ...
  {{ partial "site-schema.html" . }}  
</head>
...

Schema template

On main page, we shall create WebSite schema.
On blog post page, we shall create BlogPost schema. We shall Google’s Article Schema (BlogPosting is child of Article) which comes with a few mandatory requirements:

  • image is mandatory with mininum width of 696
  • publisher and publisher logo is required
  • author is required

We shall create schema template code at layouts/particlas/site-schema.html.

{{ if .IsHome -}}
<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "WebSite",
  "url": "{{ .Site.BaseURL }}",
  {{ if .Site.Author.name -}}
  "author": {
    "@type": "Person",
    "name": "{{ .Site.Author.name }}"
  },
  {{- end }}
  {{ if .Site.Params.description -}}
  "description": "{{ .Site.Params.description }}",
  {{- end }}
  {{ with .Site.Params.image -}}
  "image": "{{ .url | absURL }}",
  {{- end }}
  {{ with .Site.Params.logo -}}
  "thumbnailUrl": "{{ .url | absURL }}",
  {{- end }}
  {{ with .Site.Copyright -}}
  "license": "{{ . }}",
  {{- end }}
  "name": "{{ .Site.Title }}"
}
</script>
{{/*
  "potentialAction": {
    "@type": "SearchAction",
    "target": "http://example.com/search?&q={query}",
    "query-input": "required"
  } */}}
{{- else if .IsPage -}}
<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "BlogPosting",
  "headline": "{{ .Title }}",
  "mainEntityOfPage": {
    "@type": "WebPage",
    "@id": "{{ .Permalink }}"
  },
  {{ if ge (.Param "lua.image.width") 696 -}}
  "image": {
    "@type": "ImageObject",
    "url": "{{ .Param "lua.image.url" | absURL }}",
    "width": {{ .Param "lua.image.width" }},
    "height": {{ .Param "lua.image.height" }}
  },
  {{- else if ge .Site.Params.image.width 696 -}}
   "image": {
    "@type": "ImageObject",
    "url": "{{ .Site.Params.image.url | absURL }}",
    "width": {{ .Site.Params.image.width }},
    "height": {{ .Site.Params.image.height }}
  },
  {{- end }}
  "genre": "{{ .Type }}",
  {{ with .Params.tags -}}
  "keywords": "{{ delimit . ", " }}",
  {{- end }}
  "wordcount": {{ .WordCount }},
  "url": "{{ .Permalink }}",
  {{ if not .PublishDate.IsZero -}}
  "datePublished": "{{ .PublishDate.Format "2006-01-02T15:04:05-07:00" | safeHTML }}",
  {{- else if not .Date.IsZero -}}
  "datePublished": "{{ .Date.Format "2006-01-02T15:04:05-07:00" | safeHTML }}",
  {{- end }}
  {{ with .Lastmod -}}
  "dateModified": "{{ .Format "2006-01-02T15:04:05-07:00" | safeHTML }}",
  {{- end }}
  {{ with .Site.Copyright -}}
  "license": "{{ . }}",
  {{- end }}
  {{ with .Site.Params.publisher -}}
  "publisher": {
    "@type": "Organization",
    "name": "{{ .name }}",
    "logo": {
      "@type": "ImageObject",
      "url": "{{ .logo.url | absURL }}",
      "width": {{ .logo.width }},
      "height": {{ .logo.height }}
    }
  },
  {{- end }}
  {{ if .Params.author -}}
  "author": {
    "@type": "Person",
    "name": "{{ .Params.author }}"
  },
  {{- else if .Site.Author.name -}}
  "author": {
    "@type": "Person",
    "name": "{{ .Site.Author.name }}"
  },
  {{- end }}
  "description": "{{ .Description }}"
}
</script>
{{- end }}

config.toml

The following configuration is required at config.toml to generate the complete schema.

baseURL = "https://code.luasoftware.com/"
title = "Lua Software Code"
...
copyright = "This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License."

[author]
  name = "Desmond Lua"

[params]
  description = "Tutorials and snippets for programming languages, frameworks, tools, etc."
  ...

  [params.publisher]
    name = "Lua Software"

    [params.publisher.logo]
      url = "/img/logo.png"
      width = 127
      height = 40

  [params.logo]
    url = "/img/logo.png"
    width = 127
    height = 40

  [params.image]
    url = "/img/cover.png"
    width = 800
    height = 600

Page markdown

The following configuration can be edited at page markdown to generate the schema.

---
title: "Schema Markup For Hugo"
description: "Implementing rich snippets using JSON-LD"
date: 2017-07-25T12:50:39+08:00
lastmod: 2017-07-26T15:01:05+08:00
tags: ["hugo", "schema markup", "rich snippets", "json-ld"]
lua:
  image:
    url: "/img/hugo/schema-markup.jpg"
    width: 800
    height: 600
  author: "New Author"
---
...

Generated schema markup

The folloing schema markups are generated using JSON-LD format. You can verify the markup usiong Structured Data Testing Tool.

WebSite for Main Page

<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "WebSite",
  "url": "https://code.luasoftware.com/",
  "author": {
    "@type": "Person",
    "name": "Desmond Lua"
  },
  "description": "Tutorials and snippets for programming languages, frameworks, tools, etc.",
  "image": "https://code.luasoftware.com/img/cover.png",
  "thumbnailUrl": "https://code.luasoftware.com/img/logo.png",
  "license": "This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.",
  "name": "Lua Software Code"
}
</script>

BlogPosting for Blog Post Page

<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "BlogPosting",
  "headline": "Schema Markup For Hugo",
  "mainEntityOfPage": {
    "@type": "WebPage",
    "@id": "https://code.luasoftware.com/tutorials/hugo/schema-markup-for-hugo/"
  },
  "image": {
    "@type": "ImageObject",
    "url": "https://code.luasoftware.com/img/cover.png",
    "width": 800,
    "height": 600
  },
  "genre": "tutorials",
  "keywords": "hugo, schema markup, rich snippets, json-ld",
  "wordcount": 657,
  "url": "https://code.luasoftware.com/tutorials/hugo/schema-markup-for-hugo/",
  "datePublished": "2017-07-25T12:50:39+08:00",
  "dateModified": "2017-07-26T15:01:05+08:00",
  "license": "This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.",
  "publisher": {
    "@type": "Organization",
    "name": "Lua Software",
    "logo": {
      "@type": "ImageObject",
      "url": "https://code.luasoftware.com/img/logo.png",
      "width": 127,
      "height": 40
    }
  },
  "author": {
    "@type": "Person",
    "name": "Desmond Lua"
  },
  "description": "Implementing rich snippets using JSON-LD"
}
</script>
This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.