> ## 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-data op winkelwagenregels tonen

> Een Cart SDK use case die registerCartEnricher gebruikt om metafields uit de Shopify Storefront API op elke winkelwagenregel te trekken en ze vervolgens te renderen.

De winkelwagen weet wat de Ajax API van Shopify hem vertelt: titels, prijzen, aantallen, properties. Hij kent je metafields niet. Een **cart enricher** haalt extra product- of variantvelden op uit de Storefront API en koppelt ze aan elke overeenkomende regel, zodat je een leverindicatie, een "wordt apart verzonden"-waarschuwing, een ingrediëntenlijst of wat je ook maar op het product opslaat kunt tonen.

Typische toepassingen: levervensters per product, allergenen- of ingrediëntenbadges, een aangepaste "bijna uitverkocht"-vlag, loyaliteitspuntenvermenigvuldigers, prijzen alleen voor abonnees.

<div id="register-the-enricher">
  ## De enricher registreren
</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 }
  `,
});
```

Drie velden:

| Veld       | Beschrijving                                                                                                                                       |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`       | Namespace voor het resultaat; het komt terecht op `line.metadata[id]`. Moet uniek zijn; een tweede registratie met hetzelfde `id` wordt genegeerd. |
| `onType`   | `'Product'` of `'ProductVariant'`. Ook de join-key, dus product-ID vs. variant-ID.                                                                 |
| `fragment` | Een GraphQL-veldselectie (zonder buitenste accolades) die in de Storefront-query wordt gesplitst. Accolades moeten in balans zijn.                 |

Telkens wanneer de winkelwagen laadt of verandert, haalt Aftersell je fragment op voor elk product of elke variant in de winkelwagen. De fetch is **non-blocking**: de winkelwagen rendert onmiddellijk en zendt `cart_updated` opnieuw uit zodra de data binnenkomt. Een traag of falend fragment vertraagt of breekt de winkelwagen nooit.

<div id="read-the-data">
  ## De data lezen
</div>

Omdat enrichment asynchroon is, is `line.metadata.delivery` `undefined` totdat de eerste fetch resolvet. Bescherm de leesactie altijd met een guard.

```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">
  ## Het in de winkelwagen renderen
</div>

Enrichment zet de data op de regel; een [Custom code block](/nl/aftersell/cart/custom-code-blocks) in React-modus tekent het. Voeg het block toe als een **Cart items sub-block** zodat het één keer per regel rendert en die regel ontvangt als `props.line`:

```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>
  Verrijkte waarden komen **as-is en ongesanitized** terug uit de Storefront API. Render ze als tekst, zoals hierboven, en nooit met `dangerouslySetInnerHTML` of door rauwe HTML te schrijven.
</Warning>

<div id="variant-level-data">
  ## Data op variantniveau
</div>

Stel `onType: 'ProductVariant'` in wanneer het metafield op de variant staat in plaats van op het product:

```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">
  ## Meer dan metafields
</div>

Het fragment wordt in een Storefront API-query gesplitst, dus alles wat de API op een `Product` of `ProductVariant` beschikbaar stelt werkt, niet alleen 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">
  ## Dingen om goed te doen
</div>

* **Bescherm elke leesactie.** `metadata` is standaard `{}` en je namespace is `undefined` totdat de fetch resolvet. De winkelwagen rendert altijd voordat de data arriveert.
* **Elk `id` is zijn eigen namespace.** Meerdere enrichers bestaan naast elkaar zonder te botsen, inclusief die door andere apps zijn geregistreerd.
* **Metafields moeten Storefront-zichtbaar zijn.** Een metafield dat niet aan de Storefront API is blootgesteld, geeft `null` terug. Controleer de definitie in de Shopify admin als je niets terugkrijgt.
* **Houd het fragment klein.** Het draait voor elk product in de winkelwagen, bij elke winkelwagenwijziging. Vraag om de velden die je gebruikt, niet om alles.
* **Registreer op set-up-tijd.** Het is een hook, dus hij hoort bovenaan je Initialization-script.
* **Accolades moeten in balans zijn.** Geen buitenste accolades rond het fragment, maar elke geneste selectie heeft zijn eigen bijpassende paar nodig. Een ongebalanceerd fragment wordt geweigerd.

<div id="where-to-go-next">
  ## Waar je verder kunt kijken
</div>

* **[`registerCartEnricher`](/nl/aftersell/cart/sdk-hooks#registercartenricher)**: de volledige hook-referentie.
* **[Custom code blocks](/nl/aftersell/cart/custom-code-blocks)**: de data renderen.
* **[Cart object](/nl/aftersell/cart/sdk-cart-object)**: waar `metadata` op een regel staat.
