Snippet-Vorlagen entwickeln
Nutzen Sie Snippet-Vorlagen, um freigegebene Produktdaten als vorgerenderte HTML-Artefakte für Produktkarten, Teaser oder Detailbereiche bereitzustellen. Snippets kapseln Darstellung. Sie sind keine Quelle für Preise, Verfügbarkeit, Checkout-Regeln oder Warenkorbentscheidungen.
Die fachliche Pflege von Produktinhalten ist in Produktinhalte pflegen beschrieben. Die Konfiguration von Inhaltsschemata und Profilen steht in PIM-Inhalte konfigurieren.
Diese Seite ist die technische Hauptseite für Frontend-Entwickler. Sie beschreibt, welche Daten vor dem Template-Bau feststehen müssen, welche Felder im Snippet-ViewModel verfügbar sind, wie Sie fehlende Inhalte defensiv behandeln und wie die Storefront ein gebautes Artefakt einbindet.
Voraussetzungen
Klären Sie vor der Template-Entwicklung:
- Der Zielmandant wurde mit Tenant Init vorbereitet. Für Snippet-Arbeit muss die PIM-Basis initialisiert sein; für Hintergrundjobs und Rebuilds müssen die zugehörigen tenant-lokalen Jobs vorhanden sein. System > Betriebsbereitschaft zeigt keine blockierenden systemweiten Hinweise.
- Der aktuelle Storefront-Kontext liefert Sales Channel, Locale und Währung für die spätere Einbindung.
- Die Produktvarianten haben freigegebene Produktinhalte für den benötigten Zweck, die Sprache und bei Bedarf den Vertriebskanal.
- Inhaltsschema und Inhaltsprofil passen zur Produktfamilie und zum Veröffentlichungsziel.
- Nach relevanten Inhalts- oder Template-Änderungen wird ein Snippet-Rebuild gestartet.
Wenn eine dieser Voraussetzungen fehlt, bleibt die öffentliche Storefront trotz Template technisch korrekt. Rendern Sie dann aus Public Catalog, Detail und Pricing oder zeigen Sie einen definierten Ladezustand.
Für serverseitig ausgelieferte Produktdetailseiten entscheidet das Site-Template, welche Snippet-Bereiche Pflicht sind. Fehlt ein Required-Snippet für Tenant, Variante, Locale und SalesChannel, liefert die Detailseite 503, bis der Snippet-Rebuild das Artefakt erzeugt hat. Optionale Bereiche können leer bleiben. Der 503-Fall wird als kritischer Storefront-Telemetry-Fehler gemeldet. Nutzen Sie die Telemetry-Instanz, um Route, Variante, Locale, Sales Channel und fehlende Snippet-Namen zu prüfen.
Arbeitsablauf
Bauen Sie ein Produkt-Snippet in dieser Reihenfolge:
- Wählen Sie den Ausgabeort. Eine Produktkarte, ein Hero-Bereich, technische Daten und Empfehlungen sind unterschiedliche Snippets mit unterschiedlichen Namen.
- Ermitteln Sie den Storefront-Kontext: Tenant, Produktvariante, Locale, Sales Channel und Währung. Der Client darf diese Werte nicht raten.
- Prüfen Sie, ob die Variante für diesen Kontext freigegebene Produktinhalte, eine passende ProductRoute und bei Bedarf veröffentlichte Medien hat.
- Legen Sie den Snippet-Namen nach dem Ausgabeort fest, zum Beispiel
product-detail-hero. Packen Sie Locale oder Sales Channel nicht in den Namen. - Entscheiden Sie, ob das Snippet optional oder required ist. Required passt nur, wenn die Detailseite ohne diesen Bereich fachlich nicht ausgeliefert werden soll.
- Bauen Sie das HTML-Template gegen das Preview-ViewModel. Lesen Sie optionale Felder mit
indexundwith, damit fehlende Inhaltszwecke keinen Template-Fehler auslösen. - Nutzen Sie den Preview-Tab mit einer realen
resourceId, Locale undsalesChannelId. Prüfen Sie gerendertes HTML und das zurückgelieferteviewModel. - Starten Sie nach Inhalt-, Medien-, Scope- oder Template-Änderungen den Snippet-Rebuild für den betroffenen Scope.
- Binden Sie das gebaute Artefakt über den passenden Storefront-Pfad ein: serverseitig über
productSnippetoder headless über die Snippet-Referenzen aus Public Catalog.
Die Aufgabe ist abgeschlossen, wenn Preview und Rebuild für denselben Scope erfolgreich sind und die öffentliche Produktseite oder Detailantwort das passende Snippet-Artefakt für Tenant, Variante, Locale und Sales Channel liefert.
Einsatzbereiche
Typische Vorlagen sind:
product-cardfür Listen und Suchergebnisseproduct-teaserfür Empfehlungen oder Startseitenbereicheproduct-detail-summaryfür den oberen Bereich einer Produktdetailseiteproduct-optionsfür Relationsgruppen wie Zubehör oder Erweiterungen- eigene Detailabschnitte für technische Daten, Lieferumfang, Kompatibilität oder Downloads
Planen Sie Vorlagen nach Ausgabeort, nicht nach einzelnen Produktfamilien. Eine Produktkarte sollte dieselbe Vorlage behalten, solange Layout und Ziel gleich bleiben.
| Ausgabeort | Typischer Name | Required? |
|---|---|---|
| Such- oder Kategorieliste | product-card | Nein |
| Produktdetail-Hero | product-detail-hero | Nur wenn die serverseitige Detailseite ohne Hero nicht sinnvoll ist |
| Redaktioneller Detailinhalt | product-detail-content | Meist optional |
| Technische Daten | product-detail-specs | Optional oder required je nach Produkttyp |
| Empfehlungen oder Zubehör | product-detail-recommendations | Meist optional |
Vorlage anlegen
Öffnen Sie PIM > Konfiguration > Snippet-Vorlagen, um eine Vorlage zu pflegen.
Legen Sie fest:
- Ressourcentyp
variant - technischer Name der Vorlage
- optional Sprache
- optional Vertriebskanal
- HTML-Template
- optionales Transform-Skript
- Aktivstatus
Snippet-Namen tragen keine Scope-Bedeutung. Nutzen Sie nicht Namen wie product-card-de oder product-card-b2b-de, wenn Sprache oder Vertriebskanal über die Vorlage gesetzt werden sollen. Der gleiche Name darf als globales, locale-spezifisches, channel-spezifisches oder kombiniert gescoptes Template existieren. Beim Rebuild gewinnt der spezifischste Treffer:
| Treffer | Priorität |
|---|---|
| Sales Channel und Locale passen | 1 |
| Sales Channel passt, Locale leer | 2 |
| Locale passt, Sales Channel leer | 3 |
| Sales Channel und Locale leer | 4 |
Sprache, Vertriebskanal und globaler Scope
Der Scope einer Snippet-Vorlage besteht aus Sprache und Vertriebskanal. Beide Felder sind optional. Global bedeutet hier: Die Vorlage hat keine Sprache und keinen Vertriebskanal. Sie ist der Fallback, wenn für den aktuellen Storefront-Kontext keine spezifischere aktive Vorlage existiert.
| Vorlage | Sprache | Vertriebskanal | Wann verwenden? |
|---|---|---|---|
| Global | leer | leer | Das Markup ist für alle Sprachen und Kanäle gleich und liest sichtbare Texte aus Produktinhalten oder Übersetzungen. |
| Sprachspezifisch | gesetzt | leer | Layout, feste Labels oder Textreihenfolge unterscheiden sich pro Sprache, aber nicht pro Kanal. |
| Channel-spezifisch | leer | gesetzt | Ein Vertriebskanal braucht eine andere Darstellung, aber die Sprache ändert das Template nicht. |
| Kombiniert | gesetzt | gesetzt | Ein bestimmter Kanal und eine bestimmte Sprache brauchen eine eigene Darstellung. |
Ein globales Template übersetzt nichts automatisch. Wenn das Template feste sichtbare Wörter enthält, zum Beispiel Mehr erfahren, Technische Daten oder Lieferumfang, müssen diese Texte aus einem übersetzten Inhalt, Übersetzungsbündel oder aus sprachspezifischen Templates kommen. Nutzen Sie global nur für Markup, das mit jeder späteren Storefront-Sprache korrekt bleibt.
Ein globales Template erzeugt außerdem nicht automatisch Artefakte für alle Sprachen und Vertriebskanäle. Der Rebuild materialisiert Artefakte für die fachlich vorhandenen Scopes der Varianten. Wenn ein Produkt in de-DE und en-US sichtbar sein soll, müssen Produktinhalte, Routen, Veröffentlichungen und Rebuild-Scope zu diesen Sprachen passen. Das globale Template kann dann als Darstellungsvorlage dienen; es ersetzt nicht die fehlenden Sprachdaten.
Unterscheiden Sie den globalen Template-Fallback vom Rebuild ohne Filter. Ein tenantweiter Rebuild ohne --locale und ohne --sales-channel-id bedeutet: Workspace baut die verfügbaren Snippet-Scopes des Tenants neu. Das ist nicht dasselbe wie ein globales Template und nicht die Anweisung, nur ungescopte Artefakte zu erzeugen.
Template-Struktur
Ein wartbares Snippet erfüllt diese Regeln:
- Es enthält semantisches HTML für den Zielbereich.
- Es zeigt optionale Abschnitte nur an, wenn Daten vorhanden sind.
- Es rendert redaktionelle HTML-Felder nur an dafür vorgesehenen Stellen.
- Es rendert Produktrelationen nur aus public-safe Recommendation-Gruppen.
- Es nutzt keine internen Admin-Daten.
- Es berechnet keine Preise, Verfügbarkeit oder Checkout-Entscheidungen.
Beispiel für eine Produktkarte:
<article class="product-card">
<h2>{{ .name }}</h2>
{{ if .description_short }}
<p>{{ .description_short }}</p>
{{ end }}
</article>Beispiel für einen Detailabschnitt:
<section class="product-detail-section">
<h2>Beschreibung</h2>
<div class="product-detail-section__content">
{{ .description_short }}
</div>
</section>Snippet-Templates laufen über Go html/template. Normale Platzhalter werden kontextabhängig escaped. Rechnen Sie deshalb nicht damit, dass ein gepflegter String ungeprüft als HTML-Markup ausgegeben wird. Wenn ein Detailbereich Markup braucht, muss der Inhalt vor der Auslieferung fachlich und technisch als dafür geeigneter Vertrag bereitstehen.
ViewModel verstehen
Die Preview und der Snippet-Rebuild verwenden denselben ViewModel-Vertrag. Ohne Lua-Transform sieht das Template die Felder der Variantenprojektion. Die wichtigsten Felder sind:
| Feld | Bedeutung | Hinweis |
|---|---|---|
id | Produktvarianten-ID | Für Datenattribute oder Debugging, nicht als sichtbarer Produktname |
tenant_id | Tenant-ID | Nur verwenden, wenn ein öffentlicher Asset-Pfad sie braucht |
family_id | Produktfamilien-ID | Nicht als Kategorie- oder URL-Ersatz nutzen |
sku | SKU der Variante | Sichtbar nur, wenn der Shop SKU anzeigen soll |
title, name | Variantenname oder public-safe Name | Geeignet für einfache Karten und Überschriften |
base_unit_code | Basiseinheit | Nur anzeigen, wenn fachlich relevant |
description_short | Kurzbeschreibung aus dem öffentlichen Hauptzweck | Kann leer sein |
product_url | Live-Route des öffentlichen Hauptzwecks | Kann leer sein, wenn keine passende ProductRoute live ist |
primary_image_url | Öffentlich auslieferbarer Hauptbildpfad | Kann leer sein |
attributes | Variantenattribute als Objekt | Nur für Darstellung, nicht für Produktlogik |
content | Inhalte nach Zweck | Hauptpfad für strukturierte Produktinhalte |
recommendation_groups | Public-safe Produktrelationen | Nur gefüllt, wenn Scope mit Sales Channel und Locale auflösbar ist |
locale | Normalisierte Locale des Scopes | Nur vorhanden, wenn ein Locale-Scope verwendet wird |
sales_channel_id | Sales-Channel-ID des Scopes | Nur vorhanden, wenn ein Channel-Scope verwendet wird |
Das ViewModel kann Kompatibilitätsfelder wie price_amount, price_currency, inventory_physical oder in_stock enthalten. Verwenden Sie diese Felder nicht als Quelle für öffentliche Preis-, Verfügbarkeits- oder Checkout-Entscheidungen. Laden Sie solche Zustände über die dokumentierten Public-Storefront- und Pricing-Verträge.
Felder defensiv lesen
Der Renderer nutzt missingkey=error. Ein direkter Punktpfad auf ein fehlendes Feld kann deshalb den Build oder die Preview abbrechen. Verwenden Sie für optionale Inhalte index und with.
{{ with .primary_image_url }}
<img class="product-card__image" src="{{ . }}" alt="">
{{ end }}{{ with $detail := index .content "website_detail" }}
{{ with $headline := index $detail.fields "headline" }}
<h2>{{ $headline }}</h2>
{{ end }}
{{ with $copy := index $detail.fields "shortDescription" }}
<p>{{ $copy }}</p>
{{ end }}
{{ end }}Wenn ein Feld für den Ausgabeort fachlich verpflichtend ist, behandeln Sie das nicht im Template als stillen Fallback. Klären Sie Inhaltsschema, Inhaltsprofil, Produktinhalt und Veröffentlichung, damit der Rebuild das erwartete Feld im richtigen Scope sieht.
Inhaltszwecke verwenden
Root-Platzhalter wie title, name, description_short oder product_url kommen aus dem Zweck, den Administratoren als öffentlichen Hauptzweck markieren. Nutzen Sie diese Root-Felder für bestehende Produktkarten und einfache Produktdetailbereiche.
Weitere Inhaltszwecke stehen im ViewModel unter content.<purposeKey>. Die gepflegten Schemafelder liegen unter fields:
{{ with $detail := index .content "website_detail" }}
<h2>{{ index $detail.fields "name" }}</h2>
{{ end }}
{{ with $listing := index .content "marketplace_listing" }}
<p>{{ index $listing.fields "headline" }}</p>
{{ end }}Wenn ein Zweck- oder Feldschlüssel Zeichen enthält, die nicht als Punktpfad verwendbar sind, nutzen Sie ebenfalls die index-Schreibweise:
{{ index (index (index .content "marketplace-listing") "fields") "headline" }}Jeder Zweck enthält zusätzlich Metadaten wie purpose_key, locale, sales_channel_id, content_schema_id, content_schema_version und product_url. Verwenden Sie Metadaten nur für Darstellung und Routing, nicht für Preis-, Bestands- oder Checkout-Entscheidungen.
Planen Sie Templates so, dass sie fachliche Inhaltsbereiche kombinieren können. Eine Produktdetailseite kann zum Beispiel den öffentlichen Hauptzweck, technische Daten, Sicherheitshinweise und Downloads rendern. Das Template sollte optionale Zwecke nur ausgeben, wenn sie im ViewModel vorhanden sind.
Erfinden Sie keine kanal- oder layoutgetriebenen Zwecknamen in Templates. Wenn ein Inhalt fachlich Sicherheitshinweis ist, lesen Sie content.safety_instructions; der Sales Channel entscheidet vorher, welcher kanalgebundene oder allgemeine Inhalt im ViewModel liegt. Wenn ein Marktplatzlisting andere Felder braucht, verwenden Sie einen fachlich passenden Marktplatzzweck oder ein kanalgebundenes Profil, nicht einen Template-Hilfsschlüssel.
Lua-Transform verwenden
Nutzen Sie ein Transform-Skript nur, wenn die Vorlage ein kleines, stabiles ViewModel für die Darstellung braucht. Halten Sie den Transform deterministisch und frei von externen Nebenwirkungen.
Beispiel:
local detail = resource.content and resource.content.website_detail or { fields = {} }
local fields = detail.fields or {}
result = {
title = fields.name or resource.name,
teaser = fields.shortDescription or resource.description_short
}Wenn das Skript result setzt, rendert das HTML-Template nur dieses Ergebnis. Wenn Sie das ursprüngliche ViewModel erweitern möchten, ändern Sie view_model und lassen result leer. Kopieren Sie benötigte Felder bewusst, damit das Template nicht versehentlich von internen oder instabilen Daten abhängt.
Der Transform darf keine Preise, Verfügbarkeit, Warenkorbzustände oder interne Admin-Daten berechnen. Laden Sie solche Informationen in der Storefront über die öffentlichen Verträge.
Relationsgruppen anzeigen
Wenn eine Vorlage Produktrelationen rendert, nutzen Sie die im Snippet-ViewModel bereitgestellten recommendation_groups.
Die Gruppen verwenden technische Relationstypen wie accessory, cross_sell, up_sell, substitute, spare_part und bonus_item. Übersetzen Sie sichtbare Überschriften im Template oder in der Storefront, aber ändern Sie die technischen Keys nicht.
Beispiel:
{{ range .recommendation_groups }}
<section class="product-recommendations">
<h2>{{ .label }}</h2>
<div class="product-recommendations__items">
{{ range .items }}
<article class="product-teaser">
<h3>{{ .name }}</h3>
</article>
{{ end }}
</div>
</section>
{{ end }}recommendation_groups sind leer, wenn der Rebuild keinen Sales-Channel- und Locale-Scope hat oder wenn die Zielvarianten im öffentlichen Katalog für diesen Scope nicht gelistet sind. Ein leeres Ergebnis ist kein Grund, interne PIM-Relationen direkt im Frontend nachzuladen.
Preview und Rebuild prüfen
Der Preview-Tab rendert das aktuelle Template gegen eine reale Variante. Geben Sie immer dieselbe Variante, Locale und salesChannelId an, die später auch die Storefront verwendet. Die Preview liefert HTML und viewModel zurück. Prüfen Sie auch globale Vorlagen mit einem konkreten Storefront-Scope. Nur so sehen Sie, ob die globale Vorlage für diese Sprache und diesen Vertriebskanal das richtige ViewModel erhält.
Prüfen Sie im viewModel:
- Stimmt
idmit der gewünschten Variante überein? - Sind
localeundsales_channel_idfür den geplanten Scope gesetzt? - Liegt der benötigte Inhalt unter
content.<purposeKey>.fields? - Enthält
product_urleine Live-Route, wenn das Snippet verlinkt? - Ist
primary_image_urlgesetzt, wenn das Snippet ein Produktbild zeigen soll? - Sind
recommendation_groupsvorhanden, wenn das Snippet Empfehlungen rendert?
Nach Template-, Inhalts-, Medien- oder Scope-Änderungen muss ein Rebuild laufen. Ein Rebuild ohne passenden Scope erzeugt kein Artefakt für die konkrete Storefront. Wenn eine Detailseite danach weiter 503 liefert, prüfen Sie zuerst Tenant, Variante, Locale, Sales Channel, Snippet-Name und Required-Status.
Für sprach- oder channel-spezifische Korrekturen reicht oft ein selektiver Rebuild mit --locale oder --sales-channel-id. Nutzen Sie einen tenantweiten Rebuild, wenn eine globale Vorlage geändert wurde oder wenn mehrere Scopes betroffen sind.
Storefront-Vertrag
Eine Storefront nutzt öffentliche Verträge:
- Sie lädt den Storefront-Kontext.
- Sie sucht Produkte über den Public Catalog.
- Sie lädt Product Summary oder Produktdetaildaten.
- Sie rendert Produktrelationen aus öffentlichen Recommendation-Gruppen, wenn die Detaildaten oder Snippet-Artefakte sie enthalten.
- Sie löst Preise und Verfügbarkeit getrennt über Pricing auf.
- Sie bindet ein passendes Snippet-Artefakt nur ein, wenn Tenant, Variante, Sprache und Vertriebskanal zum aktuellen Kontext passen.
- Sie lässt optionale Snippet-Bereiche weg und behandelt fehlende Required-Snippets als temporär nicht bereite Detailseite.
Wenn kein passendes optionales Snippet vorliegt, rendert die Storefront aus öffentlichen Produktdaten und Pricing oder zeigt einen definierten Ladezustand.
Es gibt zwei Einbindungspfade:
| Pfad | Verwendung | Verhalten bei fehlendem Snippet |
|---|---|---|
| Dynamische Produktdetailseite im Sitegenerator | Das Site-YAML nutzt type: productSnippet mit name und optional params.required: true. Workspace ersetzt den Marker serverseitig durch das Artefakt aus dem aktuellen Site-Scope. | Required liefert 503 Service Unavailable mit Retry-After; optional rendert leer. |
| Headless Storefront-Client | Der Client lädt Produktdetaildaten über Public Catalog und fordert Snippet-Namen an. Die Antwort enthält Snippet-Referenzen mit öffentlichen URLs. | Der Client behandelt fehlende optionale URLs oder 404 als leeren Darstellungsbereich und lädt Preise/Verfügbarkeit weiter getrennt. |
Beispiel für eine dynamische Detailseite:
containers:
mainContent:
- type: productSnippet
name: product-detail-hero
params:
required: true
- type: productSnippet
name: product-detail-contentBeispiel für eine headless Detailabfrage mit konkreten Snippet-Namen:
GET /api/v1/public/v1/catalog/products/by-route/produkte/beispielprodukt?snippets=product-detail-hero,product-detail-contentSnippet-URLs zeigen auf das gebaute Artefakt, zum Beispiel:
/assets/<tenant-id>/snippets/variant/<variant-id>/<snippet-name>/ch/<sales-channel-id>/loc/<locale>/index.htmlUngescopte Fallback-Artefakte liegen unter:
/assets/<tenant-id>/snippets/variant/<variant-id>/<snippet-name>.htmlDie serverseitige Produktdetailseite prüft die Fallback-Reihenfolge selbst: Sales Channel und Locale, Sales Channel, Locale, global. Ein headless Client soll trotzdem den vom Public-Catalog-Vertrag gelieferten Snippet-URL verwenden und keine privaten Dateipfade oder interne Rebuild-Logik nachbauen.
Details zu Katalog, Pricing und Warenkorb finden Sie in Katalog, Preise und Produktdarstellung und Warenkorb, Checkout und Payment.
Erfolg erkennen
Ein Produkt-Snippet ist einsatzbereit, wenn diese Punkte erfüllt sind:
- Die Snippet-Vorlage ist aktiv und hat
resourceType=variant. - Der Preview-Tab rendert mit der echten Variante, Locale und
salesChannelIdohne Fehler. - Das Preview-
viewModelenthält die erwarteten Root-Felder odercontent.<purposeKey>.fields. - Für jeden Ziel-Scope ist klar, ob Workspace eine kombinierte, channel-spezifische, sprachspezifische oder globale Vorlage verwendet.
- Nach dem Rebuild ist das Artefakt über die öffentliche
/assets/...-URL erreichbar. - Eine dynamische Detailseite ersetzt alle
productSnippet-Marker. - Required-Snippets liefern keinen
503mehr. - Preise, Verfügbarkeit, Cart und Checkout kommen weiterhin aus ihren öffentlichen Storefront-Verträgen.
Häufige Fehler
- Eine Snippet-Vorlage enthält Sprache oder Vertriebskanal im Namen statt im Scope.
- Eine globale Vorlage enthält feste sichtbare Texte, die nicht für alle Storefront-Sprachen passen.
- Ein Team erwartet, dass ein globales Template fehlende Produktinhalte, ProductRoutes oder Sprachdaten ersetzt.
- Ein tenantweiter Rebuild ohne Filter wird mit einem globalen Template verwechselt.
- Eine Vorlage rendert leere Familienfelder als sichtbare Leerbereiche.
- Eine Vorlage übersetzt technische Relationstypen statt nur sichtbare Überschriften.
- Ein Transform berechnet Preise oder Verfügbarkeit.
- Eine Storefront behandelt Snippets als Datenquelle für Checkout-Entscheidungen.
- Nach Template- oder Inhaltsänderungen wird kein Rebuild gestartet.
- Ein Template nutzt Punktpfade auf optionale Zwecke oder Felder und bricht bei fehlenden Daten mit einem Template-Fehler ab.
- Preview und Storefront verwenden unterschiedliche Locale- oder Sales-Channel-Werte.
- Ein headless Client baut Snippet-URLs selbst zusammen, obwohl die Detailantwort bereits Snippet-Referenzen liefern kann.
- Ein Required-Snippet wird gesetzt, obwohl der Bereich fachlich optional ist.