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

# Personalize mensagens com custom_data da API

> Envie dados dinâmicos e específicos por mensagem através da Create Message API usando custom_data. Referencie valores em templates com sintaxe Liquid para personalização em tempo real.

Use o campo `custom_data` na [Create Message API](/reference/create-message) para enviar dados dinâmicos do seu backend e renderizá-los dentro de templates usando [sintaxe Liquid](./using-liquid-syntax).

`custom_data`:

* É **específico da mensagem**
* **Não é armazenado**
* Existe apenas durante a requisição da API
* Deve ser usado com um `template_id`

Referencie valores nos templates com:

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

<Warning>
  `custom_data` é efêmero. Os dados não são salvos nos perfis de usuário e não podem ser reutilizados em mensagens futuras. Se você precisa de dados persistentes, consulte [Personalização de mensagens](./message-personalization).
</Warning>

***

## Quando usar `custom_data`

Use `custom_data` quando você precisa:

* Dados que mudam por mensagem (totais de pedidos, itens do carrinho, saldos)
* Você precisa de arrays (listas de produtos, itens de linha, recomendações)
* Dados que não devem persistir (códigos únicos, URLs temporárias)
* Você envia mensagens disparadas pelo backend
* Você quer personalização em massa em uma única requisição de API

***

## Como funciona a personalização com `custom_data`

Adicionar `custom_data` às mensagens requer alguns passos:

<Steps>
  <Step title="Crie um template">
    Crie um template de Push, Email ou SMS em [Templates](./templates) no painel ou via [Create Template API](/reference/create-template).
  </Step>

  <Step title="Adicione placeholders Liquid">
    Insira referências usando o prefixo obrigatório:

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

  <Step title="Envie custom_data na sua requisição de API">
    Chame a [Create Message API](/reference/create-message) com:

    * `template_id` - O ID do template
    * `custom_data` - O objeto de dados
    * Segmentação de audiência (`include_player_ids`, `include_aliases` ou segments)

    O OneSignal renderiza o template no momento do envio usando seus dados.

    Se a sintaxe Liquid for inválida ou as chaves não existirem, esses campos são renderizados como strings vazias, mas a mensagem ainda é enviada.
  </Step>
</Steps>

***

## Padrões de dados

Exemplos comuns de padrões de dados que você pode usar com `custom_data`.

### Exemplo de JSON plano

Use pares chave-valor simples para personalização básica como nomes, IDs, URLs ou qualquer dado de valor único.

**Caso de uso:** Mensagens transacionais (faturas, recibos, confirmações) onde cada campo contém um único valor.

**Template:**

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

**Requisição de 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"
  }
}
```

**O que o cliente vê:**

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

***

### Exemplo de dados com array

Passe arrays de objetos para trabalhar com múltiplos itens como produtos do carrinho, itens de linha de pedidos ou recomendações. Arrays permitem tanto acesso direto (indexação) quanto iteração (loops).

**Caso de uso:** Exibição de listas de produtos, rankings, resumos de pedidos ou qualquer dado com múltiplos itens.

**Template de indexação (acessando o primeiro item):**

```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>
  **A indexação de arrays começa em 0**, não em 1. O primeiro item é `[0]`, o segundo é `[1]`, etc. Acessar um índice que não existe retorna vazio (nenhum erro é lançado).
</Warning>

**Template com loop (acessando todos os itens):**

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

**Requisição de 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"
      }
    ]
  }
}
```

**O que o cliente vê:**

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

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

**Propriedades úteis de arrays:**

* `{{message.custom_data.cart_items.size}}` — Número de itens no array (retorna `2` neste exemplo)
* `{{message.custom_data.cart_items.first.item_name}}` — Nome do primeiro item (equivalente a `[0]`)
* `{{message.custom_data.cart_items.last.item_name}}` — Nome do último item

***

### Exemplo de personalização em massa

Envie uma única requisição de API para múltiplos usuários onde cada destinatário vê conteúdo personalizado com base no seu `external_id`.

**Como funciona:**

1. Estruture `custom_data` como um objeto onde **as chaves são external\_ids** e **os valores são dados específicos do usuário**
2. No template, use `subscription.external_id` para buscar os dados do destinatário atual
3. O OneSignal renderiza o template uma vez por destinatário com seus dados específicos

**Template:**

```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 }}.
```

**O que está acontecendo:**

* `subscription.external_id` contém o external\_id do destinatário atual (ex.: "user123")
* `message.custom_data.users[subscription.external_id]` busca os dados desse usuário no objeto custom\_data
* `user` se torna uma variável de atalho para os dados desse usuário
* Cada destinatário vê apenas seu próprio conteúdo personalizado

**Requisição de 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" }
    }
  }
}
```

**O que cada usuário vê:**

<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>
  **Requisitos para personalização em massa:**

  * Todos os destinatários devem ter um `external_id` definido no OneSignal
  * Cada `external_id` em `include_aliases` deve ter uma chave correspondente em `custom_data.users`
  * Se o external\_id de um destinatário estiver ausente em `custom_data`, a mensagem dele terá campos vazios
</Info>

***

## Exemplo: Carrinho abandonado com custom\_data

Como criar mensagens de carrinho abandonado para email e push usando `custom_data`.

**Quando usar esta abordagem:**

* Seu servidor detecta o abandono de carrinho (ex.: 1 hora após a última atividade)
* Os dados do carrinho em tempo real estão no seu banco de dados
* Você quer exibir múltiplos produtos com imagens, nomes e preços
* Cada usuário pode ter itens e quantidades diferentes
* Você quer orquestrar a mensagem a partir do seu backend

### Exemplo de payload `custom_data`

Esta é a requisição da [Create Message API](/reference/create-message) para este exemplo.

```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"]
  }
}
```

**Explicação dos campos:**

| Campo              | Tipo   | Finalidade                                                         |
| ------------------ | ------ | ------------------------------------------------------------------ |
| `cart_url`         | string | Link único do carrinho do cliente (para botões/URLs de abertura)   |
| `cart`             | array  | Lista de produtos — suporta contagem, loops e exibição de detalhes |
| `product_image`    | string | Imagem do produto (por item no array)                              |
| `product_name`     | string | Nome do produto (por item)                                         |
| `product_quantity` | string | Quantidade (por item)                                              |
| `product_price`    | string | Preço com formatação (por item)                                    |

<Note>
  Você pode nomear os campos como quiser — apenas certifique-se de que a sintaxe Liquid do seu template corresponda.
</Note>

<Warning>
  **Mantenha abaixo de 2KB:** Se você tem carrinhos grandes, considere limitar aos primeiros 3-5 itens ou enviar apenas campos essenciais para evitar exceder o limite de tamanho.
</Warning>

### Template de email

Este exemplo mostra como criar um template de email que exibe:

* A contagem de itens do carrinho
* Cada produto com imagem, nome, quantidade e preço usando um for-loop
* Um botão que linka para a URL única do carrinho do cliente

<Frame caption="Exemplo de template de email de carrinho abandonado">
  <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="Crie o template de email">
    Navegue até **Messages > Templates > New Email Template** e abra o Editor Drag & Drop.
  </Step>

  <Step title="Adicione a estrutura de layout">
    Crie cinco linhas:

    * Linhas 1, 2 e 4: uma coluna com um bloco **Paragraph**
    * Linha 3: quatro colunas com **HTML | Paragraph | Paragraph | Paragraph**
    * Linha 5: uma coluna com um bloco **Button**

    <Frame caption="Template de email inicial para carrinho abandonado">
      <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="Exiba a contagem de itens">
    Na linha 1, adicione:

    ```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!
    ```

    Para uma gramática melhor, você pode usar uma condicional para dizer "1 item" vs "2 items", mas para emails de carrinho abandonado, o plural geralmente é aceitável.

    ```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="Inicie o loop">
    Use um [for-loop](./using-liquid-syntax#for-loops) para repetir a linha de exibição do produto para cada item no carrinho.

    Na linha 2 (início do loop), adicione isto ao bloco de texto:

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

    **O que isto faz:**

    * Inicia um loop que itera sobre cada objeto no array `cart`
    * Cria uma variável temporária chamada `product` que representa o item atual
    * Tudo entre `{% for %}` e `{% endfor %}` se repete uma vez por item do carrinho
    * Você pode nomear `product` como quiser (ex.: `item`, `cartItem`) — apenas mantenha a consistência

    <Warning>
      Posicionamento do for-loop: Certifique-se de que a sintaxe `{% for %}` esteja em sua própria linha de bloco de texto. Não coloque dentro de uma linha de múltiplas colunas com outro conteúdo, pois isso pode quebrar a renderização do email em alguns clientes.
    </Warning>
  </Step>

  <Step title="Exiba os detalhes do produto">
    Esta linha de 4 colunas mostra imagem, nome, quantidade e preço. Como está dentro do loop, ela se repete para cada item do carrinho.

    Na linha 3 (detalhes do produto), configure:

    **Coluna 1 - Bloco HTML** (imagem do produto):

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

    **Colunas 2–4 - Blocos de texto** (nome do produto, quantidade, preço):

    * Coluna 2: `{{product.product_name}}`
    * Coluna 3: `{{product.product_quantity}}`
    * Coluna 4: `{{product.product_price}}`

    **Como o loop funciona:**

    * Na primeira iteração, `product` = primeiro objeto no array cart
    * `{{product.product_image}}` obtém a URL da imagem do primeiro item
    * Na segunda iteração, `product` = segundo objeto
    * A linha se repete automaticamente para todos os itens do carrinho

    <Warning>
      **Correspondência de nomes de campos:** Chaves como `product_image` devem corresponder exatamente ao seu payload de evento (diferencia maiúsculas e minúsculas). Nomes incompatíveis são renderizados como strings vazias.
    </Warning>
  </Step>

  <Step title="Encerre o loop">
    Feche o loop para marcar onde a repetição termina.

    Na linha 4 (fim do loop), adicione:

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

    <Note>
      Todo `{% for %}` deve ter um `{% endfor %}` correspondente. Se estiver faltando, a renderização do email será quebrada.
    </Note>
  </Step>

  <Step title="Adicione um botão de link do carrinho">
    No bloco **Button** da linha 5, defina a URL de Ação para:

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

    <Frame caption="Template base finalizado de email de carrinho abandonado sem estilização">
      <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="Teste o template">
    * Configure sua requisição de API usando o [Exemplo de payload `custom_data`](#exemplo-de-payload-custom_data)
    * Envie o email para você mesmo.
    * Verifique se os dados são exibidos corretamente.

    <Check>Sucesso! Agora você pode aplicar seu próprio estilo ao template. Consulte [Design de emails com drag-and-drop](./design-emails-with-drag-and-drop).</Check>
  </Step>
</Steps>

### Template de push

Notificações push têm limites de caracteres e restrições do sistema operacional, então em vez de mostrar todos os itens, exiba o primeiro produto e indique a contagem total com gramática adequada.

Aqui está um exemplo de notificação push que vamos construir:

<Frame caption="Exemplo de template de push de carrinho abandonado">
  <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>

**Campo de mensagem:**

```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>
  Consulte [Usando sintaxe Liquid](./using-liquid-syntax#if-elsif-else) para mais informações.
</Info>

**Campo de imagem:**

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

<Info>
  Consulte [Imagens de notificação e rich media](./rich-media) para mais informações.
</Info>

**Campo de URL de abertura:**

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

<Check>
  Sucesso! Salve o template e use seu `template_id` na requisição de API [Create message](/reference/create-message) com a propriedade `custom_data` para testar.
</Check>

***

## Solução de problemas e boas práticas

* **Mantenha simples**: Inclua apenas dados que você realmente usará no template
* **Mantenha abaixo de 2KB**: Monitore o tamanho do seu payload, especialmente com arrays
* **Use nomenclatura consistente**: Mantenha `snake_case` ou `camelCase` em todo o código
* **Valide antes de enviar**: Verifique valores nulos, arrays vazios e campos obrigatórios

**Design de template:**

* **Sempre use filtros default** para campos opcionais:
  ```liquid Liquid theme={null}
  {{message.custom_data.user_name | default: "there"}}
  ```
* **Verifique o tamanho do array antes de iterar**:
  ```liquid Liquid theme={null}
  {% if message.custom_data.items.size > 0 %}
    {% for item in message.custom_data.items %}
      {{item.name}}
    {% endfor %}
  {% endif %}
  ```
* **Teste com casos extremos**: arrays vazios, campos ausentes, contagens máximas de itens

**Tratamento de erros:**

* Registre as respostas da API no lado do servidor para capturar erros de validação
* Monitore as taxas de entrega de mensagens — quedas repentinas podem indicar erros de Liquid
* Mantenha templates de fallback prontos para mensagens transacionais críticas

**Performance:**

* **Pré-formate dados complexos** no seu backend em vez de usar lógica Liquid complexa
* **Faça cache de templates** e reutilize-os em muitas chamadas de API
* Considere separar mensagens transacionais de alto volume de campanhas de marketing

<Accordion title="A mensagem é enviada mas o conteúdo está em branco">
  **Causa:** Erros de sintaxe Liquid ou nomes de campos incompatíveis

  **Soluções:**

  * Verifique se os nomes dos campos correspondem exatamente entre `custom_data` e o template (diferencia maiúsculas e minúsculas)
  * Verifique erros de digitação: `{{message.custom_data.name}}` e não `{{message.custm_data.name}}`
  * Use [filtros default](./using-liquid-syntax#default) para capturar campos ausentes
  * Teste templates com a estrutura real de `custom_data` antes de colocar em produção
</Accordion>

<Accordion title="Erro de API: Corpo da requisição muito grande">
  **Causa:** `custom_data` excede o limite de 2KB

  **Soluções:**

  * Remova campos desnecessários do seu payload
  * Encurte nomes de campos e valores quando possível
  * Limite arrays aos primeiros 3-5 itens
  * Mova conteúdo estático grande (como HTML completo) para o seu template
</Accordion>

***

## Páginas relacionadas

<Columns cols={2}>
  <Card title="Personalização de mensagens" href="./message-personalization" icon="sparkles">
    Visão geral de todas as opções de personalização no OneSignal, incluindo Tags, atributos de usuário e segmentação.
  </Card>

  <Card title="Create Message API" href="/reference/create-message" icon="code">
    Referência completa da API para envio de mensagens com custom\_data, opções de segmentação e todos os campos disponíveis.
  </Card>

  <Card title="Usando sintaxe Liquid" href="./using-liquid-syntax" icon="droplet">
    Referência completa de sintaxe Liquid incluindo filtros, condicionais, loops e manipulação de strings.
  </Card>

  <Card title="Templates" href="./templates" icon="file">
    Crie e gerencie templates de mensagens reutilizáveis para canais de Push, Email, SMS e In-App.
  </Card>
</Columns>

<Info>
  Precisa de ajuda?

  Converse com nossa equipe de Suporte ou envie email para `support@onesignal.com`

  Por favor inclua:

  * Detalhes do problema que você está enfrentando e passos para reproduzir se disponível
  * Seu OneSignal App ID
  * O External ID ou Subscription ID se aplicável
  * A URL para a mensagem que você testou no Dashboard OneSignal se aplicável
  * Quaisquer [logs ou mensagens de erro](/docs/pt-BR/capturing-a-debug-log) relevantes

  Estamos felizes em ajudar!
</Info>

***
