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:

  1. Wählen Sie den Ausgabeort. Eine Produktkarte, ein Hero-Bereich, technische Daten und Empfehlungen sind unterschiedliche Snippets mit unterschiedlichen Namen.
  2. Ermitteln Sie den Storefront-Kontext: Tenant, Produktvariante, Locale, Sales Channel und Währung. Der Client darf diese Werte nicht raten.
  3. Prüfen Sie, ob die Variante für diesen Kontext freigegebene Produktinhalte, eine passende ProductRoute und bei Bedarf veröffentlichte Medien hat.
  4. Legen Sie den Snippet-Namen nach dem Ausgabeort fest, zum Beispiel product-detail-hero. Packen Sie Locale oder Sales Channel nicht in den Namen.
  5. Entscheiden Sie, ob das Snippet optional oder required ist. Required passt nur, wenn die Detailseite ohne diesen Bereich fachlich nicht ausgeliefert werden soll.
  6. Bauen Sie das HTML-Template gegen das Preview-ViewModel. Lesen Sie optionale Felder mit index und with, damit fehlende Inhaltszwecke keinen Template-Fehler auslösen.
  7. Nutzen Sie den Preview-Tab mit einer realen resourceId, Locale und salesChannelId. Prüfen Sie gerendertes HTML und das zurückgelieferte viewModel.
  8. Starten Sie nach Inhalt-, Medien-, Scope- oder Template-Änderungen den Snippet-Rebuild für den betroffenen Scope.
  9. Binden Sie das gebaute Artefakt über den passenden Storefront-Pfad ein: serverseitig über productSnippet oder 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-card für Listen und Suchergebnisse
  • product-teaser für Empfehlungen oder Startseitenbereiche
  • product-detail-summary für den oberen Bereich einer Produktdetailseite
  • product-options fü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.

AusgabeortTypischer NameRequired?
Such- oder Kategorielisteproduct-cardNein
Produktdetail-Heroproduct-detail-heroNur wenn die serverseitige Detailseite ohne Hero nicht sinnvoll ist
Redaktioneller Detailinhaltproduct-detail-contentMeist optional
Technische Datenproduct-detail-specsOptional oder required je nach Produkttyp
Empfehlungen oder Zubehörproduct-detail-recommendationsMeist 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:

TrefferPriorität
Sales Channel und Locale passen1
Sales Channel passt, Locale leer2
Locale passt, Sales Channel leer3
Sales Channel und Locale leer4

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.

VorlageSpracheVertriebskanalWann verwenden?
GloballeerleerDas Markup ist für alle Sprachen und Kanäle gleich und liest sichtbare Texte aus Produktinhalten oder Übersetzungen.
SprachspezifischgesetztleerLayout, feste Labels oder Textreihenfolge unterscheiden sich pro Sprache, aber nicht pro Kanal.
Channel-spezifischleergesetztEin Vertriebskanal braucht eine andere Darstellung, aber die Sprache ändert das Template nicht.
KombiniertgesetztgesetztEin 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:

html
<article class="product-card">
  <h2>{{ .name }}</h2>
  {{ if .description_short }}
    <p>{{ .description_short }}</p>
  {{ end }}
</article>

Beispiel für einen Detailabschnitt:

html
<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:

FeldBedeutungHinweis
idProduktvarianten-IDFür Datenattribute oder Debugging, nicht als sichtbarer Produktname
tenant_idTenant-IDNur verwenden, wenn ein öffentlicher Asset-Pfad sie braucht
family_idProduktfamilien-IDNicht als Kategorie- oder URL-Ersatz nutzen
skuSKU der VarianteSichtbar nur, wenn der Shop SKU anzeigen soll
title, nameVariantenname oder public-safe NameGeeignet für einfache Karten und Überschriften
base_unit_codeBasiseinheitNur anzeigen, wenn fachlich relevant
description_shortKurzbeschreibung aus dem öffentlichen HauptzweckKann leer sein
product_urlLive-Route des öffentlichen HauptzwecksKann leer sein, wenn keine passende ProductRoute live ist
primary_image_urlÖffentlich auslieferbarer HauptbildpfadKann leer sein
attributesVariantenattribute als ObjektNur für Darstellung, nicht für Produktlogik
contentInhalte nach ZweckHauptpfad für strukturierte Produktinhalte
recommendation_groupsPublic-safe ProduktrelationenNur gefüllt, wenn Scope mit Sales Channel und Locale auflösbar ist
localeNormalisierte Locale des ScopesNur vorhanden, wenn ein Locale-Scope verwendet wird
sales_channel_idSales-Channel-ID des ScopesNur 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.

html
{{ with .primary_image_url }}
  <img class="product-card__image" src="{{ . }}" alt="">
{{ end }}
html
{{ 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:

html
{{ 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:

html
{{ 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:

lua
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:

html
{{ 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 id mit der gewünschten Variante überein?
  • Sind locale und sales_channel_id für den geplanten Scope gesetzt?
  • Liegt der benötigte Inhalt unter content.<purposeKey>.fields?
  • Enthält product_url eine Live-Route, wenn das Snippet verlinkt?
  • Ist primary_image_url gesetzt, wenn das Snippet ein Produktbild zeigen soll?
  • Sind recommendation_groups vorhanden, 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:

  1. Sie lädt den Storefront-Kontext.
  2. Sie sucht Produkte über den Public Catalog.
  3. Sie lädt Product Summary oder Produktdetaildaten.
  4. Sie rendert Produktrelationen aus öffentlichen Recommendation-Gruppen, wenn die Detaildaten oder Snippet-Artefakte sie enthalten.
  5. Sie löst Preise und Verfügbarkeit getrennt über Pricing auf.
  6. Sie bindet ein passendes Snippet-Artefakt nur ein, wenn Tenant, Variante, Sprache und Vertriebskanal zum aktuellen Kontext passen.
  7. 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:

PfadVerwendungVerhalten bei fehlendem Snippet
Dynamische Produktdetailseite im SitegeneratorDas 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-ClientDer 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:

yaml
containers:
  mainContent:
    - type: productSnippet
      name: product-detail-hero
      params:
        required: true
    - type: productSnippet
      name: product-detail-content

Beispiel für eine headless Detailabfrage mit konkreten Snippet-Namen:

http
GET /api/v1/public/v1/catalog/products/by-route/produkte/beispielprodukt?snippets=product-detail-hero,product-detail-content

Snippet-URLs zeigen auf das gebaute Artefakt, zum Beispiel:

text
/assets/<tenant-id>/snippets/variant/<variant-id>/<snippet-name>/ch/<sales-channel-id>/loc/<locale>/index.html

Ungescopte Fallback-Artefakte liegen unter:

text
/assets/<tenant-id>/snippets/variant/<variant-id>/<snippet-name>.html

Die 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 salesChannelId ohne Fehler.
  • Das Preview-viewModel enthält die erwarteten Root-Felder oder content.<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 503 mehr.
  • 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.