Configuración de Pushwoosh InboxKit para iOS
Disponible desde el SDK de iOS 7.0.40.
Pushwoosh InboxKit ofrece una pantalla de bandeja de entrada moderna de UIKit sobre el backend de bandeja de entrada existente. Seis diseños de celda predeterminados cubren las formas comunes de tarjetas de contenido, desde simples banners hasta carruseles de imágenes, video en línea y pases de Apple Wallet. Los botones CTA en línea manejan las interacciones más comunes, y toda la superficie está abierta para la subclasificación si necesita un aspecto a medida.

Feed predeterminado de InboxKit con tarjetas de banner, con leyenda, clásicas, de carrusel, de video y de Apple Wallet.
Cuándo usar InboxKit
Anchor link toUse InboxKit para cualquier nueva integración de iOS. Es el reemplazo recomendado para el módulo más antiguo de Objective-C PushwooshInboxUI.
InboxKit le ofrece:
- Seis tipos de celdas incorporados — banner, con leyenda, clásica, carrusel, video y Apple Wallet — seleccionados por mensaje a través del
displayTypedel payload, o forzados desde el código a través deattributes.forceCellKind. Consulte Tipos de tarjetas para ver la lista completa. (La tarjeta de Apple Wallet es solo para iOS). - Botones CTA en línea con una enumeración
PushwooshInboxButtonActiontipada (openURL,dismiss,markRead,custom). El SDK maneja los tres primeros automáticamente; su delegado enrutacustoma su propia lógica. - Soporte para fijar: los mensajes con
actionParams["pinned"] == trueflotan hacia la parte superior del feed y renderizan un glifo de pin. - Deslizar para eliminar, tirar para actualizar, marcar como leído automáticamente al desaparecer — todo conmutable a través de
PushwooshInboxKitAttributes. - Almacenamiento persistente: los estados de eliminación y lectura sobreviven a un reinicio del proceso incluso si la llamada de red aún no ha sido confirmada.
- Una clase base
PushwooshInboxCellabierta para diseños totalmente personalizados.
El contrato del servidor no ha cambiado — el mismo backend de bandeja de entrada de Pushwoosh, los payloads y las herramientas del panel de control funcionan como antes.
Elija su método de integración
Anchor link to- Configurar InboxKit con Swift Package Manager — recomendado para nuevos proyectos.
- Configurar InboxKit con CocoaPods — para proyectos que ya usan CocoaPods.
Tipos de tarjetas
Anchor link toInboxKit elige un diseño de celda por mensaje. El resolutor predeterminado lee displayType del payload del push — póngalo dentro del objeto data, que el SDK entrega bajo actionParams. Cuando falta displayType, el resolutor recurre a una heurística: imagen + sin título → banner, imagen + título + cuerpo → con leyenda, de lo contrario clásica. Para forzar un diseño para todo el feed desde el código, establezca attributes.forceCellKind.
Cada diseño enriquecido se degrada con elegancia: si un campo obligatorio está ausente o mal formado, la tarjeta recurre a classic en lugar de renderizar un marcador de posición vacío (y se registra un WARN con el motivo). classic es el recurso final y renderiza lo que el mensaje contenga; se espera que el editor de mensajes complete su título, cuerpo e icono.
displayType | Diseño | Campo de payload requerido | Se degrada a |
|---|---|---|---|
banner | Imagen a sangre completa, sin texto | imagen (inbox_image o data.image) | classic cuando no hay imagen |
captioned | Imagen en la parte superior, título + cuerpo debajo | imagen (inbox_image o data.image), title y content del mensaje | classic cuando falta la imagen, el título o el cuerpo |
classic | Avatar inicial coloreado + título + cuerpo | — (se esperan título, cuerpo e icono) | — |
carousel | Galería de múltiples imágenes deslizable | title y content del mensaje, data.carousel (1–5 diapositivas) | classic cuando no hay diapositivas o no hay título/cuerpo |
video | Póster con insignia de reproducción, reproductor a pantalla completa al tocar | data.video (url + poster opcional) | classic cuando no hay descriptor |
wallet | Botón “Añadir a Apple Wallet” (solo iOS) | data.wallet (URL de .pkpass) | classic cuando no hay URL de pase |






Las tarjetas de banner, con leyenda y clásicas se basan en los campos de mensaje estándar (imagen, título, cuerpo) más el array opcional buttons — consulte Añadir botones CTA en línea. Las tarjetas de carrusel, video y Apple Wallet llevan datos estructurados adicionales dentro de data, documentados a continuación.
Tarjeta de carrusel
Anchor link toUn carrusel renderiza varias imágenes de un solo mensaje — una galería deslizable con leyendas opcionales por diapositiva y destinos al tocar. Las diapositivas se encuentran en data.carousel. Cada diapositiva necesita una image; title (superposición de leyenda) y url (enlace profundo que se abre al tocar) son opcionales. Una diapositiva sin imagen se descarta; un toque en una diapositiva sin url recurre a la acción de fila predeterminada del mensaje. Se muestran como máximo 5 diapositivas — las diapositivas adicionales se descartan (una diapositiva sin imagen no ocupa un lugar). El title y el content del mensaje son obligatorios para este diseño; sin ellos, la tarjeta se degrada a classic.
{ "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] }] }}Tarjeta de video
Anchor link toUna tarjeta de video muestra una imagen de póster con una insignia de reproducción; al tocarla se abre un reproductor a pantalla completa (con sonido, incluso con el interruptor de silencio activado). El descriptor se encuentra en data.video: url es obligatorio y debe ser una transmisión o archivo http/https; poster es una imagen de vista previa opcional.
{ "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] }] }}Tarjeta de Apple Wallet
Anchor link toLa tarjeta de Apple Wallet muestra una imagen de héroe, un título y un cuerpo opcionales sobre el botón oficial Añadir a Apple Wallet. Al tocar el botón se descarga el .pkpass y se presenta la hoja del sistema para añadir pases. Úselo para entregar cupones, tarjetas de fidelidad, entradas o tarjetas de embarque directamente desde la bandeja de entrada. La tarjeta es solo para iOS / Mac Catalyst — en otras plataformas, el mensaje se renderiza como una tarjeta clásica.
La URL del pase se encuentra en data.wallet, ya sea como una cadena simple o como un objeto con un campo pass. Un data.image opcional añade la imagen de héroe. El botón se oculta automáticamente cuando no hay URL de pase o el dispositivo no puede añadir pases.
{ "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] }] }}El resultado se informa a su delegado:
extension MyInboxHost: PushwooshInboxKitDelegate {
func inboxKit(_ vc: PushwooshInboxKitViewController, didAddWalletPassFor message: PWInboxMessageProtocol) { // El pase está ahora en la Wallet del usuario — muestre una confirmación si lo desea. }
func inboxKit(_ vc: PushwooshInboxKitViewController, didFailToAddWalletPassFor message: PWInboxMessageProtocol, error: Error?) { // La descarga falló — muestre un reintento, registre, etc. }}Ambas devoluciones de llamada son opcionales (llevan implementaciones vacías predeterminadas). Que un usuario cancele la hoja del sistema no es ni un éxito ni un fracaso, por lo que no se activa ninguna devolución de llamada en ese caso.
Accesibilidad
Anchor link toLas celdas de InboxKit están listas para VoiceOver desde el primer momento. Las tarjetas de banner, con leyenda y clásicas exponen su título, cuerpo y fecha a través de las etiquetas subyacentes, y los botones CTA en línea leen sus propios títulos. Las tarjetas enriquecidas añaden semántica explícita:
- Video — el póster se expone como un único elemento de botón etiquetado como “Reproducir video” (rasgos
.button+.startsMediaSession), por lo que VoiceOver lo anuncia como un control multimedia en lugar de una imagen simple. - Carrusel — cada diapositiva es un elemento de botón cuya etiqueta de accesibilidad es la leyenda de la diapositiva, o “Diapositiva” cuando no tiene ninguna. El indicador de página anuncia la posición actual como “n de total”.
- Apple Wallet — el botón Añadir a Apple Wallet es el
PKAddPassButtonestándar de Apple, que lleva su propia etiqueta de VoiceOver localizada.
Para las pruebas de interfaz de usuario y la automatización, se establecen dos accessibilityIdentifier estables: inboxkit.video.play en el póster del video y inboxkit.wallet.add en el botón de Wallet.
Leer datos personalizados de un mensaje
Anchor link toPara que una notificación push aparezca en la bandeja de entrada, la solicitud createMessage de la API de Mensajes debe incluir inbox_image, inbox_date o inbox_days — sin uno de esos campos, el push se entrega como una notificación regular y nunca llega al feed de la bandeja de entrada. Los datos personalizados de formato libre van bajo la clave data, que el SDK entrega al cliente como el parámetro u:
{ "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] }] }}El SDK expone ese objeto en el mensaje de la bandeja de entrada a través de actionParams. Léalo desde el delegado cuando el usuario toque la fila o un CTA en línea:
extension MyInboxHost: PushwooshInboxKitDelegate {
func inboxKit(_ vc: PushwooshInboxKitViewController, didSelect message: PWInboxMessageProtocol) -> Bool { guard let params = message.actionParams as? [String: Any] else { return true }
// El objeto `data` personalizado llega bajo la clave "u" — // ya sea como un diccionario anidado o como una cadena codificada en JSON, // dependiendo de cómo se construyó el payload en el origen. 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 // hemos manejado el toque; el SDK no debe ejecutar la acción predeterminada } return true }}La misma búsqueda actionParams["u"] funciona dentro de inboxKit(_:didTapButton:onMessage:) para los botones CTA en línea. Para los casos de CTA tipados (openURL, dismiss, markRead), el SDK ya realiza la acción predeterminada — devuelva true para mantener ese comportamiento, o false para suprimirlo y ejecutar el suyo propio.
Añadir botones CTA en línea
Anchor link toUn mensaje puede llevar hasta tres botones de llamada a la acción en línea. Los botones se encuentran junto a otros datos personalizados dentro de data como un array buttons. El SDK los renderiza automáticamente dentro de las celdas con leyenda y clásicas:
{ "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ón tiene estos campos:
| Campo | Tipo | Cuándo |
|---|---|---|
title | string | Requerido. Etiqueta visible del botón. |
url | string | Una URL analizable no vacía produce una acción openURL. El SDK la abre a través de UIApplication.shared.open a menos que su delegado la suprima. |
action | string | Token de acción explícito: dismiss (elimina el mensaje del feed), markRead (marca el mensaje como leído) o custom (manejado por el host). No distingue entre mayúsculas y minúsculas. |
| Cualquier otra cosa | any | Cuando action es custom, cada clave en el objeto del botón, excepto title y action, se reenvía a su delegado como el payload personalizado — acuerde una clave con el comercializador (p. ej., tag) y despache en función de ella. |
Prioridad de resolución: primero el token de action explícito, luego url si no está vacío; de lo contrario, el botón cae en custom llevando el payload completo (menos title y action).
Intercepte los toques desde su delegado. La propiedad button.action es la enumeración tipada PushwooshInboxButtonAction:
extension MyInboxHost: PushwooshInboxKitDelegate {
func inboxKit(_ vc: PushwooshInboxKitViewController, didTapButton button: PushwooshInboxButton, onMessage message: PWInboxMessageProtocol) -> Bool { switch button.action { case .openURL(let url): // El comportamiento predeterminado está bien — deje que el SDK abra la URL. return true
case .dismiss, .markRead: // El SDK maneja ambos. Devuelva false si desea anularlo. return true
case .custom(let payload): // Botón personalizado definido por el comercializador. Despache en una clave que haya acordado. if let tag = payload["tag"] as? String { switch tag { case "save_promo": saveCurrentPromoLocally(message: message) default: break } } return true // ignorado para custom — el SDK nunca ejecuta una acción predeterminada aquí } }}