Pular para o conteúdo

Configurando o Pushwoosh InboxKit para iOS

Disponível desde o SDK do iOS 7.0.40.

O Pushwoosh InboxKit oferece uma tela de caixa de entrada moderna em UIKit sobre o backend de caixa de entrada existente. Seis layouts de célula padrão cobrem os formatos comuns de cartões de conteúdo — de banners simples a carrosséis de imagens, vídeo em linha e passes do Apple Wallet — botões de CTA em linha lidam com as interações mais comuns, e toda a superfície está aberta para subclassificação se você precisar de um visual personalizado.

Feed do InboxKit mostrando cartões de banner, com legenda, clássico, carrossel, vídeo e Apple Wallet

Feed padrão do InboxKit com cartões de banner, com legenda, clássico, carrossel, vídeo e Apple Wallet.

Quando usar o InboxKit

Anchor link to

Use o InboxKit para qualquer nova integração com iOS. É o substituto recomendado para o módulo mais antigo em Objective-C PushwooshInboxUI.

O InboxKit oferece a você:

  • Seis tipos de célula integrados — banner, com legenda, clássico, carrossel, vídeo e Apple Wallet — selecionados por mensagem através do displayType do payload, ou forçados a partir do código via attributes.forceCellKind. Veja Tipos de cartão para a lista completa. (O cartão Apple Wallet é exclusivo para iOS.)
  • Botões de CTA em linha com um enum tipado PushwooshInboxButtonAction (openURL, dismiss, markRead, custom). O SDK lida com os três primeiros automaticamente; seu delegate roteia custom para sua própria lógica.
  • Suporte à fixação: mensagens com actionParams["pinned"] == true flutuam para o topo do feed e renderizam um glifo de pino.
  • Deslizar para excluir, puxar para atualizar, marcar como lido automaticamente ao desaparecer — tudo alternável via PushwooshInboxKitAttributes.
  • Armazenamento persistente: exclusões e estado de leitura sobrevivem a uma reinicialização do processo, mesmo que a chamada de rede ainda não tenha sido confirmada.
  • Uma classe base aberta PushwooshInboxCell para layouts totalmente personalizados.

O contrato do servidor permanece inalterado — o mesmo backend de caixa de entrada do Pushwoosh, payloads e ferramentas do painel funcionam como antes.

Escolha seu método de integração

Anchor link to

Tipos de cartão

Anchor link to

O InboxKit escolhe um layout de célula por mensagem. O resolvedor padrão lê displayType do payload do push — coloque-o dentro do objeto data, que o SDK entrega sob actionParams. Quando displayType está ausente, o resolvedor recorre a uma heurística: imagem + sem título → banner, imagem + título → com legenda, caso contrário, clássico. Para forçar um layout para todo o feed a partir do código, defina attributes.forceCellKind.

Cada layout rico degrada-se graciosamente: se o payload necessário estiver ausente ou malformado, o cartão volta para classic em vez de renderizar um espaço reservado vazio (e um WARN é registrado).

displayTypeLayoutCampo de payload obrigatórioDegrada para
bannerImagem de sangria total, sem textoimagem (inbox_image ou data.image)classic quando não há imagem
captionedImagem no topo, título + corpo abaixoimagem (inbox_image ou data.image)classic quando não há imagem
classicAvatar inicial colorido + título + corpo
carouselGaleria de múltiplas imagens deslizáveldata.carousel (array de slides)classic quando não há slides
videoPôster com ícone de play, player em tela cheia ao tocardata.video (url + poster opcional)classic quando não há descritor
walletBotão “Adicionar à Carteira da Apple” (somente iOS)data.wallet (URL do .pkpass)classic quando não há URL do passe
Cartão de banner do InboxKit
Cartão de banner
Cartão com legenda do InboxKit
Cartão com legenda
Cartão clássico do InboxKit
Cartão clássico
Cartão de carrossel do InboxKit
Cartão de carrossel
Cartão de vídeo do InboxKit
Cartão de vídeo
Cartão Apple Wallet do InboxKit
Cartão Apple Wallet

Os cartões de banner, com legenda e clássicos são controlados pelos campos de mensagem padrão (imagem, título, corpo) mais o array opcional buttons — veja Adicionar botões de CTA em linha. Os cartões de carrossel, vídeo e Apple Wallet carregam dados estruturados extras dentro de data, documentados abaixo.

Cartão de carrossel

Anchor link to

Um carrossel renderiza várias imagens de uma única mensagem — uma galeria deslizável com legendas por slide e destinos de toque opcionais. Os slides ficam em data.carousel. Cada slide precisa de uma image; title (sobreposição de legenda) e url (deep link aberto ao tocar) são opcionais. Um slide sem imagem é descartado; um toque em um slide sem url recai para a ação de linha padrão da mensagem.

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"request": {
"application": "XXXXX-XXXXX",
"auth": "API_TOKEN",
"notifications": [{
"send_date": "now",
"ios_title": "New arrivals",
"content": "Swipe through this week's drops",
"inbox_days": 7,
"data": {
"displayType": "carousel",
"carousel": [
{ "image": "https://cdn.example.com/inbox/1.jpg", "title": "New in", "url": "myapp://product/1" },
{ "image": "https://cdn.example.com/inbox/2.jpg", "title": "On sale", "url": "myapp://product/2" },
{ "image": "https://cdn.example.com/inbox/3.jpg" }
]
},
"platforms": [1]
}]
}
}

Cartão de vídeo

Anchor link to

Um cartão de vídeo mostra uma imagem de pôster com um ícone de play; tocá-lo abre um player em tela cheia (com som, mesmo com o interruptor de silêncio ativado). O descritor fica em data.video: url é obrigatório e deve ser um stream ou arquivo http/https; poster é uma imagem de pré-visualização opcional.

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"request": {
"application": "XXXXX-XXXXX",
"auth": "API_TOKEN",
"notifications": [{
"send_date": "now",
"ios_title": "Watch the reveal",
"content": "Tap to play",
"inbox_days": 7,
"data": {
"displayType": "video",
"video": {
"url": "https://cdn.example.com/inbox/clip.mp4",
"poster": "https://cdn.example.com/inbox/poster.jpg"
}
},
"platforms": [1]
}]
}
}

Cartão Apple Wallet

Anchor link to

O cartão Apple Wallet mostra uma imagem de herói opcional, título e corpo acima do botão oficial Adicionar à Carteira da Apple. Tocar no botão baixa o .pkpass e apresenta a folha do sistema para adicionar passes. Use-o para entregar cupons, cartões de fidelidade, ingressos ou cartões de embarque diretamente da caixa de entrada. O cartão é exclusivo para iOS / Mac Catalyst — em outras plataformas, a mensagem é renderizada como um cartão clássico.

A URL do passe fica em data.wallet, seja como uma string simples ou como um objeto com um campo pass. Um data.image opcional adiciona a imagem de herói. O botão se esconde automaticamente quando não há URL de passe ou o dispositivo não pode adicionar passes.

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"request": {
"application": "XXXXX-XXXXX",
"auth": "API_TOKEN",
"notifications": [{
"send_date": "now",
"ios_title": "Your loyalty card is ready",
"content": "Add it to Apple Wallet in one tap",
"inbox_days": 7,
"data": {
"displayType": "wallet",
"image": "https://cdn.example.com/inbox/loyalty.png",
"wallet": "https://passes.example.com/v1/passes/pass.com.example.loyalty/abc123?token=…"
},
"platforms": [1]
}]
}
}

O resultado é reportado ao seu delegate:

extension MyInboxHost: PushwooshInboxKitDelegate {
func inboxKit(_ vc: PushwooshInboxKitViewController,
didAddWalletPassFor message: PWInboxMessageProtocol) {
// O passe agora está na Carteira do usuário — mostre uma confirmação se desejar.
}
func inboxKit(_ vc: PushwooshInboxKitViewController,
didFailToAddWalletPassFor message: PWInboxMessageProtocol,
error: Error?) {
// O download falhou — exiba uma nova tentativa, registre em log, etc.
}
}

Ambos os callbacks são opcionais (eles carregam implementações vazias padrão). Um usuário cancelando a folha do sistema não é nem sucesso nem falha, então nenhum callback é disparado nesse caso.

Acessibilidade

Anchor link to

As células do InboxKit estão prontas para o VoiceOver desde o início. Os cartões de banner, com legenda e clássicos expõem seu título, corpo e data através dos rótulos subjacentes, e os botões de CTA em linha leem seus próprios títulos. Os cartões ricos adicionam semântica explícita:

  • Vídeo — o pôster é exposto como um único elemento de botão rotulado “Reproduzir vídeo” (atributos .button + .startsMediaSession), então o VoiceOver o anuncia como um controle de mídia em vez de uma imagem simples.
  • Carrossel — cada slide é um elemento de botão cujo rótulo de acessibilidade é a legenda do slide, ou “Slide” quando não tem nenhuma. O indicador de página anuncia a posição atual como “n de total”.
  • Apple Wallet — o botão Adicionar à Carteira da Apple é o PKAddPassButton padrão da Apple, que carrega seu próprio rótulo de VoiceOver localizado.

Para testes de UI e automação, dois accessibilityIdentifiers estáveis são definidos: inboxkit.video.play no pôster do vídeo e inboxkit.wallet.add no botão da Carteira.

Ler dados personalizados de uma mensagem

Anchor link to

Para fazer um push aparecer na caixa de entrada, a solicitação createMessage da API de Mensagens deve incluir inbox_image, inbox_date ou inbox_days — sem um desses campos, o push é entregue como uma notificação regular e nunca chega ao feed da caixa de entrada. Dados personalizados de formato livre vão sob a chave data, que o SDK entrega ao cliente como o parâmetro u:

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"request": {
"application": "XXXXX-XXXXX",
"auth": "API_TOKEN",
"notifications": [{
"send_date": "now",
"ios_title": "Summer sale",
"content": "30% off everything — limited time only",
"inbox_image": "https://cdn.example.com/inbox/summer.png",
"inbox_days": 7,
"data": {
"displayType": "captioned",
"promo_id": "SUMMER2026",
"screen": "promo_details"
},
"platforms": [1]
}]
}
}

O SDK expõe esse objeto na mensagem da caixa de entrada através de actionParams. Leia-o do delegate quando o usuário tocar na linha ou em um CTA em linha:

extension MyInboxHost: PushwooshInboxKitDelegate {
func inboxKit(_ vc: PushwooshInboxKitViewController,
didSelect message: PWInboxMessageProtocol) -> Bool {
guard let params = message.actionParams as? [String: Any] else { return true }
// O objeto `data` personalizado chega sob a chave "u" —
// seja como um dicionário aninhado ou como uma string codificada em JSON,
// dependendo de como o payload foi construído anteriormente.
let custom: [String: Any]? = {
if let dict = params["u"] as? [String: Any] { return dict }
if let raw = params["u"] as? String,
let bytes = raw.data(using: .utf8),
let parsed = try? JSONSerialization.jsonObject(with: bytes) as? [String: Any] {
return parsed
}
return nil
}()
if let promoId = custom?["promo_id"] as? String {
navigateToPromo(promoId)
return false // nós lidamos com o toque; o SDK não deve executar a ação padrão
}
return true
}
}

A mesma busca actionParams["u"] funciona dentro de inboxKit(_:didTapButton:onMessage:) para botões de CTA em linha. Para os casos de CTA tipados (openURL, dismiss, markRead), o SDK já executa a ação padrão — retorne true para manter esse comportamento, ou false para suprimi-lo e executar o seu próprio.

Adicionar botões de CTA em linha

Anchor link to

Uma mensagem pode carregar até três botões de chamada para ação (CTA) em linha. Os botões ficam ao lado de outros dados personalizados dentro de data como um array buttons. O SDK os renderiza automaticamente dentro das células com legenda e clássicas:

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"request": {
"application": "XXXXX-XXXXX",
"auth": "API_TOKEN",
"notifications": [{
"send_date": "now",
"ios_title": "New promo card",
"content": "Tap a button to claim or save",
"inbox_image": "https://cdn.example.com/inbox/promo.png",
"inbox_days": 7,
"data": {
"displayType": "captioned",
"promo_id": "SUMMER2026",
"buttons": [
{ "title": "Claim", "url": "https://example.com/promo/SUMMER2026" },
{ "title": "Read", "action": "markRead" },
{ "title": "Save", "action": "custom", "tag": "save_promo" }
]
},
"platforms": [1]
}]
}
}

Cada objeto de botão tem estes campos:

CampoTipoQuando
titlestringObrigatório. Rótulo visível do botão.
urlstringUma URL analisável e não vazia produz uma ação openURL. O SDK a abre via UIApplication.shared.open, a menos que seu delegate a suprima.
actionstringToken de ação explícito: dismiss (remove a mensagem do feed), markRead (marca a mensagem como lida) ou custom (tratado pelo host). Não diferencia maiúsculas de minúsculas.
Qualquer outra coisaanyQuando action é custom, todas as chaves no objeto do botão, exceto title e action, são encaminhadas para o seu delegate como o payload personalizado — combine uma chave com o profissional de marketing (por exemplo, tag) e despache com base nela.

Prioridade de resolução: primeiro o token action explícito, depois url se não estiver vazio, caso contrário, o botão cai em custom carregando o payload completo (menos title e action).

Intercepte os toques do seu delegate. A propriedade button.action é o enum tipado PushwooshInboxButtonAction:

extension MyInboxHost: PushwooshInboxKitDelegate {
func inboxKit(_ vc: PushwooshInboxKitViewController,
didTapButton button: PushwooshInboxButton,
onMessage message: PWInboxMessageProtocol) -> Bool {
switch button.action {
case .openURL(let url):
// O comportamento padrão está bom — deixe o SDK abrir a URL.
return true
case .dismiss, .markRead:
// O SDK lida com ambos. Retorne false se quiser substituir.
return true
case .custom(let payload):
// Botão personalizado definido pelo profissional de marketing. Despache com base em uma chave que vocês combinaram.
if let tag = payload["tag"] as? String {
switch tag {
case "save_promo":
saveCurrentPromoLocally(message: message)
default:
break
}
}
return true // ignorado para custom — o SDK nunca executa uma ação padrão aqui
}
}
}