×
Startseite RSS-Feed Info
Den Inhalt von Open Graph Meta-Tags selber festlegen.

Hugo - angepasste Open Graph Integration

Customized Open Graph integration

Open Graph ist ein Protokoll, mit dem sich beeinflussen lässt wie eine Webseite dargestellt wird, wenn sie auf Social Media geteilt wird. Über Meta Einträge im Head jeder Webseite kann man selber beeinflussen welche Daten dafür benutzt werden. In diesem Artikel beschreibe ich meine in einem Partial zusammengefassten Open Graph Meta-Tags.

Allgemeine Informationen zu Open Graph

Ursprünglich wurde Open Graph von Facebook entwickelt. Seither wurde es aber auch von anderen Social-Media-Kanälen wie Twitter, Pinterest und LinkedIn übernommen.

Die meisten Inhalte werden als URL auf Facebook und anderen (Open Graph Protokoll) OGP-unterstützenden Websites geteilt. Aus diesem Grund kann es nur positiv sein, wenn die eigene Website mit Open Graph Meta-Tags ausgestattet ist. Nur so hat man die Kontrolle, welche Inhalte dort angezeigt werden.

Da ich verstehen möchte was zu einer entsprechenden Ausgabe im Sourcecode führt und was für Möglichkeiten es gibt, habe ich mir unter anderem die folgenden Webseiten angeschaut:

Hugo Open Graph Template

Hugo stellt ein Template für die Integration der Open Graph Meta-Tags zur Verfügung. Das Template wird im Head aufgerufen und integriert die Meta-Tags. Wenn Sie das Template benutzen möchten reicht der folgende Aufruf:

{{ template "_internal/opengraph.html" . }}

Für ein besseres Verständnis was das Template so macht, gibt es eine Hugo Doku und einen Link zum Template Sourcecode:

Mein Partial ogData.html

Das Hugo Template ist für viele Einsatzzwecke konzipiert. Da ich nur die für meine Website angepassten Inhalte ausgeben möchte, habe ich Teile des Templates übernommen bzw. neu geschrieben. Dazu weiter unten mehr.

Das Partial ogData.html habe ich wie folgt im head-Tag meiner baseof.html eingebunden:

{{ partial "ogData" . }}

Der Sourcecode des Partials themes/tekki/layouts/partials/ogData.html sieht wie folgt aus:

<meta property="og:title" content="{{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ .Title }} &middot; {{ .Site.Title }}{{ end }}">
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}">
<meta property="og:description" content="{{ if .Description }}{{ .Description }}{{ else }}{{ .Site.Params.description }}{{ end }}">
<meta property="og:site_name" content="{{ .Site.Title }}">
<meta property="og:url" content="{{ .Permalink }}">
{{ if eq .Site.Language.Lang "de" }}
  <meta property="og:locale" content="de_DE">
  <meta property="og:locale:alternate" content="en_GB">
{{ else }}
  <meta property="og:locale" content="en_GB">
  <meta property="og:locale:alternate" content="de_DE">
{{ end }}
{{ if and (.IsPage) (ne .Section "") }}<meta property="article:section" content="{{ .Section }}">{{ end }}
{{ $iso8601 := "2006-01-02T15:04:05-07:00" }}
{{ with .PublishDate }}<meta property="article:published_time" {{ .Format $iso8601 | printf "content=%q" | safeHTMLAttr }}>{{ end }}
{{ with .Lastmod }}<meta property="article:modified_time" {{ .Format $iso8601 | printf "content=%q" | safeHTMLAttr }}>{{ end }}
{{ $image := .Resources.GetMatch "featured" }}
{{ with $image }}
  <meta property="og:image" content="{{ .Permalink }}">
  <meta property="og:image:secure_url" content="{{ .Permalink }}">
  <meta property="og:image:type" content="{{ .MediaType }}">
  <meta property="og:image:width" content="{{ .Width }}">
  <meta property="og:image:height" content="{{ .Height }}">
  <meta property="og:image:alt" content="{{ .Title }}">
{{ else }}
  {{ $ogimage := resources.Get "tekki-tipps-og.png" }}
  {{ with $ogimage }}
    <meta property="og:image" content="{{ .Permalink }}">
    <meta property="og:image:secure_url" content="{{ .Permalink }}">
    <meta property="og:image:type" content="{{ .MediaType }}">
    <meta property="og:image:width" content="{{ .Width }}">
    <meta property="og:image:height" content="{{ .Height }}">
    <meta property="og:image:alt" content="Blog about Hugo, web design, CSS/SCSS, SEO, Tools">
  {{ end}}
{{ end }}

Zum besseren Verständnis werde ich jedes Meta-Tag einzelnd beschreiben.

meta property=“og:title”

<meta property="og:title" content="{{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ .Title }} &middot; {{ .Site.Title }}{{ end }}">

Wenn die aktuelle Webseite die Startseite ist, wird der title aus der hugo.toml übernommen. Ansonsten, also für alle anderen Webseiten, wird der title dem Front Matter Eintrag der aktuellen Webseite entnommen. Ein Bindestrich eingefügt und der title aus der hugo.toml angefügt.

Die Einträge der hugo.toml für deutsch und englisch sehen wie folgt aus:

[languages]
  [languages.de]
    languageName = "Deutsch"
    weight = 1
    title = "tekki-tipps.de 🇩🇪"
    description = "Blog über Hugo, Webdesign, CSS/SCSS, SEO, Tools"
..
..
  [languages.en]
    languageName = "English"
    weight = 2
    title = "tekki-tipps.de/en 🇬🇧"
    description = "Blog about Hugo, web design, CSS/SCSS, SEO, Tools"

meta property=“og:type”

<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}">

Auf meiner Website wird der og:type website für die Startseite, die Tag-Cloud und auf Tag-Listen angezeigt. Also auf allen Übersichtslisten. Alle anderen Webseiten erhalten den og:type article.

meta property=“og:description”

<meta property="og:description" content="{{ if .Description }}{{ .Description }}{{ else }}{{ .Site.Params.description }}{{ end }}">

Wenn die aktuelle Webseite im Front Matter eine description hat, wird diese durch .Description übernommen. Ansonsten wird die description der hugo.toml benutzt.

meta property=“og:site_name”

<meta property="og:site_name" content="{{ .Site.Title }}">

Der Title aus der hugo.toml.

meta property=“og:url”

<meta property="og:url" content="{{ .Permalink }}">

Die permanente URL der aktuellen Webseite.

meta property=“og:locale” und “og:locale:alternate”

{{ if eq .Site.Language.Lang "de" }}
  <meta property="og:locale" content="de_DE">
  <meta property="og:locale:alternate" content="en_GB">
{{ else }}
  <meta property="og:locale" content="en_GB">
  <meta property="og:locale:alternate" content="de_DE">
{{ end }}

og:locale definiert die Sprache der aktuellen Webseite. og:locale:alternate teilt mit, dass für die aktuelle Webseite eine Übersetzung in einer alternativen Sprache vorhanden ist.

meta property=“article:section”

{{ if and (.IsPage) (ne .Section "") }}<meta property="article:section" content="{{ .Section }}">{{ end }}

Wenn die aktuelle Webseite eine Page ist und die .Section kein leerer String ist, dann soll das Meta-Tag in den Head geschrieben werden. Auf meiner Website gibt es nur die Section blog. Damit bei Webseiten die keine Section haben das Meta-Tag nicht in den Head geschrieben wird, erfolgt die Abfrage ob der String in .Section leer ist.

meta property=“article:published_time” und article:modified_time

{{ $iso8601 := "2006-01-02T15:04:05-07:00" }}
{{ with .PublishDate }}<meta property="article:published_time" {{ .Format $iso8601 | printf "content=%q" | safeHTMLAttr }}>{{ end }}
{{ with .Lastmod }}<meta property="article:modified_time" {{ .Format $iso8601 | printf "content=%q" | safeHTMLAttr }}>{{ end }}

Die Übersichtsseiten - Startseite, Tag-Cloud und Tag-Listen - habe kein .PublishDate deshalb die Abfrage. Alle anderen Webseiten haben eventuell noch kein .Lastmod.

meta property=“og:image”

{{ $image := .Resources.GetMatch "featured" }}
{{ with $image }}
  <meta property="og:image" content="{{ .Permalink }}">
  <meta property="og:image:secure_url" content="{{ .Permalink }}">
  <meta property="og:image:type" content="{{ .MediaType }}">
  <meta property="og:image:width" content="{{ .Width }}">
  <meta property="og:image:height" content="{{ .Height }}">
  <meta property="og:image:alt" content="{{ .Title }}">
{{ else }}
  {{ $ogimage := resources.Get "tekki-tipps-og.png" }}
  {{ with $ogimage }}
    <meta property="og:image" content="{{ .Permalink }}">
    <meta property="og:image:secure_url" content="{{ .Permalink }}">
    <meta property="og:image:type" content="{{ .MediaType }}">
    <meta property="og:image:width" content="{{ .Width }}">
    <meta property="og:image:height" content="{{ .Height }}">
    <meta property="og:image:alt" content="Blog about Hugo, web design, CSS/SCSS, SEO, Tools">
  {{ end}}
{{ end }}

Nun wird es etwas komplizierter. Deshalb muss ich etwas mehr erklären. Meine Webseiten sind multilingual in zwei Sprachen. Ich benutze PageBundles wegen der Übersichtlichkeit - alles für eine Webseite, in einem Verzeichnis. Die jeweiligen Bilder werden innerhalb des PageBundle Verzeichnis im img-Verzeichnis gespeichert. Meine Blogbeitragsseiten haben ein Artikelbild und ein als featured bezeichnetes Bild. Alle anderen Webseiten haben kein als featured bezeichnetes Bild.

Im Front Matter für diese Webseite sehen die Einträge wie folgt aus:

resources:
- name: featured
  src: img/featured.png
  title: Customized Open Graph integration
- name: article-img
  src: img/open-graph.png
  title: Customized Open Graph integration

Mit .Resources.GetMatch hole ich das als featured bezeichnete Bild aus dem PageBundle und speicher es in der Variablen $image. Wenn ein featured Bild vorhanden ist, gebe ich die entsprechenden Meta-Tags für dieses Bild aus.

Wenn kein featured Bild vorhanden ist, suche ich mit resources.Get nach dem Bild tekki-tipps-og.png und speicher es in der Variablen $ogimage. Das Bild habe ich im static Verzeichnis auf der obersten Ebene gespeichert.

Die Bilder sollten eine Auflösung von 1200px X 600px haben, damit auch auf hochauflösenden Bildschirmen ein gutes Bild angezeigt wird. Siehe dazu auch den oben genannten Facebook Link.

meta property=“og:image:secure_url”

Heutzutage gibt es ja kaum noch Websites die kein SSL-Zertifikat haben. Das Meta-Tag kommt noch aus einer anderen Zeit. Muss aber angegeben werden. Auch hier übergebe ich den .Permalink des Bildes.

meta property=“og:image:type”

Ich benutze Bilddateien vom Typ png und jpg. png sind von der Größe her kleiner, wenn ein großer Teil des Bildes die gleichen Farbanteile enthält. Der Typ wird durch .MediaType automatisch festgestellt.

meta property=“og:image:width”

Mit .Width wird die Breite des Bildes festgestellt.

meta property=“og:image:height”

Mit .Height wird die Höhe des Bildes festgestellt.

meta property=“og:image:alt”

Bei den Blogbeiträgen entnehme ich den alternativen Text des Bildes aus dem Resource Title. Für alle anderen Webseiten, mit dem allgemeinen Bild, speicher ich meinen alt-Text manuell.

Kontrolle der Open Graph Parameter

Im head des HTML-Sourcecodes kann man die entsprechenden Meta-Tags anschauen. Da ich die Open Graph Meta-Tags erst im nachhinein erstellt habe, ist es sehr aufwändig dies für jeden Beitrag und jeder Sprache zu kontrollieren.

Auch dafür gibt es eine Lösung - Browser Extensions. Für Safari habe ich gar keine Extension gefunden. Für Edge gibt eine Textlösung, aber der relevante Teil muss gescrollt werden. Da kann man sich dann auch den HTML-Sourcecode anschauen.

Für Firefox und Chrome gibt es entsprechende Extension. Das für Firefox finde ich hübscher und setze es auch ein:

Open Graph blog post extension
Firefox Browser Extension - Anzeige für diesen Blogbeitrag.
Open Graph website extension
Firefox Browser Extension - Anzeige für alle anderen Webseiten außer Blogbeiträgen.

Fazit

Ich habe keinen Facebook Account und kann deshalb die Weitergabe von Links innerhalb von Facebook nicht kontrollieren. Die Weitergabe meiner Kontaktadressen ist mir zu wertvoll um sie gezwungenermaßen mit Facebook zu teilen. Andere sehen dies anders und für diese Menschen habe ich die OG Meta-Tags integriert.

Linkliste zu diesem Beitrag

Update:  |
8 Minuten Lesezeit
0
Dieser Beitrag wurde mit der Hugo-Version 0.111.3 erstellt.

Kommentare werden bei deutscher Spracheinstellung nicht in der englischen Variante der Webseite angezeigt und umgekehrt.

© 2023 - Frank Kunert  -  Ich über mich
Ein Service von webdienste-kunert.de