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

# カートラインにメタフィールドのデータを表示する

> registerCartEnricher を使って Shopify Storefront API からメタフィールドを取得し、すべてのカートラインに付与して表示する Cart SDK のユースケース。

カートが知っているのは Shopify の Ajax API が伝える情報、つまりタイトル、価格、数量、プロパティだけです。メタフィールドのことは知りません。**cart enricher** は Storefront API から商品またはバリアントの追加フィールドを取得し、一致するすべてのラインに付与します。これにより、配送予定の目安、「別便で発送」の注意書き、成分リストなど、商品に保存しているあらゆる情報を表示できます。

代表的な用途: 商品ごとの配送期間、アレルゲンや成分のバッジ、カスタムの「残りわずか」フラグ、ロイヤルティポイントの倍率、購読者限定価格。

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

フィールドは 3 つです。

| フィールド      | 説明                                                                        |
| ---------- | ------------------------------------------------------------------------- |
| `id`       | 結果の名前空間。`line.metadata[id]` に格納されます。一意である必要があり、同じ `id` での 2 回目の登録は無視されます。 |
| `onType`   | `'Product'` または `'ProductVariant'`。結合キーでもあるため、商品 ID かバリアント ID かを決めます。     |
| `fragment` | Storefront クエリに差し込まれる GraphQL のフィールド選択(外側の波かっこは不要)。波かっこは対応が取れている必要があります。  |

カートが読み込まれたり変更されたりするたびに、Aftersell はカート内のすべての商品またはバリアントについて fragment を取得します。この取得は**非ブロッキング**です。カートは即座にレンダリングされ、データが届いた時点で `cart_updated` を再発行します。fragment が遅くても失敗しても、カートが遅延したり壊れたりすることはありません。

<div id="read-the-data">
  ## データを読み取る
</div>

エンリッチメントは非同期なので、最初の取得が完了するまで `line.metadata.delivery` は `undefined` です。読み取りは必ずガードしてください。

```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">
  ## カートにレンダリングする
</div>

エンリッチメントがラインにデータを載せ、React モードの[カスタムコードブロック](/ja/aftersell/cart/custom-code-blocks)がそれを描画します。ブロックを **Cart items のサブブロック**として追加すると、ラインごとに 1 回レンダリングされ、そのラインが `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>
  エンリッチされた値は Storefront API から**そのまま、サニタイズされずに**返されます。上記のようにテキストとしてレンダリングし、`dangerouslySetInnerHTML` を使ったり生の HTML を書き込んだりしないでください。
</Warning>

<div id="variant-level-data">
  ## バリアントレベルのデータ
</div>

メタフィールドが商品ではなくバリアントにある場合は、`onType: 'ProductVariant'` を設定します。

```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">
  ## メタフィールド以外にも
</div>

fragment は Storefront API のクエリに差し込まれるため、メタフィールドに限らず、API が `Product` または `ProductVariant` 上で公開しているものなら何でも使えます。

```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">
  ## 押さえておくべきポイント
</div>

* **すべての読み取りをガードする。** `metadata` のデフォルトは `{}` で、取得が完了するまで名前空間は `undefined` です。カートは常にデータの到着前にレンダリングされます。
* **各 `id` は独立した名前空間。** 複数の enricher は、他のアプリが登録したものも含めて、衝突せずに共存します。
* **メタフィールドは Storefront に公開されている必要がある。** Storefront API に公開されていないメタフィールドは `null` を返します。何も返ってこない場合は、Shopify 管理画面で定義を確認してください。
* **fragment は小さく保つ。** カート内のすべての商品に対して、カートが変更されるたびに実行されます。必要なフィールドだけをリクエストし、すべてを取得しないようにしてください。
* **セットアップ時に登録する。** フックなので、Initialization スクリプトの先頭に置くのが適切です。
* **波かっこは対応させる。** fragment を外側の波かっこで囲む必要はありませんが、入れ子の選択には対応するペアが必要です。対応が取れていない fragment は拒否されます。

<div id="where-to-go-next">
  ## 次に読むページ
</div>

* **[`registerCartEnricher`](/ja/aftersell/cart/sdk-hooks#registercartenricher)**: フックの完全なリファレンス。
* **[カスタムコードブロック](/ja/aftersell/cart/custom-code-blocks)**: データのレンダリング。
* **[Cart オブジェクト](/ja/aftersell/cart/sdk-cart-object)**: ライン上の `metadata` の位置。
