Implementieren Sie strukturierte Daten (Schema.org) in Ihr Shoporama-Thema
Vollständige Anleitung für JSON-LD strukturierte Daten in einem Shoporama-Theme. Smarty-Beispiele für Product, Store, BreadcrumbList und AggregateRating mit geeigneten sicheren Methoden.
Strukturierte Daten (Schema.org) helfen Google und anderen Suchmaschinen dabei, den Inhalt Ihrer Seiten zu verstehen. Für einen Online-Shop ist es besonders wichtig, Produkte, Shop-Informationen, Breadcrumbs und Produktbewertungen zu markieren, damit Sie in den Suchergebnissen „Rich Snippets“ mit beispielsweise Preis, Lagerbestand und Sternebewertung erhalten.
Tipp: Shoporama fügt über unsere integrierten SEO-Funktionen automatisch grundlegende Schema.org-Markups für Produkte hinzu. Erfahren Sie mehr über automatische strukturierte Daten und SEO in Shoporama. Dieser Artikel richtet sich an alle, die das Markup in ihrem Theme selbst erstellen oder erweitern möchten.

Was sind strukturierte Daten?
Strukturierte Daten sind eine standardisierte Methode, den Inhalt einer Seite in einem Format zu beschreiben, das Suchmaschinen verstehen. JSON-LD ist das empfohlene Format und wird in einem <script type="application/ld+json">-Tag platziert. Dies hat keinen Einfluss auf das visuelle Erscheinungsbild der Seite, liefert den Suchmaschinen jedoch strukturierte Informationen, die für Rich Snippets genutzt werden können.
Die richtigen „safe“-Methoden bei SafeProduct, SafeWebshop und SafeCompany
Bevor Sie Ihr eigenes JSON-LD-Markup erstellen, ist es wichtig, die „safe“-Methoden zu kennen, die tatsächlich für die Objekte in einem Shoporama-Theme verfügbar sind. Dies sind die stabilen Methoden, die Sie in Smarty verwenden können.
Bei $product (SafeProduct):
- getName(), getDescription(), getOwnId(), getGtin(), getMpn(), getBrandName()
- getPrice(), getSalePrice(), getRealPrice(), getLowest30DayPrice()
- getStockCount(), getIsInStock() und getAllowNegativeStock()
- getImage() und getImages() geben ein SafeImage mit getSrc($w, $h, $type) zurück
- getAvgRating($no_round), getReviewCount(), getProductReviews($limit)
- getUrl() liefert den relativen Pfad des Produkts
Auf $webshop (SafeWebshop):
- getName(), getDescription(), getCurrency(), getUrl(), getLogo()
- getCompany() gibt ein SafeCompany-Objekt zurück
Bei $webshop->getCompany() (SafeCompany):
- getName(), getRegNr(), getEmail(), getPhone()
- getAddress(), getZipcode(), getCity(), getCountry()
Hinweis: Verwenden Sie nicht $product->getStock(), $product->getAverageRating(), $webshop->getCurrencyCode(), $webshop->getDomain(), $webshop->getEmail() oder $webshop->getPhone(). Diese sind nicht als „safe“-Methoden verfügbar, und Ihr Theme wird einen Fehler auslösen. Verwenden Sie stattdessen getStockCount(), getAvgRating(), getCurrency(), getUrl() und getCompany()->getEmail()/getPhone().
Escaping: Verwenden Sie @json_encode, nicht escape:javascript
JSON-LD ist JSON, und JSON hat seine eigenen Regeln für die Schreibweise von Sonderzeichen. Dies ist mit Abstand der häufigste Grund dafür, dass ein ansonsten korrektes Markup von Google abgelehnt wird; daher lohnt es sich, sich damit vertraut zu machen, bevor du deinen ersten Block schreibst.
Verwende in JSON-LD nicht |escape:'javascript '. Dies wandelt ein Apostroph in \' um, was in JavaScript gültig ist, nicht jedoch in JSON, wo diese Escape-Sequenz gar nicht existiert. Ein einziges Produkt mit einem Apostroph im Namen, z. B. „Bo’s Kaffe“, reicht daher aus, dass Google den gesamten Block verwirft und die Seite Preis, Lagerstatus und Sterne auf einen Schlag verliert. In der Search Console wird dies als „Bad escape sequence in string“ angezeigt.
Verwenden Sie stattdessen |@json_encode. Diese Funktion schreibt den Wert als fertigen JSON-String einschließlich der Anführungszeichen, sodass die Anführungszeichen aus Ihrer Vorlage entfernt werden müssen:
Falsch: "name": "<{$product->getName()|escape:'javascript'}>",
Richtig: "name": <{$product->getName()|@json_encode}>,
Dadurch werden Apostrophe, Anführungszeichen, Backslashes und Zeilenumbrüche korrekt behandelt. Zeilenumbrüche sind besonders zu beachten: Ein über mehrere Zeilen verfasster Bewertungstext zerstört das JSON, wenn er nicht escaped ist, und dies wird weder von |escape noch von <{strip}> abgefangen. Darüber hinaus maskiert die Methode Schrägstriche, sodass ein </script> in einem Produktnamen Ihren Skriptblock nicht vorzeitig schließen kann.
- Wenn das Feld leer sein kann, füge vorher |default:"" ein, z. B. <{$product->getOwnId()|default:""|@json_encode}>. Andernfalls ist das Ergebnis null statt einer leeren Zeichenkette.
- Wenn HTML zuerst entfernt werden soll, füge |strip_tags:true davor ein, also |strip_tags:true|@json_encode.
- In Smarty gibt es kein |escape:'json'. Wenn du es verwendest, findet überhaupt kein Escaping statt.
- Zahlen und feste Werte, z. B. Preis, Währung und schema.org-URLs, müssen weiterhin in einfachen Anführungszeichen stehen. Sie enthalten keine Sonderzeichen.
- |escape:'javascript' ist in normalem JavaScript, z. B. in einem dataLayer-Push, nach wie vor die richtige Wahl. Nur in JSON-LD ist es falsch.
Produkt-Markup (Product)
Der wichtigste Typ für einen Webshop ist das Product-Markup. Fügen Sie den Block in Ihre Produktvorlage ein (typischerweise product/view.html):
<{assign var="availability" value=$product->getStructuredDataAvailability()}>
<{assign var="availabilityStarts" value=$product->getStructuredDataAvailabilityStarts()}>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": <{$product->getName()|@json_encode}>,
"description": <{$product->getDescription()|strip_tags|@json_encode}>,
"sku": <{$product->getOwnId()|@json_encode}>,
<{if $product->getGtin()}>
"gtin": <{$product->getGtin()|@json_encode}>,
<{/if}>
<{if $product->getMpn()}>
"mpn": <{$product->getMpn()|@json_encode}>,
<{/if}>
<{if $product->getBrandName()}>
"brand": {
"@type": "Brand",
"name": <{$product->getBrandName()|@json_encode}>
},
<{/if}>
<{if $product->getImage()}>
"image": "<{$product->getImage()->getSrc(800, 800, 'fit')}>",
<{/if}>
"offers": {
"@type": "Offer",
"url": "<{$webshop->getUrl()}><{$product->getUrl()}>",
"price": "<{$product->getRealPrice()|string_format:"%.2f"}>",
"priceCurrency": "<{$webshop->getCurrency()}>",
"availability": <{$availability|@json_encode}><{if $availabilityStarts}>,
"availabilityStarts": <{$availabilityStarts|@json_encode}><{/if}>
}
}
</script>
Drei wichtige Punkte in diesem Beispiel:
- Der Preis wird mit getRealPrice() abgerufen, sodass eventuelle Sonderpreise und Rabatte berücksichtigt und die Mehrwertsteuer hinzugerechnet werden.
- Die Währung wird mit getCurrency() auf $webshop abgerufen (gibt z. B. „DKK“ oder „EUR“ zurück).
- Der Lagerbestand wird mit getStructuredDataAvailability() abgerufen, das die fertige schema.org-URL zurückgibt, also „https://schema.org/InStock“, „OutOfStock“ oder „BackOrder“. Die Methode verwendet genau dieselbe Logik wie unser Google-Shopping-Feed, sodass die Produktseite und der Feed immer übereinstimmen. Erstellen Sie diese nicht selbst aus getIsInStock() und getAllowNegativeStock(): Diese Kombination übersieht, dass der Shop selbst entscheidet, ob Artikel mit Lieferrückstand als „Backorder“ versendet werden sollen, und genau dann entsteht die Unstimmigkeit, die Sie vermeiden wollten.
- getStructuredDataAvailabilityStarts() liefert das voraussichtliche Lieferdatum eines Artikels mit Nachbestellung, also das Feld „availabilityStarts“. Die Funktion gibt einen leeren Wert zurück, wenn der Artikel nicht nachbestellt ist oder wenn du unter Google Shopping keine Lieferzeit angegeben hast; binde sie daher wie im Beispiel in ein <{if}> -Tag ein.
Wichtig, wenn du Google Shopping nutzt: Google vergleicht den Lagerbestand auf der Produktseite mit dem, den du im Produkt-Feed übermittelst. Stimmen diese beiden Angaben nicht überein, kann Google den Artikel deaktivieren, sodass er sowohl aus den Shopping-Anzeigen als auch aus den kostenlosen Produktanzeigen verschwindet. Wenn du getStructuredDataAvailability() verwendest, können die beiden Angaben nicht miteinander in Konflikt geraten, da der Feed und die Produktseite auf derselben Methode basieren. Wenn du deine eigene Logik für den Lagerbestand programmierst, riskierst du, dass die Seite einen Artikel als „ausverkauft“ anzeigt, während der Feed ihn als käuflich meldet. Die eigenen Themes von Shoporama berücksichtigen dies bereits. Weitere Informationen findest du unter „Google Shopping-Feed einrichten“.
Vorheriger Preis (Omnibus-Richtlinie)
Wenn das Produkt im Sonderangebot ist, empfiehlt Google, den niedrigsten Preis der letzten 30 Tage als Referenzpreis anzuzeigen. Verwende getLowest30DayPrice(), um diesen abzurufen. Die Funktion gibt „null“ zurück, wenn nicht genügend Preisdaten vorliegen.
Produktbewertungen (AggregateRating)
Wenn Sie das integrierte Bewertungssystem von Shoporama verwenden, können Sie eine Durchschnittsbewertung direkt in das „Product“-Markup einfügen. Dadurch werden möglicherweise Sterne in den Google-Suchergebnissen angezeigt. Fügen Sie den Block innerhalb des „Product“-Objekts ein:
<{if $product->getReviewCount() > 0}>
,
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "<{$product->getAvgRating(true)|string_format:"%.1f"}>",
"reviewCount": "<{$product->getReviewCount()}>"
}
<{/if}>
Der Parameter „true“ bei ` getAvgRating()` liefert einen nicht gerundeten Durchschnittswert, was von Google bevorzugt wird (z. B. 4,3 statt nur 4).
Shop-Informationen (Store / LocalBusiness)
Du kannst auch den Webshop selbst kennzeichnen, z. B. in deiner Fußzeilenvorlage. Rufe die Kontaktdaten über $webshop->getCompany() ab, damit die Informationen, die du bereits unter „Unternehmen“, „Unternehmensdaten“ eingegeben hast, automatisch übernommen werden:
<{$company = $webshop->getCompany()}>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Store",
"name": <{$webshop->getName()|@json_encode}>,
"url": "<{$webshop->getUrl()}>"
<{if $company}>
,
<{if $company->getEmail()}>
"email": <{$company->getEmail()|@json_encode}>,
<{/if}>
<{if $company->getPhone()}>
"telephone": <{$company->getPhone()|@json_encode}>,
<{/if}>
"address": {
"@type": "PostalAddress",
"streetAddress": <{$company->getAddress()|@json_encode}>,
"postalCode": <{$company->getZipcode()|@json_encode}>,
"addressLocality": <{$company->getCity()|@json_encode}>,
"addressCountry": <{$company->getCountry()|@json_encode}>
}
<{/if}>
<{if $webshop->getLogo()}>
,
"logo": "<{$webshop->getLogo()->getSrc(400, 400, 'fit')}>"
<{/if}>
}
</script>
Stellen Sie sicher, dass die Unternehmensdaten im Admin-Bereich unter „Unternehmen“, „Unternehmensdaten“ korrekt ausgefüllt sind. Wenn Sie ein stationäres Geschäft betreiben, können Sie „LocalBusiness“ oder einen spezifischeren Subtyp (z. B. „ClothingStore“) als @type verwenden.
Brotkrumen (BreadcrumbList)
Auf Produkt- und Kategorieseiten ist es eine bewährte SEO-Praxis, Breadcrumbs zu markieren. Beispiel für ein Produkt mit Hauptkategorie:
<{if $product->getMainCategory()}>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": <{$webshop->getName()|@json_encode}>,
"item": "<{$webshop->getUrl()}>"
},
{
"@type": "ListItem",
"position": 2,
"name": <{$product->getMainCategory()->getName()|@json_encode}>,
"item": "<{$webshop->getUrl()}><{$product->getMainCategory()->getUrl()}>"
},
{
"@type": "ListItem",
"position": 3,
"name": <{$product->getName()|@json_encode}>,
"item": "<{$webshop->getUrl()}><{$product->getUrl()}>"
}
]
}
</script>
<{/if}>
Testen Sie Ihre strukturierten Daten
Verwende die Tools von Google und Schema.org, um dein Markup zu validieren, bevor du live gehst:
- Der Rich Results Test prüft, ob Ihr Markup Rich Snippets in Google generiert
- Der Schema Markup Validator überprüft die JSON-LD-Syntax
- In der Google Search Console kannst du Berichte zu deinen Produkten und Rich Results einsehen, nachdem die Seiten gecrawlt wurden
Tipp: Wenn du bereits automatische strukturierte Daten in Shoporama aktiviert hast, achte darauf, Duplikate zu vermeiden. Überprüfe, was bereits auf der Seite vorhanden ist, bevor du dein eigenes Markup hinzufügst.
Häufig gestellte Fragen
Muss ich JSON-LD überhaupt selbst programmieren?
Nein, nicht unbedingt. Shoporama verfügt über integrierte automatische strukturierte Daten für Produkte, die den Großteil abdecken. Das eigene Codieren ist vor allem dann relevant, wenn du zusätzliche Felder hinzufügen oder einen spezifischeren @type verwenden möchtest, z. B. für Hotels, Restaurants oder Veranstaltungen.
Welche Schema-Typen kann ich neben „Product“ noch verwenden?
In einem Shoporama-Theme kannst du alle Schema.org-Typen implementieren, die als JSON-LD verfügbar sind. Die für Webshops am häufigsten verwendeten sind „Product“, „Offer“, „AggregateRating“, „Review“, „BreadcrumbList“, „Store“, „LocalBusiness“, „Organization“, „WebSite“ mit „SearchAction“ sowie „FAQPage“ für feste FAQ-Seiten.
Warum erhalte ich Fehler im Rich Results Test?
Typische Fehler sind fehlende Felder (z. B. „price“ ohne „priceCurrency“), eine falsche Formatierung von Zahlen oder Sonderzeichen, die die JSON-Syntax zerstören. Die mit Abstand häufigste Ursache ist das Escaping: Führen Sie alle Textwerte durch |@json_encode und nicht durch |escape:'javascript', da Letzteres ein Apostroph in ungültiges JSON umwandelt. Siehe den Abschnitt über Escaping weiter oben.
Wie lange dauert es, bis ich in Google Sterne sehe?
Google muss die Seite zunächst erneut crawlen, bevor dein neues Markup übernommen wird. Das kann zwischen wenigen Tagen und einigen Wochen dauern. In der Search Console kannst du eine schnelle Neuindizierung einzelner Seiten beantragen.
Beeinflusst das meine Platzierungen bei Google?
Strukturierte Daten sind kein direkter Ranking-Faktor, aber Rich Snippets mit beispielsweise Preis und Sternen machen Ihr Suchergebnis sichtbarer und können die Klickrate erhöhen. Langfristig trägt dies zur Verbesserung Ihrer gesamten SEO bei.
Wie gehe ich mit der Mehrwertsteuer im Preisfeld um?
Verwende getRealPrice(), das den Preis inkl. MwSt. zurückgibt. Das ist der Preis, den der Kunde im Shop vorfindet, und der, den Google im Product-Markup eines B2C-Shops erwartet. Sollst du den Preis ohne MwSt. (B2B) anzeigen, verwende stattdessen getPriceExVat().
Muss ich Bewertungen haben, bevor ich „AggregateRating“ anzeige?
Ja. Füge „AggregateRating“ nur hinzu, wenn das Produkt tatsächlich Bewertungen hat. Das obige Beispiel prüft, ob „getReviewCount() > 0“ ist, damit das Markup nicht zu Produkten ohne Bewertungen hinzugefügt wird. Gefälschte oder leere Bewertungen können eine Strafe von Google nach sich ziehen.
Wo finde ich meine Unternehmensdaten für das Store-Markup?
Gehe im Admin-Bereich unter „Unternehmen“ zu „Unternehmensdaten“. Die Daten, die du hier eingibst, werden über $webshop->getCompany() in deinem Theme verfügbar, sodass der Store-Block automatisch ausgefüllt wird.
Wo muss JSON-LD auf der Seite platziert werden?
Sie können es entweder in <head> oder in <body> platzieren. Beides ist laut Google gültig. Bei Produktseiten ist es üblich, es am Ende der Produktvorlage zu platzieren.
Mein Webshop verkauft in mehreren Sprachen. Brauche ich für jede Sprache ein eigenes Markup?
Ja, Namen und Beschreibungen im Markup müssen die Seite widerspiegeln, die der Kunde sieht. Da $product->getName() und $product->getDescription() automatisch den übersetzten Text für die aktive Sprache zurückgeben, geschieht dies ganz automatisch, wenn du die hier aufgeführten Beispiele verwendest.
Benötigen Sie Hilfe bei strukturierten Daten? Kontaktieren Sie uns unter support@shoporama.dk.
Ähnliche Artikel
SEO im Shoporama
Vollständiger Leitfaden zu den SEO-Funktionen von Shoporama - von Meta-Tags und Sitemap bis zu Google Shopping und AI Assistant.
Produktbewertungen
Erfahren Sie, wie Sie Produktbewertungen in Shoporama nutzen können. Sammeln Sie automatisch Kundenrezensionen, moderieren Sie sie und zeigen Sie...
Variablen in einem Shoporama-Thema
Überblick über die globalen und seitenbezogenen Smarty-Variablen, die in Shoporama-Themen verfügbar sind.
Implementierung von Tracking in ein Shoporama-Thema
Entwicklerhandbuch zum E-Commerce-Tracking in einem Shoporama-Theme: Data Layer, Google Tag Manager, benutzerdefinierte Ereignisse und korrekte...
Blog mit Link zu Ihrem Shop
Vollständige Anleitung zur Blog-Funktion in Shoporama - Beiträge erstellen, Veröffentlichung planen, Produkte verlinken, für Suchmaschinen...
Preisentwicklung und die Omnibus-Richtlinie
Shoporama protokolliert automatisch Preisänderungen und berechnet den korrekten Vorpreis gemäß der Omnibus-Richtlinie. Omnibus-Richtlinie (EU...
Noindex für eine Seite, ein Produkt oder eine Kategorie festlegen
Anleitung zur Einstellung von noindex in Shoporama, damit Suchmaschinen bestimmte Seiten nicht indizieren.
Google Shopping-Feed einrichten
Anleitung zur Einrichtung des Google Shopping-Feeds in Shoporama: Kategorien, benutzerdefinierte Bezeichnungen, Produkt-ID und Katalogabgleich...
Erhalten Sie Sterne bei Google Shopping durch Produktbewertungen
So lassen Sie Ihre Produktbewertungen mithilfe des integrierten Bewertungs-Feeds von Shoporama als Sterne in Google Shopping anzeigen: Aktivierung,...
Produkt-IDs und Katalogabgleich: So werden Ihre Anzeigen mit Ihrem Produkt-Feed abgeglichen
Erläuterung, welche Produkt-ID das Tracking von Shoporama übermittelt, warum diese immer mit dem Google Shopping-Feed übereinstimmt, was...
Verwandte Funktionen
Strukturierte Daten - automatische Schema.org-Auszeichnung
Automatisches Schema.org-Markup für Produkte, Bewertungen, Breadcrumbs und Unternehmensinformationen. Rich Snippets in Google mit Sternen und...
SEO in Shoporama - in Google sichtbar werden
Shoporama verfügt über integrierte SEO-Funktionen: hohe Geschwindigkeit, volle Kontrolle über Titel und Meta-Beschreibungen, dynamische Tags,...