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

# API custom_dataでメッセージをパーソナライズする

> Create Message APIのcustom_dataを使用して、動的なメッセージ固有のデータを送信します。Liquid構文でテンプレート内の値を参照し、リアルタイムのパーソナライゼーションを実現します。

[Create Message API](/reference/create-message)の`custom_data`フィールドを使用して、バックエンドから動的データを送信し、[Liquid構文](./using-liquid-syntax)を使ってテンプレート内でレンダリングします。

`custom_data`:

* **メッセージ固有**のデータです
* **保存されません**
* APIリクエスト中のみ存在します
* `template_id`と一緒に使用する必要があります

テンプレートで値を参照するには：

```liquid Liquid theme={null}
{{ message.custom_data.key_name }}
```

<Warning>
  `custom_data`は一時的なデータです。ユーザープロファイルには保存されず、将来のメッセージで再利用することはできません。永続的なデータが必要な場合は、[メッセージパーソナライゼーション](./message-personalization)を参照してください。
</Warning>

***

## `custom_data`を使用するタイミング

`custom_data`は以下の場合に使用します：

* データがメッセージごとに変わる場合（注文合計、カートアイテム、残高）
* 配列が必要な場合（商品リスト、明細項目、おすすめ商品）
* データを永続化すべきでない場合（ワンタイムコード、一時的なURL）
* バックエンドからトリガーされるメッセージを送信する場合
* 1回のAPIリクエストで一括パーソナライゼーションを行いたい場合

***

## `custom_data`パーソナライゼーションの仕組み

メッセージに`custom_data`を追加するには、いくつかの手順が必要です：

<Steps>
  <Step title="テンプレートを作成する">
    ダッシュボードまたは[Create Template API](/reference/create-template)を使用して、Push、メール、またはSMSの[テンプレート](./templates)を作成します。
  </Step>

  <Step title="Liquidプレースホルダーを追加する">
    必須のプレフィックスを使用して参照を挿入します：

    ```liquid Liquid theme={null}
    Hi {{ message.custom_data.first_name }},
    Order {{ message.custom_data.order_id }} is confirmed.
    ```
  </Step>

  <Step title="APIリクエストでcustom_dataを送信する">
    以下を含めて[Create Message API](/reference/create-message)を呼び出します：

    * `template_id` - テンプレートのID
    * `custom_data` - データオブジェクト
    * オーディエンスターゲティング（`include_player_ids`、`include_aliases`、またはセグメント）

    OneSignalは送信時にデータを使用してテンプレートをレンダリングします。

    Liquid構文が無効であるか、キーが存在しない場合、それらのフィールドは空文字列としてレンダリングされますが、メッセージは送信されます。
  </Step>
</Steps>

***

## データパターン

`custom_data`で使用できる一般的なデータパターンの例です。

### フラットJSONの例

名前、ID、URL、またはその他の単一値データなど、基本的なパーソナライゼーションにはシンプルなキーバリューペアを使用します。

**ユースケース：** 各フィールドに単一の値を含むトランザクションメッセージ（請求書、領収書、確認）。

**テンプレート：**

```liquid Liquid theme={null}
Invoice {{ message.custom_data.invoice_id }} for {{ message.custom_data.product_name }} is ready.
```

**APIリクエスト：**

```json JSON theme={null}
{
  "app_id": "YOUR_APP_ID",
  "template_id": "YOUR_TEMPLATE_ID",
  "include_email_tokens": ["user@example.com"],
  "custom_data": {
    "invoice_id": "463246732",
    "product_name": "Widget"
  }
}
```

**顧客に表示される内容：**

```liquid Text theme={null}
Invoice 463246732 for Widget is ready.
```

***

### 配列データの例

カート内の商品、注文の明細項目、おすすめ商品など、複数のアイテムを扱うためにオブジェクトの配列を渡します。配列は直接アクセス（インデックス指定）と反復処理（ループ）の両方を可能にします。

**ユースケース：** 商品リスト、ランキング、注文サマリー、またはその他の複数アイテムデータの表示。

**インデックス指定テンプレート（最初のアイテムにアクセス）：**

```liquid Liquid theme={null}
Your {{message.custom_data.cart_items[0].item_name}} is waiting for you!
Image: {{message.custom_data.cart_items[0].img_url}}
```

<Warning>
  **配列のインデックスは0から始まります**（1ではありません）。最初のアイテムは`[0]`、2番目は`[1]`です。存在しないインデックスにアクセスすると空が返されます（エラーはスローされません）。
</Warning>

**ループテンプレート（すべてのアイテムにアクセス）：**

```liquid Liquid theme={null}
{% for item in message.custom_data.cart_items %}
- {{ item.item_name }} — {{ item.img_url }}
{% endfor %}
```

**APIリクエスト：**

```json theme={null}
{
  "app_id": "YOUR_APP_ID",
  "template_id": "YOUR_TEMPLATE_ID",
  "include_email_tokens": ["user@example.com"],
  "custom_data": {
    "cart_items": [
      {
        "item_name": "sweater",
        "img_url": "https://.../sweater.png"
      },
      {
        "item_name": "socks",
        "img_url": "https://.../socks.png"
      }
    ]
  }
}
```

**顧客に表示される内容：**

```liquid Text theme={null}
Your sweater is waiting for you!
Image: https://.../sweater.png

- sweater — https://.../sweater.png
- socks — https://.../socks.png
```

**便利な配列プロパティ：**

* `{{message.custom_data.cart_items.size}}` — 配列内のアイテム数（この例では`2`を返します）
* `{{message.custom_data.cart_items.first.item_name}}` — 最初のアイテムの名前（`[0]`と同等）
* `{{message.custom_data.cart_items.last.item_name}}` — 最後のアイテムの名前

***

### 一括パーソナライゼーションの例

1回のAPIリクエストを複数のユーザーに送信し、各受信者が`external_id`に基づいたパーソナライズされたコンテンツを表示できるようにします。

**仕組み：**

1. `custom_data`を**キーがexternal\_id**で**値がユーザー固有のデータ**であるオブジェクトとして構造化します
2. テンプレートで`subscription.external_id`を使用して現在の受信者のデータを検索します
3. OneSignalは受信者ごとに、その受信者固有のデータでテンプレートを1回レンダリングします

**テンプレート：**

```liquid theme={null}
{% assign user = message.custom_data.users[subscription.external_id] %}
Hi {{ user.first_name }}, you have {{ user.points }} points. Your level is {{ user.level }}.
```

**処理の内容：**

* `subscription.external_id`には現在の受信者のexternal\_idが含まれています（例：「user123」）
* `message.custom_data.users[subscription.external_id]`はcustom\_dataオブジェクトからそのユーザーのデータを検索します
* `user`はそのユーザーのデータのショートハンド変数になります
* 各受信者は自分のパーソナライズされたコンテンツのみを見ることができます

**APIリクエスト：**

```json theme={null}
{
  "app_id": "YOUR_APP_ID",
  "template_id": "YOUR_TEMPLATE_ID",
  "include_aliases": {
    "external_id": ["user123", "user456"]
  },
  "custom_data": {
    "users": {
      "user123": { "first_name": "John", "points": "150", "level": "Gold" },
      "user456": { "first_name": "Sarah", "points": "200", "level": "Platinum" }
    }
  }
}
```

**各ユーザーに表示される内容：**

<Check>
  * **John**（user123）：「Hi John, you have 150 points. Your level is Gold.」
  * **Sarah**（user456）：「Hi Sarah, you have 200 points. Your level is Platinum.」
</Check>

<Info>
  **一括パーソナライゼーションの要件：**

  * すべての受信者がOneSignalで`external_id`を設定している必要があります
  * `include_aliases`内の各`external_id`に対応するキーが`custom_data.users`に必要です
  * 受信者のexternal\_idが`custom_data`に存在しない場合、そのメッセージのフィールドは空になります
</Info>

***

## 例：custom\_dataを使用したカゴ落ちメッセージ

`custom_data`を使用して、メールとプッシュの両方でカゴ落ちメッセージを構築する方法です。

**このアプローチを使用するタイミング：**

* サーバーがカゴ落ちを検出した場合（例：最後のアクティビティから1時間後）
* リアルタイムのカートデータがデータベースにある場合
* 画像、名前、価格付きの複数の商品を表示したい場合
* 各ユーザーのアイテムと数量が異なる可能性がある場合
* バックエンドからメッセージをオーケストレーションしたい場合

### `custom_data`ペイロードの例

この例の[Create Message API](/reference/create-message)リクエストです。

```json JSON theme={null}
{
  "custom_data": {
    "cart_url": "https://yourdomain.com/cart",
    "cart": [
      {
        "product_name": "24 Pack of Acorns",
        "product_image": "https://i.imgur.com/ssPCfbC.png",
        "product_price": "$12.99",
        "product_quantity": "1"
      },
      {
        "product_name": "Fancy Sweater",
        "product_image": "https://i.imgur.com/8QWTfV4.png",
        "product_price": "$9.99",
        "product_quantity": "1"
      }
    ]
  },
  "app_id": "YOUR_APP_ID",
  "template_id": "YOUR_TEMPLATE_ID",
  "include_aliases": {
    "external_id": ["YOUR_EXTERNAL_ID"]
  }
}
```

**フィールドの説明：**

| フィールド              | 型      | 用途                        |
| ------------------ | ------ | ------------------------- |
| `cart_url`         | string | 顧客固有のカートリンク（ボタン/起動URLに使用） |
| `cart`             | array  | 商品リスト — カウント、ループ、詳細表示に対応  |
| `product_image`    | string | 商品画像（配列内のアイテムごと）          |
| `product_name`     | string | 商品名（アイテムごと）               |
| `product_quantity` | string | 数量（アイテムごと）                |
| `product_price`    | string | フォーマット済み価格（アイテムごと）        |

<Note>
  フィールド名は自由に設定できます。テンプレートのLiquid構文が一致していることを確認してください。
</Note>

<Warning>
  **2KB以下に抑えてください：** カートが大きい場合は、最初の3〜5アイテムに制限するか、必須フィールドのみを送信して、サイズ制限を超えないようにしてください。
</Warning>

### メールテンプレート

この例では、以下を表示するメールテンプレートの構築方法を説明します：

* カートアイテム数
* forループを使用した各商品の画像、名前、数量、価格
* 顧客固有のカートURLにリンクするボタン

<Frame caption="カゴ落ちメールテンプレートの例">
  <img src="https://mintcdn.com/onesignal/KSCNwSpBCNSQ8xdF/images/docs/fd61543-Screenshot_2023-08-28_at_10.52.05_AM.png?fit=max&auto=format&n=KSCNwSpBCNSQ8xdF&q=85&s=4128b15d8d53d69c6626e129eee538fa" width="693" height="1477" data-path="images/docs/fd61543-Screenshot_2023-08-28_at_10.52.05_AM.png" />
</Frame>

<Steps>
  <Step title="メールテンプレートを作成する">
    **Messages > Templates > New Email Template**に移動し、ドラッグ＆ドロップエディターを開きます。
  </Step>

  <Step title="レイアウト構造を追加する">
    5つの行を作成します：

    * 行1、2、4：**Paragraph**ブロックを含む1列
    * 行3：**HTML | Paragraph | Paragraph | Paragraph**の4列
    * 行5：**Button**ブロックを含む1列

    <Frame caption="カゴ落ち用メールテンプレートのスターター">
      <img src="https://mintcdn.com/onesignal/v-hm59YoewwF90UX/images/email/starter-template-abandoned-cart.png?fit=max&auto=format&n=v-hm59YoewwF90UX&q=85&s=551e9ec4618f64fdc0b6ab610a537c48" width="2968" height="2124" data-path="images/email/starter-template-abandoned-cart.png" />
    </Frame>
  </Step>

  <Step title="アイテム数を表示する">
    行1に以下を追加します：

    ```liquid Liquid theme={null}
    We're holding onto {{message.custom_data.cart.size}} items in your cart, but don't wait too long, other squirrels are getting ahead!
    ```

    文法を改善するために、「1 item」と「2 items」を条件分岐で使い分けることもできますが、カゴ落ちメールでは通常、複数形で問題ありません。

    ```liquid Liquid theme={null}
    {% assign cart = message.custom_data.cart %}
    {% assign item_count = cart.size | plus: 0 %}
    {% if item_count == 1 %}
    We're holding onto {{item_count}} item in your cart, but don't wait too long, other squirrels are getting ahead!
    {% endif %}
    {% if item_count > 1 %}
    We're holding onto {{item_count}} items in your cart, but don't wait too long, other squirrels are getting ahead!
    {% endif %}
    ```
  </Step>

  <Step title="ループを開始する">
    [forループ](./using-liquid-syntax#for-loops)を使用して、カート内の各アイテムに対して商品表示行を繰り返します。

    行2（ループ開始）のテキストブロックに以下を追加します：

    ```liquid Text theme={null}
    {% for product in message.custom_data.cart %}
    ```

    **この処理の内容：**

    * `cart`配列内の各オブジェクトを反復するループを開始します
    * 現在のアイテムを表す`product`という一時変数を作成します
    * `{% for %}`と`{% endfor %}`の間のすべてがカートアイテムごとに1回繰り返されます
    * `product`は任意の名前（例：`item`、`cartItem`）に変更できますが、一貫性を保ってください

    <Warning>
      forループの配置：`{% for %}`構文は独自のテキストブロック行に配置してください。他のコンテンツを含む複数列の行の中に入れないでください。一部のメールクライアントでレンダリングが崩れる可能性があります。
    </Warning>
  </Step>

  <Step title="商品詳細を表示する">
    この4列の行は、画像、名前、数量、価格を表示します。ループ内にあるため、カートアイテムごとに繰り返されます。

    行3（商品詳細）を設定します：

    **列1 - HTMLブロック**（商品画像）：

    ```html HTML theme={null}
    <img src="{{product.product_image}}" alt="Product image" style="max-width:100%;" />
    ```

    **列2〜4 - テキストブロック**（商品名、数量、価格）：

    * 列2：`{{product.product_name}}`
    * 列3：`{{product.product_quantity}}`
    * 列4：`{{product.product_price}}`

    **ループの動作：**

    * 最初の反復では、`product` = カート配列の最初のオブジェクト
    * `{{product.product_image}}`は最初のアイテムの画像URLを取得します
    * 2回目の反復では、`product` = 2番目のオブジェクト
    * この行はすべてのカートアイテムに対して自動的に繰り返されます

    <Warning>
      **フィールド名の一致：** `product_image`のようなキーは、イベントペイロードと完全に一致する必要があります（大文字小文字を区別）。不一致の場合、空文字列としてレンダリングされます。
    </Warning>
  </Step>

  <Step title="ループを終了する">
    ループを閉じて、繰り返しの終了位置を示します。

    行4（ループ終了）に以下を追加します：

    ```liquid Liquid theme={null}
    {% endfor %}
    ```

    <Note>
      すべての`{% for %}`には対応する`{% endfor %}`が必要です。これがない場合、メールのレンダリングが崩れます。
    </Note>
  </Step>

  <Step title="カートリンクボタンを追加する">
    行5の**Button**ブロックで、アクションURLを以下に設定します：

    ```liquid Text theme={null}
    {{message.custom_data.cart_url}}
    ```

    <Frame caption="スタイリングなしのカゴ落ち用ベースメールテンプレート完成版">
      <img src="https://mintcdn.com/onesignal/v-hm59YoewwF90UX/images/email/finished-template-abandoned-cart-custom-data.png?fit=max&auto=format&n=v-hm59YoewwF90UX&q=85&s=d26b638eb17878bb51c28a5e08f77724" width="2968" height="1716" data-path="images/email/finished-template-abandoned-cart-custom-data.png" />
    </Frame>
  </Step>

  <Step title="テンプレートをテストする">
    * [例の`custom_data`ペイロード](#example-custom-data-payload)を使用してAPIリクエストをセットアップします
    * 自分宛にメールを送信します。
    * データが正しく表示されることを確認します。

    <Check>成功です！これで独自のスタイルをテンプレートに適用できます。[ドラッグ＆ドロップでメールをデザインする](./design-emails-with-drag-and-drop)を参照してください。</Check>
  </Step>
</Steps>

### プッシュテンプレート

プッシュ通知には文字数制限とオペレーティングシステムの制約があるため、すべてのアイテムを表示する代わりに、最初の商品を表示し、適切な文法で合計数を示します。

以下は構築するプッシュ通知の例です：

<Frame caption="カゴ落ちプッシュテンプレートの例">
  <img src="https://mintcdn.com/onesignal/4HyuQPBpu-4xjmQC/images/docs/d0db985-Screenshot_2023-08-28_at_9.30.23_AM.png?fit=max&auto=format&n=4HyuQPBpu-4xjmQC&q=85&s=6cf03ce9b622ba399656f2b14fb055f3" width="688" height="656" data-path="images/docs/d0db985-Screenshot_2023-08-28_at_9.30.23_AM.png" />
</Frame>

**メッセージフィールド：**

```liquid Liquid theme={null}
{% assign cart = message.custom_data.cart %}
{% assign item_count = cart.size | plus: 0 %}
{% if item_count == 1 %}
You left {{cart.first.product_name}} in your cart.
{% endif %}
{% if item_count == 2 %}
You left {{cart.first.product_name}} and {{item_count | minus: 1}} more item in your cart.
{% endif %}
{% if item_count > 2 %}
You left {{cart.first.product_name}} and {{item_count | minus: 1}} more items in your cart.
{% endif %}
```

<Info>
  詳細については、[Liquid構文の使用](./using-liquid-syntax#if-elsif-else)を参照してください。
</Info>

**画像フィールド：**

```liquid Liquid theme={null}
{{message.custom_data.cart.first.product_image | default: "https://i.imgur.com/ssPCfbC.png"}}
```

<Info>
  詳細については、[通知画像とリッチメディア](./rich-media)を参照してください。
</Info>

**起動URLフィールド：**

```liquid Liquid theme={null}
{{cart_url | default: "https://yourdomain.com/cart"}}
```

<Check>
  成功です！テンプレートを保存し、その`template_id`を[Create message](/reference/create-message) APIリクエストで`custom_data`プロパティと一緒に使用してテストしてください。
</Check>

***

## トラブルシューティングとベストプラクティス

* **シンプルに保つ**：テンプレートで実際に使用するデータのみを含めてください
* **2KB以下に抑える**：特に配列を含む場合、ペイロードサイズを監視してください
* **一貫した命名規則を使用する**：全体を通して`snake_case`または`camelCase`で統一してください
* **送信前にバリデーションする**：null値、空の配列、必須フィールドを確認してください

**テンプレート設計：**

* **オプションフィールドには常にdefaultフィルターを使用してください**：
  ```liquid Liquid theme={null}
  {{message.custom_data.user_name | default: "there"}}
  ```
* **ループ前に配列サイズを確認してください**：
  ```liquid Liquid theme={null}
  {% if message.custom_data.items.size > 0 %}
    {% for item in message.custom_data.items %}
      {{item.name}}
    {% endfor %}
  {% endif %}
  ```
* **エッジケースでテストしてください**：空の配列、欠落フィールド、最大アイテム数

**エラーハンドリング：**

* バリデーションエラーをキャッチするために、APIレスポンスをサーバーサイドでログに記録してください
* メッセージ配信率を監視してください — 急激な低下はLiquidエラーを示している可能性があります
* 重要なトランザクションメッセージ用にフォールバックテンプレートを準備しておいてください

**パフォーマンス：**

* 複雑なLiquidロジックを使用する代わりに、バックエンドで**複雑なデータを事前にフォーマット**してください
* **テンプレートをキャッシュ**して、多数のAPI呼び出しで再利用してください
* 大量のトランザクションメッセージとマーケティングキャンペーンを分離することを検討してください

<Accordion title="メッセージは送信されるがコンテンツが空白">
  **原因：** Liquid構文エラーまたはフィールド名の不一致

  **解決方法：**

  * `custom_data`とテンプレート間でフィールド名が完全に一致していることを確認してください（大文字小文字を区別）
  * タイプミスを確認してください：`{{message.custom_data.name}}`であり、`{{message.custm_data.name}}`ではありません
  * 欠落フィールドをキャッチするために[defaultフィルター](./using-liquid-syntax#default)を使用してください
  * 本番環境に導入する前に、実際の`custom_data`構造でテンプレートをテストしてください
</Accordion>

<Accordion title="APIエラー：リクエストボディが大きすぎます">
  **原因：** `custom_data`が2KB制限を超えています

  **解決方法：**

  * ペイロードから不要なフィールドを削除してください
  * 可能な場合はフィールド名と値を短縮してください
  * 配列を最初の3〜5アイテムに制限してください
  * 大きな静的コンテンツ（完全なHTMLなど）はテンプレートに移動してください
</Accordion>

***

## 関連ページ

<Columns cols={2}>
  <Card title="メッセージパーソナライゼーション" href="./message-personalization" icon="sparkles">
    Tags、ユーザー属性、セグメンテーションを含む、OneSignalのすべてのパーソナライゼーションオプションの概要。
  </Card>

  <Card title="Create Message API" href="/reference/create-message" icon="code">
    custom\_data、ターゲティングオプション、すべての利用可能なフィールドを含む、メッセージ送信の完全なAPIリファレンス。
  </Card>

  <Card title="Liquid構文の使用" href="./using-liquid-syntax" icon="droplet">
    フィルター、条件分岐、ループ、文字列操作を含む、完全なLiquid構文リファレンス。
  </Card>

  <Card title="Templates" href="./templates" icon="file">
    Push、メール、SMS、アプリ内チャネル用の再利用可能なメッセージテンプレートの作成と管理。
  </Card>
</Columns>

<Info>
  サポートが必要ですか？

  サポートチームとチャットするか、`support@onesignal.com`にメールしてください

  以下を含めてください：

  * 発生している問題の詳細と再現手順（利用可能な場合）
  * OneSignal App ID
  * 該当する場合は、External IDまたはSubscription ID
  * 該当する場合は、OneSignalダッシュボードでテストしたメッセージのURL
  * 関連する[ログまたはエラーメッセージ](/docs/ja/capturing-a-debug-log)

  お気軽にお問い合わせください！
</Info>

***
