Webentwicklung: Detaillierte Linkvorschauen von Websites automatisiert erstellen

Seite 2: Das Open Graph Protocol als de-facto-Standard

Inhaltsverzeichnis

Neben den standardisierten Metadaten gibt es das Open Graph Protocol (OGP), die "de facto Standard-Erweiterung". Dieses Protokoll ergänzt die Angabe von Vorschaubildern, Videos und Audiodateien, ermöglicht das Festlegen eines Typen (wie Artikel, Musik oder Website) sowie weiterer Metadaten für das HTML-Dokument. Dabei überschneidet sich das OGP mit einigen vereinheitlichten Metadaten. Es unterscheidet zwischen den verpflichtenden Metadaten og:title, og:type, og:image, og:url und folgenden optionalen Metadaten

  • og:audio
  • og:description
  • og:determiner
  • og:locale
  • og:locale:alternate
  • og:site_name
  • og:video

Die Deklaration der OGP-Daten weicht minimal von den standardisierten Metadaten ab:

<meta property="og:title" content="Never Gonna Give You Up">
<meta property="og:type" content="music.song">
<meta property="og:image"
content="https://i.scdn.co/image/ab67616d0000b273255e131abc1410833be95673">
<meta property="og:url"
content="https://open.spotify.com/track/4cOdK2wGLETKBW3PvgPWqT">

Listing 3: Angabe der erforderlichen Open-Graph-Metadaten für einen Spotify-Song

Anstelle des name-Attributs verwendet das OGP in Listing 3 das property-Attribut. Abhängig vom Typ og:type können weitere grundlegende OGP-Metadaten nötig sein. Für einen Song wären dies zum Beispiel:

  • music:duration
  • music:album
  • music:album:disc
  • music:album:track
  • music:musician

Die Angabe der gesonderten Metadaten für einen Song folgt dem Schema des Open Graph Protocol:

<meta name="music:duration" content="214">
<meta name="music:album"
content="https://open.spotify.com/album/6N9PS4QXF1D0OWPk0Sxtb4">
<meta name="music:album:track" content="1">
<meta name="music:musician"
content="https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt">

Listing 4: Gesonderte OGP-Metadaten zur Deklaration eines Songs

Der einzige Unterschied zum OGP-Standard in Listing 4 besteht darin, dass das Präfix og durch eine dem Typ entsprechende Alternative (hier music) ausgetauscht wird. Entwicklerinnen und Entwickler sollten dabei jedoch beachten, dass sich nicht jede Website strikt an die OGP-Vorgaben hält. Beim dargestellten Song von Spotify fehlt etwa die Angabe des Albums (music:album:disc), da sie aus Sicht von Spotify vermutlich irrelevant ist.

Neben dem Song gibt es weitere Typen:

  • music.album
  • music.playlist
  • music.radio_station
  • video.movie
  • video.episode
  • video.tv_show
  • video.other
  • article
  • book
  • profile
  • website

Zudem dokumentiert die offizielle Seite nicht alle OGP-Metadaten. So dokumentiert Meta/Facebook etwa die Eigenschaft article:content_tier, die auf ogp.me nicht erwähnt wird. Wer die Vorschau testen möchte, kann dazu den LinkedIn Post Inspector heranziehen, der jedoch nicht alle Eigenschaften des Open Graph Protocol betrachtet. Die Twitter Cards ähneln dem OGP stark. Hier existieren jedoch einige zusätzliche Meta-Tags wie das Twitter-Handle. Die Angabe von Metadaten erfolgt mit dem Präfix twitter. Die Angabe des Twitter-Handles für die Twitter Card eines Spotify-Songs hat dann die folgende Form: <meta name="twitter:site" content="@spotify">

Weitere Angaben wie twitter:title, twitter:description sind für das Erstellen einer eigenen Linkvorschau redundant, können jedoch als Fallback verwendet werden, falls korrespondierende Metadaten (description oder og:description) nicht gesetzt sind.

Die Eigenschaft twitter:card wird von Twitter verwendet, um die Darstellung der Card (Linkvorschau) zu beeinflussen. Auch Dritte können sie interpretieren. So verwendet Slack die Angaben in Verbindung mit den Metadaten twitter:label1, twitter:data1, twitter:label2 und twitter:data2 für die eigene Linkvorschau. Entwicklerinnen können die Label/Data-Paare für die eigene Vorschau heranziehen. Sie enthalten benutzerdefinierte Angaben, wie etwa den Preis eines Produkts:

<meta name="twitter:label1" content="Preis">
<meta name="twitter:data1" content="€42"> 

Listing 5: Angabe des Produktpreises durch Twitter-Label

Das oEmbed-Format weicht vom OGP und den Twitter Cards ab. Statt meta-Elemente auszulesen, spricht dabei ein Konsument ("consumer") die API-Schnittstelle des Anbieters ("provider") an, um Inhalte über die anzufragende Seite zu erhalten. Auch für den Spotify-Song gibt es eine oEmbed-Schnittstelle, die entweder ein Link-Element im Quellcode, die Angabe des Link-Headers oder ein Lookup in der Provider-Liste anfragen kann. Letztere Methode ist nicht empfehlenswert, da sie nur eine begrenzte Anzahl an Providern (aktuell 296) enthält und so nicht sichergestellt ist, dass der oEmbed-Endpunkt gefunden wird.

<link
rel="alternate"
type="application/json+oembed"
href="https://open.spotify.com/oembed?url=https%3A%2F%2Fopen.spotify.com%2Ftrack%2F4cOdK2wGLETKBW3PvgPWqT"
> 

Listing 6: Angabe der oEmbed-Schnittstelle für einen Spotify-Song

Die Anfrage des Endpunktes erfolgt durch document mit folgender Eingabe: document.querySelector('link[rel="alternate"][type="application/json+oembed"]')?.href;

Das JSON-Ergebnis – wie folgendes Listing es zeigt – ermöglicht das Abrufen des Endpunktes:

{
  "html": "<iframe>...</iframe>",
  "width": 456,
  "height": 152,
  "version": "1.0",
  "provider_name": "Spotify",
  "provider_url": "https://spotify.com",
  "type": "rich",
  "title": "Never Gonna Give You Up",
  "thumbnail_url": "https://i.scdn.co/image/ab67616d00001e025755e164993798e0c9ef7d7a",
  "thumbnail_width": 300,
  "thumbnail_height": 300
} 

Listing 7: Resultat der Abfrage der oEmbed-Schnittstelle

Das Resultat aus Listing 7 enthält die optionalen Angaben Anbieter (provider_name), Titel (title), Thumbnail (thumbnail_url) sowie eine dynamische Vorschau (html). Die Vorschau existiert, wenn der Typ auf rich gesetzt ist, alternativ kann er die Werte photo, video und link enthalten. Die Angaben über den Autor (author_name, author_url) sowie die Cache-Dauer (cache_age) sind weiterhin optional. Grundsätzlich können Programmierer die oEmbed-Schnittstellen ohne Autorisierung abrufen. Allerdings verlangt Meta/Facebook zusätzlich einen API-Key, der über den Anfrage-Parameter access_token gesetzt wird.

Schließlich stehen den Entwicklern auch noch die strukturierten Daten zur Verfügung, bei denen die Implementierung durch Resource Description Framework in Attributes (RDFa), Mikrodaten oder JSON for Linked Data (kurz JSON-LD) erfolgt. Google empfiehlt JSON-LD, weshalb dieses Format hier genutzt wird. Im Gegensatz zu meta-Elementen oder dem oEmbed-Format beschreiben strukturierte Daten nicht zwangsläufig die komplette Website oder eine Unterseite, sondern können sich auch auf bestimmte Teile beschränken, etwa auf den Autor des Artikels oder das Unternehmen. Für die Angabe strukturierter Daten mittels JSON-LD verwenden Entwickler das script-Element als Container mit den strukturierten Daten als Inhalt:

<script type="application/ld+json">
{
  "@context": "http://schema.org/",
  "@type": "MusicRecording",
  "@id": "https://open.spotify.com/track/4cOdK2wGLETKBW3PvgPWqT",
  "url": "https://open.spotify.com/track/4cOdK2wGLETKBW3PvgPWqT",
  "name": "Never Gonna Give You Up",
  "description": "Listen to Never Gonna Give You Up on Spotify. Rick Astley · Song · 1987.",
  "datePublished": "1987-11-12",
  "potentialAction": {
    "@type": "ListenAction",
    "target": [...],
    "expectsAcceptanceOf": {
      "@type": "Offer",
      "category": "free",
      "eligibleRegion": []
    }
  }
}
</script> 

Listing 8: script-Element mit JSON-LD Inhalt

Die Eigenschaften des Objekts entstammen dabei der korrespondierenden Schema-Seite, in diesem Fall MusicRecording. Dabei muss ein Programmierer immer sowohl @context als auch @type angeben. Neben diesen beiden und weiteren Eigenschaften aus Listing 8 lässt sich dann beispielsweise noch die Attribute duration oder byArtist hinzufügen (siehe Abb. 2). Die Eigenschaften übergeordneter Objekte können Entwicklerinnen und Entwickler ebenfalls nutzen. Bei MusicRecording wären dies CreativeWork und Thing.

Ausschnitt von Eigenschaften des Schemas MusicRecording aus schema.org (Abb. 2)

In den geschilderten Fällen beschränken sich JSON-LD-Objekte nicht auf jeweils ein Objekt pro HTML-Dokument, sodass Entwicklerinnen auch weitere Objekte wie Organisation verwenden können. Zum Validieren können sie den Dienst Google Validation für strukturierte Daten verwenden.

Die bisher in diesem Beitrag vorgestellten Daten wie Autor, Publikationsdatum und Genre sind grundsätzlich interessant für eine Linkvorschau. Nachdem in den vorangegangenen Abschnitten einzelne Methoden zur Datengewinnung erläutert wurden, geht es nun daran, diese zu einer Vorschau zusammenzusetzen. In den Codebeispielen überschneiden sich diverse Eigenschaften wie das Publikationsdatum oder die Beschreibung. Dies ist insbesondere für die Absicherung von Vorteil, da so die Wahrscheinlichkeit sinkt, dass ein Wert für die Vorschau nicht gefüllt ist. Für die Vorschau aus Abbildung 1 benötigen Entwickler Host, Titel, Beschreibung sowie ein Vorschaubild. Folgendes Listing zeigt, wie die Vorschau auf diese Werte zugreift:

function getMeta(name) {
	const attribute = name.toLowerCase().startsWith('og:')
? 'property' : 'name';
	const element = document.querySelector(`meta[${attribute}="${name}"]`);
	
	if (element) {
		return element.getAttribute('content');
	}
}

const { hostname } = new URL(url);
const titleTag = document.querySelector('title');
const titleMeta = getMeta('og:title') || getMeta('twitter:title');
const title = titleTag ? titleTag.textContent : titleMeta;
const img = getMeta('og:image') || getMeta('og:image:url')
|| getMeta('og:image:secure_url') || getMeta('twitter:image');
const description = getMeta('description')
|| getMeta('og:description') || getMeta('twitter:description'); 

Listing 9: Datensammlung für die Linkvorschau mittels Node.js

Strukturierte Daten kommen in Listing 9 nicht zum Einsatz, da sie zur Replikation der Linkvorschau aus Abbildung 1 nicht nötig sind und Twitter lediglich die Beschreibung anzeigt. Grundsätzlich kann die Vorschau auch Autoren, Lesezeit und die Anzahl an Kommentaren ebenfalls anzeigen. Dies ist insbesondere bei Zeitungsartikeln und Blogbeiträgen von Interesse. So nutzt heise.de das Schema NewsArticle auf Artikelseiten, das unter anderem author und commentCount isAccessibleForFree enthält. Wer einen Überblick über verwendete JSON-LD-Schemata einer Website erhalten möchte, kann nachfolgenden Befehl in der Browser-Konsole ausführen: $$("script[type='application/ld+json']").map(x => JSON.parse(x.textContent))