> ## 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.

# Mostra i dati dei metafield sulle righe del carrello

> Un caso d'uso del Cart SDK che usa registerCartEnricher per portare i metafield dalla Shopify Storefront API su ogni riga del carrello, per poi renderizzarli.

Il carrello sa ciò che gli dice l'Ajax API di Shopify: titoli, prezzi, quantità, proprietà. Non conosce i tuoi metafield. Un **cart enricher** recupera campi extra di prodotto o variante dalla Storefront API e li allega a ogni riga corrispondente, così puoi mostrare una stima di consegna, un avviso "spedito separatamente", una lista di ingredienti o qualsiasi altra cosa memorizzi sul prodotto.

Usi tipici: finestre di consegna per prodotto, badge di allergeni o ingredienti, un flag personalizzato di "scorte limitate", moltiplicatori di punti fedeltà, prezzi riservati agli abbonati.

<div id="register-the-enricher">
  ## Registra l'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 }
  `,
});
```

Tre campi:

| Campo      | Descrizione                                                                                                                                 |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`       | Namespace per il risultato; finisce in `line.metadata[id]`. Deve essere unico; una seconda registrazione con lo stesso `id` viene ignorata. |
| `onType`   | `'Product'` o `'ProductVariant'`. È anche la chiave di join, quindi ID prodotto vs. ID variante.                                            |
| `fragment` | Una selezione di campi GraphQL (senza graffe esterne) inserita nella query Storefront. Le graffe devono essere bilanciate.                  |

Ogni volta che il carrello si carica o cambia, Aftersell recupera il tuo fragment per ogni prodotto o variante nel carrello. Il fetch è **non bloccante**: il carrello renderizza immediatamente e riemette `cart_updated` quando i dati arrivano. Un fragment lento o fallimentare non ritarda né rompe mai il carrello.

<div id="read-the-data">
  ## Leggi i dati
</div>

Poiché l'arricchimento è asincrono, `line.metadata.delivery` è `undefined` finché il primo fetch non si risolve. Proteggi sempre la lettura.

```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">
  ## Renderizzarlo nel carrello
</div>

L'arricchimento mette i dati sulla riga; un [blocco Custom code](/it/aftersell/cart/custom-code-blocks) in modalità React li disegna. Aggiungi il blocco come **sub-blocco di Cart items** così viene renderizzato una volta per riga e riceve quella riga come `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>
  I valori arricchiti tornano dalla Storefront API **così come sono e non sanificati**. Renderizzali come testo, come sopra, e mai con `dangerouslySetInnerHTML` né scrivendo HTML grezzo.
</Warning>

<div id="variant-level-data">
  ## Dati a livello di variante
</div>

Imposta `onType: 'ProductVariant'` quando il metafield vive sulla variante invece che sul prodotto:

```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">
  ## Più che metafield
</div>

Il fragment viene inserito in una query della Storefront API, quindi funziona tutto ciò che l'API espone su un `Product` o `ProductVariant`, non solo i metafield:

```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">
  ## Cose da fare bene
</div>

* **Proteggi ogni lettura.** `metadata` è `{}` di default e il tuo namespace è `undefined` finché il fetch non si risolve. Il carrello renderizza prima che i dati arrivino, sempre.
* **Ogni `id` è un namespace a sé.** Più enricher coesistono senza collidere, inclusi quelli registrati da altre app.
* **I metafield devono essere visibili allo Storefront.** Un metafield non esposto alla Storefront API restituisce `null`. Controlla la definizione nell'admin Shopify se non ottieni nulla.
* **Mantieni il fragment piccolo.** Viene eseguito per ogni prodotto nel carrello, a ogni cambiamento del carrello. Chiedi i campi che usi, non tutto.
* **Registra in fase di set-up.** È un hook, quindi va all'inizio del tuo script Initialization.
* **Le graffe devono essere bilanciate.** Nessuna graffa esterna attorno al fragment, ma qualsiasi selezione annidata richiede la propria coppia corrispondente. Un fragment sbilanciato viene rifiutato.

<div id="where-to-go-next">
  ## Dove andare adesso
</div>

* **[`registerCartEnricher`](/it/aftersell/cart/sdk-hooks#registercartenricher)**: il riferimento completo dell'hook.
* **[Blocchi Custom code](/it/aftersell/cart/custom-code-blocks)**: renderizzare i dati.
* **[Cart object](/it/aftersell/cart/sdk-cart-object)**: dove si trova `metadata` su una riga.
