← WISSENS-BLOG

Mit ExpressionEngine effektiv und pflegeleicht strukturierte Daten entwickeln

Strukturierte Daten entfalten ihren größten Nutzen, wenn sie die Informationsarchitektur einer Website widerspiegeln. Dieser Praxisbericht zeigt anhand einer Website für ein Seniorenheim, wie mit ExpressionEngine eine durchgängige JSON-LD-Strategie entwickelt wurde. Ausgangspunkt ist die Startseite. Sie beschreibt nicht nur die Einrichtung, sondern bildet gleichzeitig die semantische Grundlage für sämtliche Themenbereiche und Fachartikel.

Mit ExpressionEngine effektiv und pflegeleicht strukturierte Daten entwickeln

Bildnachweis: iStockphoto / Tim Arbaev

Die Startseite als Ausgangspunkt der gesamten JSON-LD-Architektur

Im Rahmen eines Kundenprojekts entstand eine neue Website für ein Seniorenheim. Die Inhalte wurden bewusst nicht als lose Einzelseiten aufgebaut, sondern in klar voneinander abgegrenzte Wissensbereiche gegliedert. Dazu gehören unter anderem:

  • Pflege und Betreuung
  • Wohnen und Leben
  • Qualität und Transparenz
  • Kosten und Finanzierung
  • Essen auf Rädern
  • Jobs und Ehrenamt

Jeder dieser Bereiche besitzt eine eigene Übersichtsseite sowie mehrere Artikel. Ergänzt wird die Website durch aktuelle Meldungen, Termine und Videointerviews. Schon während der Konzeption wurde deutlich, dass eine einzige JSON-LD-Struktur diesem Aufbau nicht gerecht werden würde. Die einzelnen Seitentypen erfüllen unterschiedliche Aufgaben und benötigen deshalb auch unterschiedliche strukturierte Daten. Es entstanden drei Ebenen.

  • Die Startseite beschreibt die Einrichtung und bildet den Einstieg in die gesamte Website.
  • Die Themenübersichten erschließen jeweils einen kompletten Informationsbereich.
  • Die Artikel beantworten eine konkrete Fragestellung.

Diese Unterscheidung bildet die Grundlage der gesamten JSON-LD-Struktur.

Warum die Entwicklung mit der Startseite beginnt

Die Entwicklung beginnt bewusst mit der Startseite. Sie beschreibt nicht nur das Seniorenheim, sondern führt gleichzeitig in die wichtigsten Inhalte der Website ein. Besucher finden hier den Einstieg in die zentralen Wissensbereiche, aktuelle Meldungen, zusätzliche Angebote und Videointerviews.

Diese Inhalte erfüllen unterschiedliche Aufgaben. Die wichtigsten Informationen führen in die einzelnen Wissensbereiche. Aktuelle Meldungen zeigen neue Entwicklungen. Angebote verweisen auf eigenständige Leistungsbereiche. Videos ergänzen die Website um einen weiteren Inhaltstyp.

Die Startseite bildet damit bereits die Informationsarchitektur der gesamten Website ab. Genau diese Struktur sollte sich auch in den strukturierten Daten widerspiegeln. Erst auf dieser Grundlage entstehen anschließend die JSON-LD-Ausgaben für Themenübersichten und Fachartikel.

Die erste Überlegung

Der erste Schritt bestand darin, das Seniorenheim selbst eindeutig zu beschreiben. Dafür fiel die Wahl bewusst auf den Schema.org-Typ NursingHome. Dadurch wird nicht nur eine Website beschrieben, sondern die Einrichtung als eigenständige Entität.

Zu dieser Beschreibung gehören unter anderem:

  • Name der Einrichtung
  • Logo
  • Anschrift
  • Telefonnummer
  • E-Mail-Adresse

Diese Informationen bilden den gemeinsamen Kern der gesamten JSON-LD-Architektur.

Anschließend wird die Website selbst als WebSite beschrieben und direkt mit dem Seniorenheim verknüpft. Dadurch entstehen zwei klar voneinander getrennte, aber miteinander verbundene Ebenen.

  • Die Einrichtung beschreibt den realen Ort.
  • Die Website beschreibt den digitalen Auftritt.

Diese Informationen werden anschließend auf allen weiteren Seiten wiederverwendet und bilden den gemeinsamen Kontext für sämtliche Themenübersichten und Themenartikel. Dadurch müssen die grundlegenden Angaben zum Unternehmen nicht bei jeder JSON-LD-Ausgabe erneut definiert werden.

Der erste JSON-LD-Block

Der erste Schritt der Umsetzung besteht deshalb ausschließlich aus der Beschreibung der Einrichtung und der Website.

<script type="application/ld+json">
{
  "@context":"https://schema.org",
  "@graph":[
    {
      "@type":"NursingHome",
      "@id":"https://kundendomain.de/#kunde",
      "name":"Beispielkunde",
      "url":"https://kundendomain.de/",
      "logo":{
        "@type":"ImageObject",
        "url":"https://kundendomain.de/images/logo.webp"
      },
      "telephone":"+49 0000 000000",
      "email":"info@kundendomain.de",
      "address":{
        "@type":"PostalAddress",
        "streetAddress":"Musterstraße 1",
        "postalCode":"00000",
        "addressLocality":"Musterstadt",
        "addressCountry":"DE"
      }
    },
    {
      "@type":"WebSite",
      "@id":"https://kundendomain.de/#website",
      "url":"https://kundendomain.de/",
      "name":"Beispielkunde",
      "publisher":{
        "@id":"https://kundendomain.de/#kunde"
      }
    }
  ]
}
</script>

Der eigentliche Zweck dieser Struktur

Das Seniorenheim wird als eigenständige Entität beschrieben und direkt mit der Website verknüpft. Diese grundlegenden Informationen stehen anschließend allen weiteren JSON-LD-Ausgaben als gemeinsamer Kontext zur Verfügung und müssen nicht auf jeder Seite erneut definiert werden.

Damit war die technische Grundlage geschaffen. Eine Frage blieb jedoch offen: Reicht es aus, auf der Startseite nur die Einrichtung und die Website zu beschreiben? Nein. Die Startseite ist zugleich der Einstieg in die wichtigsten Themenbereiche der Website. Deshalb entstand ein zweiter JSON-LD-Block, der die Startseite zusätzlich als CollectionPage mit mehreren ItemList beschreibt. Genau darum geht es in der Folge.

Die Startseite als CollectionPage mit Grid-Feldern: Warum die Startseite mehr leisten muss

Von NursingHome zur CollectionPage

Mit NursingHome und WebSite waren die grundlegenden Informationen beschrieben. Es fehlte jedoch noch die eigentliche Funktion der Startseite. Sie erschließt die wichtigsten Wissensbereiche, Angebote, aktuellen Meldungen und Videos. Deshalb wurde sie zusätzlich als CollectionPage mit mehreren ItemList modelliert.

Der Aufbau in ExpressionEngine

Die Startseite wird in ExpressionEngine über den Channel startseite gepflegt. Die einzelnen Bereiche der Startseite sind dabei eigene Einträge innerhalb dieses Channels (siehe dazu meinen Praxisbericht: Eine flexible und pflegeleichte Startseite mit ExpressionEngine). Für die wiederholbaren Inhalte werden Grid-Felder verwendet. Das ist entscheidend, weil dieselben Inhalte dadurch sowohl im sichtbaren HTML als auch im JSON-LD wiederverwendet werden können. Die wichtigsten Felder sind:

slider für die Bühnenbilder

cards für Kacheln, Links, Bilder und Videos

cards:thema für den Titel der Kachel

cards:link für die Zielseite

cards:file für Bild oder Video

cards:alttext für Alternativtexte

cards:bildtext_fuer_screenreader für zugänglichere Videobeschreibungen.

Damit wird die Startseite nicht doppelt gepflegt. Die Inhalte liegen einmal im CMS und werden an verschiedenen Stellen ausgegeben.

Das sichtbare Template der Startseite

{preload_replace:channels="startseite"}
{layout="DRY/_header-footer"}
<main id="inhalt" class="startseite">
{exp:channel:entries channel="startseite" url_title="pflege-mit-herz" limit="1"}
<section class="buehne">
  <div class="buehnenbilder">
    {slider}
      <img{if slider:count == 1} class="aktiv"{/if}
           src="{slider:file}"
           alt="{slider:alttext}">
    {/slider}
  </div>
  <div class="buehnetext">
    <h1>{title}</h1>
    <a class="bewerben" href="{site_url}jobs/info/stellenangebote">Jetzt bewerben</a>
  </div>
</section>
{/exp:channel:entries}
{exp:channel:entries channel="startseite" url_title="wichtige-informationen" limit="1"}
<section class="bereich">
  <h2>{title}</h2>
  <div class="kacheln">
    {cards}
      <a class="kachelklein" href="{cards:link}">
        <img src="{cards:file}{path}_bildklein/{filename}.{extension}{/cards:file}"
             alt="{cards:alttext}">
        <h3>{cards:thema}</h3>
      </a>
    {/cards}
  </div>
</section>
{/exp:channel:entries}
{exp:channel:entries channel="startseite" url_title="angebote" limit="1"}
<section class="bereich">
  <h2>{title}</h2>
  <div class="kacheln">
    {cards}
      <a class="kachelgross" href="{cards:link}">
        <img src="{cards:file}{path}_bildteaser/{filename}.{extension}{/cards:file}"
             alt="{cards:alttext}">
        <span>{cards:thema}</span>
      </a>
    {/cards}
  </div>
</section>
{/exp:channel:entries}
<section class="bereich">
  <h2>Aktuelles</h2>
  <div class="kacheln">
    {exp:channel:entries channel="aktuelles" dynamic="no" limit="2" orderby="date" sort="desc"}
      <a class="kachelgross" href="{route='aktuelles/eintrag' url_title='{url_title}'}">
        {if teaserbild}
          <img src="{teaserbild}{path}_bildteaser/{filename}.{extension}{/teaserbild}"
               alt="{if alttext}{alttext}{if:else}{title}{/if}">
        {/if}
        <span>{title}</span>
      </a>
    {/exp:channel:entries}
  </div>
</section>
{exp:channel:entries channel="startseite" url_title="videos" limit="1"}
<section class="bereich">
  <h2>{title}</h2>
  <div class="videos">
    {cards}
      <div class="video">
        <video controls aria-label="{if cards:bildtext_fuer_screenreader}{cards:bildtext_fuer_screenreader}{if:else}{cards:thema}{/if}">
          <source src="{cards:file}" type="video/mp4">
        </video>
      </div>
    {/cards}
  </div>
</section>
{/exp:channel:entries}
</main>


Aus dem sichtbaren Aufbau wird JSON-LD

Der entscheidende Punkt ist nun: Die strukturierte Ausgabe folgt exakt dem sichtbaren Aufbau der Startseite. Die Kacheln im Bereich „Die wichtigsten Informationen im Überblick“ werden als ItemList ausgegeben. Dasselbe gilt für Angebote, aktuelle Meldungen und Videos. Die Inhalte kommen dabei nicht aus einem zweiten System, sondern aus denselben ExpressionEngine-Feldern. So entsteht eine saubere Verbindung zwischen redaktioneller Pflege, sichtbarem Frontend und strukturierter Datenausgabe.

Der JSON-LD-Code für die Startseite

{if segment_1 == ""}
<script type="application/ld+json">
{
  "@context":"https://schema.org",
  "@type":"CollectionPage",
  "@id":"{site_url}#startseite",
  "url":"{site_url}",
  "name":"Beispielkunde",
  "description":"Beschreibung über den Beispielkunden.",
  "inLanguage":"de",
  "isPartOf":{
    "@id":"{site_url}#website"
  },
  "about":{
    "@id":"{site_url}#kunde"
  },
  "mainEntity":[
    {exp:channel:entries channel="startseite" url_title="wichtige-informationen" limit="1"}
    {
      "@type":"ItemList",
      "@id":"{site_url}#wichtige-informationen",
      "name":"{title}",
      "itemListElement":[
        {cards}
        {if cards:count > 1},{/if}
        {
          "@type":"ListItem",
          "position":{cards:count},
          "name":"{cards:thema}",
          "url":"{cards:link}",
          "image":"{cards:file}{path}_bildklein/{filename}.{extension}{/cards:file}"
        }
        {/cards}
      ]
    }
    {/exp:channel:entries},
    {exp:channel:entries channel="startseite" url_title="angebote" limit="1"}
    {
      "@type":"ItemList",
      "@id":"{site_url}#angebote",
      "name":"{title}",
      "itemListElement":[
        {cards}
        {if cards:count > 1},{/if}
        {
          "@type":"ListItem",
          "position":{cards:count},
          "name":"{cards:thema}",
          "url":"{cards:link}",
          "image":"{cards:file}{path}_bildteaser/{filename}.{extension}{/cards:file}"
        }
        {/cards}
      ]
    }
    {/exp:channel:entries},
    {
      "@type":"ItemList",
      "@id":"{site_url}#aktuelles",
      "name":"Aktuelles",
      "itemListElement":[
        {exp:channel:entries channel="aktuelles" dynamic="no" limit="2" orderby="date" sort="desc"}
        {if count > 1},{/if}
        {
          "@type":"ListItem",
          "position":{count},
          "name":"{title}",
          "url":"{route='aktuelles/eintrag' url_title='{url_title}'}"
          {if teaserbild},
          "image":"{teaserbild}{path}_bildteaser/{filename}.{extension}{/teaserbild}"
          {/if}
        }
        {/exp:channel:entries}
      ]
    },
    {exp:channel:entries channel="startseite" url_title="videos" limit="1"}
    {
      "@type":"ItemList",
      "@id":"{site_url}#videos",
      "name":"{title}",
      "itemListElement":[
        {cards}
        {if cards:count > 1},{/if}
        {
          "@type":"ListItem",
          "position":{cards:count},
          "item":{
            "@type":"VideoObject",
            "name":"{cards:thema}",
            "contentUrl":"{cards:file}"
          }
        }
        {/cards}
      ]
    }
    {/exp:channel:entries}
  ]
}
</script>
{/if}


Warum diese Lösung sauber ist

Die Startseite wird nicht künstlich mit strukturierten Daten angereichert. Sie wird so beschrieben, wie sie tatsächlich aufgebaut ist. Die sichtbaren Kachelbereiche werden zu ItemList. Die einzelnen Kacheln werden zu ListItem. Die Videos werden nicht wie normale Links behandelt, sondern als VideoObject ausgegeben. Aktuelle Meldungen kommen direkt aus dem Channel aktuelles.

Dadurch entsteht kein zusätzliches Pflegeproblem. Die Redakteure pflegen weiterhin die Startseite in ExpressionEngine. Die JSON-LD-Ausgabe nutzt dieselben Inhalte und übersetzt sie in eine maschinenlesbare Struktur. Auch hier zeigt sich die Stärke von ExpressionEngine. Grid-Felder, Channel-Einträge und Templates greifen sauber ineinander. Inhalte werden einmal gepflegt und können trotzdem an mehreren Stellen sinnvoll ausgegeben werden. Die Startseite wird damit nicht nur visuell zum Einstieg in die Website. Sie wird auch semantisch zum Einstieg in den gesamten Informationsbereich. Genau daran schließen im nächsten Schritt die Themenübersichten an.

Themenübersichten mit CollectionPage und ItemList: Von mehreren Templates zu einer zentralen Lösung

Nachdem die Startseite die semantische Grundlage der Website geschaffen hatte, ging es an die Themenübersichten. Für jeden Wissensbereich sollte eine eigene CollectionPage mit den dazugehörigen Fachartikeln ausgegeben werden.Der erste Lösungsansatz lag nahe: Für jeden Hauptbereich einen eigenen JSON-LD-Block anzulegen. Technisch wäre das problemlos möglich gewesen. Praktisch hätte dies jedoch bedeutet, dass nahezu derselbe Code siebenmal im Template vorhanden gewesen wäre. Unterschieden hätten sich im Wesentlichen nur zwei Angaben:

  • der Channel
  • Name und Beschreibung des jeweiligen Themenbereichs

Alle übrigen Bestandteile wären identisch geblieben. Gerade solche Redundanzen führen im Laufe eines Projekts häufig zu Problemen. Wird später eine Eigenschaft ergänzt oder geändert, muss dieselbe Anpassung an mehreren Stellen vorgenommen werden. Mit jeder Erweiterung steigt die Gefahr, dass einzelne Templates unübersichtlich werden. Mein Ziel war deshalb von Anfang Eine JSON-LD-Struktur, die alle Themenbereiche verarbeitet.

Der entscheidende Perspektivwechsel

Zunächst stand die Frage im Mittelpunkt, welcher Channel jeweils geladen werden muss. Im Laufe der Entwicklung wurde jedoch deutlich, dass dies gar nicht die eigentliche Aufgabe ist. Entscheidend ist vielmehr, in welchem Bereich der Website sich der Besucher gerade befindet. Die URL liefert diese Information bereits.

/pflege/info/pflegeberatung

Daraus ergeben sich unmittelbar die wichtigsten Informationen:

  • pflege
  • info
  • pflegeberatung

Nicht der Channel bestimmt also den Kontext der Seite, sondern die URL. Diese kleine Veränderung der Denkweise machte es möglich, sämtliche Themenübersichten mit nur einem einzigen Template abzubilden.

Die URL übernimmt das Routing

Bevor ExpressionEngine den passenden Channel laden kann, wird zunächst geprüft, ob sich die aktuelle Seite überhaupt innerhalb eines der vorgesehenen Hauptbereiche befindet.Erst wenn diese Voraussetzung erfüllt ist, übernimmt segment_1 automatisch den richtigen Channel. Dadurch reagiert das Template ausschließlich auf die gewünschten Themenübersichten und bleibt gleichzeitig flexibel für alle Bereiche. Der Einstieg sieht deshalb folgendermaßen aus.

{if segment_2 == "info"}
{if segment_1 == "pflege"
OR segment_1 == "qualitaet"
OR segment_1 == "wohnen"
OR segment_1 == "essen"
OR segment_1 == "kosten"
OR segment_1 == "jobs"
OR segment_1 == "ueberuns"}

Der eigentliche Channel muss anschließend nicht mehr fest hinterlegt werden.

channel="{segment_1}"

Damit genügt ein einziges Template für sämtliche Wissensbereiche.

Der vollständige Template-Code

{if segment_2 == "info"}
{if segment_1 == "pflege"
OR segment_1 == "qualitaet"
OR segment_1 == "wohnen"
OR segment_1 == "essen"
OR segment_1 == "kosten"
OR segment_1 == "jobs"
OR segment_1 == "ueberuns"}
<script type="application/ld+json">
{
  "@context":"https://schema.org",
  "@type":"CollectionPage",
  "@id":"{site_url}{segment_1}/info/{segment_3}#webpage",
  "url":"{site_url}{segment_1}/info/{segment_3}",
  "name":"{if segment_1 == 'pflege'}Pflege und Betreuung{/if}{if segment_1 == 'qualitaet'}Qualität und Transparenz{/if}{if segment_1 == 'wohnen'}Wohnen und Leben{/if}{if segment_1 == 'essen'}Essen auf Rädern{/if}{if segment_1 == 'kosten'}Kosten und Finanzierung{/if}{if segment_1 == 'jobs'}Jobs und Ehrenamt{/if}{if segment_1 == 'ueberuns'}Über uns{/if}",
  "description":"{if segment_1 == 'pflege'}Beschreibung zum Bereich Pflege und Betreuung des Beispielkunden.{/if}{if segment_1 == 'qualitaet'}Beschreibung zum Bereich Qualität und Transparenz des Beispielkunden.{/if}{if segment_1 == 'wohnen'}Beschreibung zum Bereich Wohnen und Leben des Beispielkunden.{/if}{if segment_1 == 'essen'}Beschreibung zum Bereich Essen auf Rädern des Beispielkunden.{/if}{if segment_1 == 'kosten'}Beschreibung zum Bereich Kosten und Finanzierung des Beispielkunden.{/if}{if segment_1 == 'jobs'}Beschreibung zum Bereich Jobs und Ehrenamt des Beispielkunden.{/if}{if segment_1 == 'ueberuns'}Beschreibung zum Bereich Über uns des Beispielkunden.{/if}",
  "inLanguage":"de",
  "isPartOf":{
    "@id":"{site_url}#website"
  },
  "about":{
    "@id":"{site_url}#kunde"
  },
  "mainEntity":{
    "@type":"ItemList",
    "itemListElement":[
      {exp:channel:entries
        channel="{segment_1}"
        limit="6"
        orderby="date"
        sort="asc"
        dynamic="no"
      }
      {if count > 1},{/if}
      {
        "@type":"ListItem",
        "position":{count},
        "name":"{title:attr_safe}",
        "url":"{site_url}{segment_1}/{url_title}"
        {if teaser},
        "description":"{teaser:attr_safe}"
        {/if}
        {if teaserbild},
        "image":"{teaserbild}"
        {/if}
      }
      {/exp:channel:entries}
    ]
  }
}
</script>
{/if}
{/if}


Warum die CollectionPage eine Beschreibung erhält

Nachdem die technische Umsetzung funktionierte, stellte sich eine weitere Frage: Reichen Titel und URL aus, um einen Themenbereich sinnvoll zu beschreiben? Formal wäre das ausreichend gewesen. Inhaltlich blieb jedoch viel Potenzial ungenutzt.

Deshalb erhielt nicht nur jedes Listenelement eine Beschreibung über das vorhandene Teaser-Feld. Auch die CollectionPage selbst bekam eine eigene description. Dadurch beschreiben die strukturierten Daten nicht mehr nur eine Sammlung von Links, sondern den gesamten Themenbereich und seine inhaltliche Ausrichtung.

Der zusätzliche Pflegeaufwand war gleich null. Alle Informationen waren bereits im CMS eingepflegt und mussten lediglich an der passenden Stelle erneut ausgegeben werden.

In der Folge wird dieses Prinzip auf die einzelnen Artikel übertragen. Auch dort entsteht mit derselben Template-Strategie eine zentrale JSON-LD-Ausgabe – ohne redundanten Code.

Die gleiche Strategie für alle Artikel

Nachdem die Themenübersichten umgesetzt waren, wurde derselbe Gedanke auf die einzelnen Fachartikel übertragen. Auch hier sollte möglichst wenig redundanter Template-Code entstehen.Die Lösung folgt deshalb demselben Prinzip wie zuvor. Zunächst wird geprüft, ob sich die aktuelle Seite in einem der vorgesehenen Hauptbereiche befindet. Anschließend übernimmt ExpressionEngine automatisch den passenden Channel. Der eigentliche Fachartikel wird danach über das zweite URL-Segment geladen. Dadurch entsteht auch für sämtliche Fachartikel nur ein einziges zentrales Template. Neue Bereiche lassen sich später problemlos ergänzen, ohne zusätzlichen JSON-LD-Code anlegen zu müssen.

Der vollständige Template-Code

{if segment_2 != "info" AND segment_2 != ""}
{if segment_1 == "pflege"
OR segment_1 == "qualitaet"
OR segment_1 == "wohnen"
OR segment_1 == "essen"
OR segment_1 == "kosten"
OR segment_1 == "jobs"
OR segment_1 == "ueberuns"}
{exp:channel:entries
    channel="{segment_1}"
    url_title="{segment_2}"
    limit="1"
    require_entry="yes"
    track_views="one"
    dynamic="no"
}
<script type="application/ld+json">
{
  "@context":"https://schema.org",
  "@type":"Article",
  "@id":"{site_url}{segment_1}/{url_title}#article",
  "url":"{site_url}{segment_1}/{url_title}",
  "headline":"{title:attr_safe}",
  "inLanguage":"de",
  "isPartOf":{
    "@id":"{site_url}#website"
  },
  "about":{
    "@id":"{site_url}#kunde"
  }
  {if seo_description},
  "description":"{seo_description:attr_safe}"
  {if:elseif teaser},
  "description":"{teaser:attr_safe}"
  {/if}
  {if teaserbild},
  "image":"{teaserbild}"
  {/if},
  "publisher":{
    "@id":"{site_url}#kunde"
  },
  "mainEntityOfPage":{
    "@type":"WebPage",
    "@id":"{site_url}{segment_1}/{url_title}"
  }
}
</script>
{/exp:channel:entries}
{/if}
{/if}


Vorhandene Inhalte intelligent wiederverwenden

Auch bei den Fachartikeln wurde bewusst auf doppelte Pflege verzichtet. Existiert eine SEO-Beschreibung, wird sie für die JSON-LD-Ausgabe verwendet. Ist keine vorhanden, greift das Template automatisch auf den vorhandenen Teaser zurück.

{if seo_description},
"description":"{seo_description:attr_safe}"
{if:elseif teaser},
"description":"{teaser:attr_safe}"
{/if}

Dadurch erhält jeder Fachartikel eine aussagekräftige Beschreibung, ohne dass zusätzliche Inhalte geschrieben oder gepflegt werden müssen. Dasselbe Prinzip wurde bereits bei den Themenübersichten genutzt. Ein Inhalt wird einmal im CMS gepflegt und anschließend an unterschiedlichen Stellen wiederverwendet – auf der Website ebenso wie innerhalb der strukturierten Daten. Genau dadurch bleibt die Pflege einfach und die Ausgabe konsistent.

Fazit

Dieses Projekt hat einmal mehr gezeigt, dass gute strukturierte Daten nicht mit JSON-LD beginnen, sondern mit einer durchdachten Informationsarchitektur. Erst wenn Inhalte, URL-Struktur und Templates sauber zusammenspielen, lassen sich strukturierte Daten nachhaltig und wartungsfreundlich entwickeln.Genau hier spielt ExpressionEngine seine größten Stärken aus. Die konsequente Trennung von Inhalten, Templates und Logik ermöglicht es, vorhandene Informationen mehrfach zu nutzen, redundanten Code zu vermeiden und eine Lösung zu schaffen, die sich auch Jahre später problemlos erweitern lässt.

Verwandte Artikel

\\\ Update: 06.07.2026   Angelegt: 06.07.2026   Rubrik: ExpressionEngine   Views: 17   

Wissens-Startseite /// Rubrik ExpressionEngine