> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aftersell.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Metafield-Daten auf Warenkorbzeilen anzeigen

> Ein Cart-SDK-Anwendungsfall, der mit registerCartEnricher Metafields aus der Shopify Storefront API auf jede Warenkorbzeile holt und sie anschließend rendert.

Der Warenkorb weiß, was Shopifys Ajax API ihm mitteilt: Titel, Preise, Mengen, Eigenschaften. Deine Metafields kennt er nicht. Ein **Cart Enricher** ruft zusätzliche Produkt- oder Variantenfelder aus der Storefront API ab und hängt sie an jede passende Zeile an, damit du eine Lieferzeitschätzung, einen Hinweis „wird separat versendet“, eine Zutatenliste oder alles andere anzeigen kannst, was du am Produkt speicherst.

Typische Einsatzzwecke: produktspezifische Lieferfenster, Allergen- oder Zutaten-Badges, ein eigenes „Geringer Bestand“-Kennzeichen, Multiplikatoren für Treuepunkte, Preise nur für Abonnenten.

<div id="register-the-enricher">
  ## Registriere den Enricher
</div>

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.hooks.registerCartEnricher({
  id: 'delivery',
  onType: 'Product',
  fragment: `
    deliveryWindow: metafield(namespace: "custom", key: "delivery_window") { value }
    shipsSeparately: metafield(namespace: "custom", key: "ships_separately") { value }
  `,
});
```

Drei Felder:

| Feld       | Beschreibung                                                                                                                                       |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`       | Namespace für das Ergebnis; es landet unter `line.metadata[id]`. Muss eindeutig sein; eine zweite Registrierung mit derselben `id` wird ignoriert. |
| `onType`   | `'Product'` oder `'ProductVariant'`. Zugleich der Join-Schlüssel, also Produkt-ID vs. Varianten-ID.                                                |
| `fragment` | Eine GraphQL-Feldauswahl (ohne äußere geschweifte Klammern), die in die Storefront-Abfrage eingefügt wird. Klammern müssen ausgeglichen sein.      |

Immer wenn der Warenkorb lädt oder sich ändert, ruft Aftersell dein Fragment für jedes Produkt bzw. jede Variante im Warenkorb ab. Der Abruf ist **nicht blockierend**: Der Warenkorb rendert sofort und sendet `cart_updated` erneut, sobald die Daten eintreffen. Ein langsames oder fehlschlagendes Fragment verzögert oder beschädigt den Warenkorb nie.

<div id="read-the-data">
  ## Lies die Daten
</div>

Da die Anreicherung asynchron erfolgt, ist `line.metadata.delivery` so lange `undefined`, bis der erste Abruf abgeschlossen ist. Sichere den Lesezugriff immer ab.

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.events.on('cart_updated', (state) => {
  state.items.forEach((line) => {
    const deliveryWindow = line.metadata.delivery?.deliveryWindow?.value;
    if (!deliveryWindow) return; // not fetched yet

    console.log(line.title, 'arrives in', deliveryWindow);
  });
});
```

<div id="render-it-in-the-cart">
  ## Rendere sie im Warenkorb
</div>

Die Anreicherung legt die Daten auf die Zeile; ein [Custom-Code-Block](/de/aftersell/cart/custom-code-blocks) im React-Modus zeichnet sie. Füge den Block als **Sub-Block von Cart items** hinzu, damit er einmal pro Zeile rendert und diese Zeile als `props.line` erhält:

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomCode(props) {
  const data = props.line?.metadata?.delivery;
  const window_ = data?.deliveryWindow?.value;

  if (!window_) return null;

  return (
    <div className="cart-external-custom-code_html" style={{ fontSize: '12px', opacity: 0.7 }}>
      Arrives in {window_}
    </div>
  );
}
```

<Warning>
  Angereicherte Werte kommen **unverändert und unbereinigt** von der Storefront API zurück. Rendere sie wie oben als Text und niemals mit `dangerouslySetInnerHTML` oder durch das Schreiben von rohem HTML.
</Warning>

<div id="variant-level-data">
  ## Daten auf Variantenebene
</div>

Setze `onType: 'ProductVariant'`, wenn das Metafield an der Variante statt am Produkt hängt:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.hooks.registerCartEnricher({
  id: 'pricing',
  onType: 'ProductVariant',
  fragment: `
    anchorPrice: metafield(namespace: "custom", key: "anchor_price") { value }
    subscriberPrice: metafield(namespace: "custom", key: "subscriber_price") { value }
  `,
});
```

<div id="more-than-metafields">
  ## Mehr als Metafields
</div>

Das Fragment wird in eine Storefront-API-Abfrage eingefügt, daher funktioniert alles, was die API auf einem `Product` oder `ProductVariant` bereitstellt, nicht nur Metafields:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.hooks.registerCartEnricher({
  id: 'productInfo',
  onType: 'Product',
  fragment: `
    tags
    vendor
    productType
    availableForSale
  `,
});
```

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
// Then: warn about anything from a drop-ship vendor.
window.aftersell.cart.events.on('cart_updated', (state) => {
  const hasDropship = state.items.some((line) => {
    const tags = line.metadata.productInfo?.tags;
    return tags?.includes('dropship');
  });
});
```

<div id="things-to-get-right">
  ## Worauf du achten solltest
</div>

* **Sichere jeden Lesezugriff ab.** `metadata` ist standardmäßig `{}`, und dein Namespace ist `undefined`, bis der Abruf abgeschlossen ist. Der Warenkorb rendert immer, bevor die Daten eintreffen.
* **Jede `id` ist ihr eigener Namespace.** Mehrere Enricher koexistieren ohne Kollisionen, auch solche, die von anderen Apps registriert wurden.
* **Metafields müssen für die Storefront sichtbar sein.** Ein Metafield, das nicht für die Storefront API freigegeben ist, gibt `null` zurück. Prüfe die Definition im Shopify-Adminbereich, wenn du nichts zurückbekommst.
* **Halte das Fragment klein.** Es läuft für jedes Produkt im Warenkorb, bei jeder Warenkorbänderung. Frage die Felder ab, die du verwendest, nicht alles.
* **Registriere zur Einrichtungszeit.** Es ist ein Hook, er gehört also an den Anfang deines Initialisierungsskripts.
* **Klammern müssen ausgeglichen sein.** Keine äußeren geschweiften Klammern um das Fragment, aber jede verschachtelte Auswahl braucht ihr eigenes passendes Paar. Ein unausgeglichenes Fragment wird abgelehnt.

<div id="where-to-go-next">
  ## Nächste Schritte
</div>

* **[`registerCartEnricher`](/de/aftersell/cart/sdk-hooks#registercartenricher)**: die vollständige Hook-Referenz.
* **[Custom-Code-Blöcke](/de/aftersell/cart/custom-code-blocks)**: das Rendern der Daten.
* **[Cart-Objekt](/de/aftersell/cart/sdk-cart-object)**: wo `metadata` auf einer Zeile liegt.
