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

# Mostrar dados de metafields nas linhas do carrinho

> Um caso de uso do Cart SDK usando registerCartEnricher para puxar metafields da Shopify Storefront API para cada linha do carrinho e então renderizá-los.

O carrinho sabe o que a Ajax API da Shopify diz a ele: títulos, preços, quantidades, propriedades. Ele não conhece seus metafields. Um **cart enricher** busca campos extras de produto ou variante na Storefront API e os anexa a cada linha correspondente, para que você possa mostrar uma estimativa de entrega, um aviso de "enviado separadamente", uma lista de ingredientes ou qualquer outra coisa que você armazene no produto.

Usos típicos: janelas de entrega por produto, selos de alérgenos ou ingredientes, uma flag personalizada de "estoque baixo", multiplicadores de pontos de fidelidade, preços exclusivos para assinantes.

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

Três campos:

| Campo      | Descrição                                                                                                                        |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `id`       | Namespace para o resultado; ele aparece em `line.metadata[id]`. Deve ser único; um segundo registro com o mesmo `id` é ignorado. |
| `onType`   | `'Product'` ou `'ProductVariant'`. Também é a chave de junção, ou seja, ID de produto vs. ID de variante.                        |
| `fragment` | Uma seleção de campos GraphQL (sem chaves externas) inserida na consulta da Storefront. As chaves devem estar balanceadas.       |

Sempre que o carrinho carrega ou muda, a Aftersell busca seu fragment para cada produto ou variante no carrinho. A busca é **não bloqueante**: o carrinho renderiza imediatamente e reemite `cart_updated` quando os dados chegam. Um fragment lento ou com falha nunca atrasa nem quebra o carrinho.

<div id="read-the-data">
  ## Ler os dados
</div>

Como o enriquecimento é assíncrono, `line.metadata.delivery` é `undefined` até a primeira busca resolver. Sempre proteja a leitura.

```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">
  ## Renderizar no carrinho
</div>

O enriquecimento coloca os dados na linha; um [bloco Custom code](/pt/aftersell/cart/custom-code-blocks) em modo React os desenha. Adicione o bloco como um **sub-bloco de Cart items** para que ele renderize uma vez por linha e receba essa linha como `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>
  Os valores enriquecidos voltam da Storefront API **como estão e sem sanitização**. Renderize-os como texto, como acima, e nunca com `dangerouslySetInnerHTML` nem escrevendo HTML bruto.
</Warning>

<div id="variant-level-data">
  ## Dados no nível da variante
</div>

Defina `onType: 'ProductVariant'` quando o metafield está na variante em vez de no produto:

```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">
  ## Mais que metafields
</div>

O fragment é inserido em uma consulta da Storefront API, então qualquer coisa que a API expõe em um `Product` ou `ProductVariant` funciona, não só 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">
  ## Coisas para acertar
</div>

* **Proteja toda leitura.** `metadata` tem `{}` como padrão e seu namespace é `undefined` até a busca resolver. O carrinho renderiza antes de os dados chegarem, sempre.
* **Cada `id` é seu próprio namespace.** Vários enrichers coexistem sem colidir, incluindo os registrados por outros apps.
* **Os metafields devem estar visíveis para a Storefront.** Um metafield que não está exposto à Storefront API retorna `null`. Verifique a definição no admin da Shopify se você não receber nada de volta.
* **Mantenha o fragment pequeno.** Ele executa para cada produto no carrinho, em cada mudança do carrinho. Peça os campos que você usa, não tudo.
* **Registre no momento de configuração.** É um hook, então pertence ao topo do seu script de Initialization.
* **As chaves devem estar balanceadas.** Sem chaves externas ao redor do fragment, mas qualquer seleção aninhada precisa do seu próprio par correspondente. Um fragment desbalanceado é rejeitado.

<div id="where-to-go-next">
  ## Para onde ir a seguir
</div>

* **[`registerCartEnricher`](/pt/aftersell/cart/sdk-hooks#registercartenricher)**: a referência completa do hook.
* **[Custom code blocks](/pt/aftersell/cart/custom-code-blocks)**: renderizando os dados.
* **[Cart object](/pt/aftersell/cart/sdk-cart-object)**: onde `metadata` fica em uma linha.
