Esta página fue traducida automáticamente y puede contener errores. Para informar de un error de traducción, usa el componente de comentarios situado bajo el sumario, a la derecha de la página.
Migrar de Content Cards a banners
Esta guía te ayuda en la migración de Content Cards a banners para casos de uso de mensajería tipo banner. Los banners son ideales para mensajes en línea, persistentes dentro de la aplicación y en la Web que aparecen en ubicaciones específicas de tu aplicación.
¿Por qué migrar a Banners?
- Si tu equipo de ingeniería está construyendo o manteniendo Content Cards personalizadas, migrar a Banners puede reducir esa inversión continua. Banners permite a los especialistas en marketing controlar la interfaz de usuario directamente, liberando a los desarrolladores para otro trabajo.
- Si estás lanzando nuevos mensajes en la página de inicio, flujos de incorporación o anuncios persistentes, comienza con Banners en lugar de construir sobre Content Cards. Puedes beneficiarte de la personalización en tiempo real, sin expiración de 30 días, sin límite de tamaño y priorización nativa desde el primer día.
- Si estás buscando soluciones alternativas al límite de expiración de 30 días, gestionando lógica compleja de reelegibilidad o frustrado por la personalización obsoleta, Banners resuelve estos problemas de forma nativa.
Banners ofrece varias ventajas sobre Content Cards para mensajería de tipo banner:
Producción acelerada
- Menor soporte de ingeniería continuo requerido: Los especialistas en marketing pueden crear mensajes personalizados usando un editor de arrastrar y soltar y HTML personalizado sin necesidad de asistencia del desarrollador para la personalización.
- Opciones de personalización flexibles: Diseña directamente en el editor, usa HTML o aprovecha modelos de datos existentes con propiedades personalizadas.
Mejor experiencia de usuario
- Actualizaciones de contenido dinámico: Banners actualiza la lógica Liquid y la elegibilidad en cada actualización, asegurando que los usuarios siempre vean el contenido más relevante.
- Soporte nativo de ubicación: Los mensajes aparecen en contextos específicos en lugar de una fuente, proporcionando mejor relevancia contextual.
- Priorización nativa: Control sobre el orden de visualización sin lógica personalizada, lo que facilita la gestión de la jerarquía de mensajes.
Persistencia
- Sin límite de expiración: Las Campaigns de Banners no tienen un límite de expiración de 30 días como Content Cards, lo que permite una verdadera persistencia de los mensajes.
Cuándo migrar
Considera migrar a Banners si estás usando Content Cards para:
- Héroes de página de inicio, promociones de páginas de producto, ofertas en el proceso de pago
- Anuncios persistentes de navegación o mensajes en la barra lateral
- Mensajes siempre activos que se ejecutan durante más de 30 días
- Mensajes en los que deseas personalización y elegibilidad en tiempo real
Cuándo seguir usando Content Cards
Sigue usando Content Cards si necesitas:
- Experiencias de fuente: Cualquier ejemplo que implique múltiples mensajes desplazables o un “buzón de entrada” basado en tarjetas.
- Características específicas: Mensajes que requieren códigos promocionales, ya que los banners no los admiten de forma nativa. Los banners admiten contenido conectado en acceso anticipado.
- Entrega desencadenada: Ejemplos que requieren estrictamente entrega activada por API o entrega basada en acciones. Aunque los banners no admiten la entrega activada por API ni la entrega basada en acciones, la evaluación de elegibilidad en tiempo real significa que los usuarios califican o dejan de calificar instantáneamente en función de la pertenencia a un segmento en cada actualización.
Guía de migración
Requisitos previos
Antes de migrar, asegúrate de que tu SDK de Braze cumple con los requisitos mínimos de versión:
Los descartes y la reelegibilidad requieren las siguientes versiones mínimas del SDK:
Suscribirse a actualizaciones
Enfoque de Content Cards
1
2
3
4
5
6
7
8
| import * as braze from "@braze/web-sdk";
braze.subscribeToContentCardsUpdates((cards) => {
// Handle array of cards
cards.forEach(card => {
console.log("Card:", card.id);
});
});
|
1
2
3
4
5
6
| Braze.getInstance(context).subscribeToContentCardsUpdates { cards ->
// Handle array of cards
cards.forEach { card ->
Log.d(TAG, "Card: ${card.id}")
}
}
|
1
2
3
4
5
6
| braze.contentCards.subscribeToUpdates { cards in
// Handle array of cards
for card in cards {
print("Card: \(card.id)")
}
}
|
1
2
3
4
5
6
7
| Braze.addListener(Braze.Events.CONTENT_CARDS_UPDATED, (update) => {
const cards = update.cards;
// Handle array of cards
cards.forEach(card => {
console.log("Card:", card.id);
});
});
|
1
2
3
4
5
6
| StreamSubscription contentCardsStreamSubscription = braze.subscribeToContentCards((List<BrazeContentCard> contentCards) {
// Handle array of cards
for (final card in contentCards) {
print("Card: ${card.id}");
}
});
|
Enfoque de banners
1
2
3
4
5
6
7
8
9
| import * as braze from "@braze/web-sdk";
braze.subscribeToBannersUpdates((banners) => {
// Get banner for specific placement
const banner = braze.getBanner("sample_placement_id");
if (banner) {
console.log("Banner received for placement:", banner.placementId);
}
});
|
1
2
3
4
5
6
7
| Braze.getInstance(context).subscribeToBannersUpdates { update ->
// Get banner for specific placement
val banner = Braze.getInstance(context).getBanner("sample_placement_id")
if (banner != null) {
Log.d(TAG, "Banner received for placement: ${banner.placementId}")
}
}
|
1
2
3
4
5
6
7
8
| braze.banners.subscribeToUpdates { banners in
// Get banner for specific placement
braze.banners.getBanner(for: "sample_placement_id") { banner in
guard let banner = banner else { return }
print("Banner received for placement: \(banner.placementId)")
}
}
|
1
2
3
4
5
6
7
8
9
| Braze.addListener(Braze.Events.BANNER_CARDS_UPDATED, (data) => {
const banners = data.banners;
// Get banner for specific placement
Braze.getBanner("sample_placement_id").then(banner => {
if (banner) {
console.log("Banner received for placement:", banner.placementId);
}
});
});
|
1
2
3
4
5
6
7
8
| StreamSubscription bannerStreamSubscription = braze.subscribeToBanners((List<BrazeBanner> banners) {
// Get banner for specific placement
braze.getBanner("sample_placement_id").then((banner) {
if (banner != null) {
print("Banner received for placement: ${banner.placementId}");
}
});
});
|
Mostrar contenido

Nota
Las Content Cards se pueden renderizar manualmente con lógica de interfaz personalizada, mientras que los banners solo se pueden renderizar con los métodos del SDK incluidos de serie.
Enfoque de Content Cards
1
2
3
4
5
6
7
8
9
10
11
| // Show default feed UI
braze.showContentCards(document.getElementById("feed"));
// Or manually render cards
const cards = braze.getCachedContentCards();
cards.forEach(card => {
// Custom rendering logic
if (card instanceof braze.ClassicCard) {
// Render classic card
}
});
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| // Using default fragment
val fragment = ContentCardsFragment()
supportFragmentManager.beginTransaction()
.replace(R.id.content_cards_container, fragment)
.commit()
// Or manually render cards
val cards = Braze.getInstance(context).getCachedContentCards()
cards.forEach { card ->
when (card) {
is ClassicCard -> {
// Render classic card
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| // Using default view controller
let contentCardsController = BrazeContentCardUI.ViewController(braze: braze)
navigationController?.pushViewController(contentCardsController, animated: true)
// Or manually render cards
let cards = braze.contentCards.cards
for card in cards {
switch card {
case let card as Braze.ContentCard.Classic:
// Render classic card
default:
break
}
}
|
1
2
3
4
5
6
7
8
9
10
| // Launch default feed
Braze.launchContentCards();
// Or manually render cards
const cards = await Braze.getCachedContentCards();
cards.forEach(card => {
if (card.type === 'CLASSIC') {
// Render classic card
}
});
|
1
2
3
4
5
6
7
8
9
10
| // Launch default feed
braze.launchContentCards();
// Or manually render cards
final cards = await braze.getContentCards();
for (final card in cards) {
if (card.type == 'CLASSIC') {
// Render classic card
}
}
|
Enfoque de banners
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| braze.subscribeToBannersUpdates((banners) => {
const banner = braze.getBanner("sample_placement_id");
if (!banner) {
return;
}
const container = document.getElementById("global-banner-container");
braze.insertBanner(banner, container);
if (banner.isControl) {
container.style.display = "none";
}
});
braze.requestBannersRefresh(["sample_placement_id"]);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| // Using BannerView in XML
// <com.braze.ui.banners.BannerView
// android:id="@+id/banner_view"
// android:layout_width="match_parent"
// android:layout_height="wrap_content"
// app:placementId="sample_placement_id" />
// Or programmatically
val bannerView = BannerView(context).apply {
placementId = "sample_placement_id"
}
container.addView(bannerView)
Braze.getInstance(context).requestBannersRefresh(listOf("sample_placement_id"))
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| // Using BannerUIView
let bannerView = BrazeBannerUI.BannerUIView(
placementId: "sample_placement_id",
braze: braze,
processContentUpdates: { result in
switch result {
case .success(let updates):
if let height = updates.height {
// Update height constraint
}
case .failure:
break
}
}
)
view.addSubview(bannerView)
braze.banners.requestBannersRefresh(placementIds: ["sample_placement_id"])
|
1
2
3
4
5
6
7
8
9
10
11
12
| // Using BrazeBannerView component
<Braze.BrazeBannerView
placementId='sample_placement_id'
/>
// Or get banner data
const banner = await Braze.getBanner("sample_placement_id");
if (banner) {
// Render custom banner UI
}
Braze.requestBannersRefresh(["sample_placement_id"]);
|
1
2
3
4
5
6
7
8
9
10
11
12
| // Using BrazeBannerView widget
BrazeBannerView(
placementId: "sample_placement_id",
)
// Or get banner data
final banner = await braze.getBanner("sample_placement_id");
if (banner != null) {
// Render custom banner UI
}
braze.requestBannersRefresh(["sample_placement_id"]);
|
Registrar análisis (implementaciones personalizadas)

Nota
Tanto Content Cards como los banners rastrean análisis automáticamente cuando se utilizan sus componentes de interfaz predeterminados. Los siguientes ejemplos son para implementaciones personalizadas en las que construyes tu propia interfaz.
Enfoque de Content Cards
1
2
3
4
5
6
7
| // Manual impression logging required for custom implementations
cards.forEach(card => {
braze.logContentCardImpressions([card]);
});
// Manual click logging required for custom implementations
card.logClick();
|
1
2
3
4
5
6
7
| // Manual impression logging required for custom implementations
cards.forEach { card ->
card.logImpression()
}
// Manual click logging required for custom implementations
card.logClick()
|
1
2
3
4
5
6
7
| // Manual impression logging required for custom implementations
for card in cards {
card.context?.logImpression()
}
// Manual click logging required for custom implementations
card.context?.logClick()
|
1
2
3
4
5
6
7
| // Manual impression logging required for custom implementations
cards.forEach(card => {
Braze.logContentCardImpression(card.id);
});
// Manual click logging required for custom implementations
Braze.logContentCardClicked(card.id);
|
1
2
3
4
5
6
7
| // Manual impression logging required for custom implementations
for (final card in cards) {
braze.logContentCardImpression(card);
}
// Manual click logging required for custom implementations
braze.logContentCardClicked(card);
|
Enfoque de banners

Importante
Los análisis se rastrean automáticamente cuando se usa insertBanner(). No se debe usar el registro manual cuando se utiliza insertBanner().
1
2
3
4
5
6
7
8
9
| // Analytics are automatically tracked when using insertBanner()
// Manual logging should not be used when using insertBanner()
// For custom implementations, use manual logging methods:
// Log impression
braze.logBannerImpressions([banner]);
// Log click (with optional buttonId)
braze.logBannerClick("sample_placement_id", buttonId);
|

Importante
Los análisis se rastrean automáticamente cuando se usa BannerView. No se debe usar el registro manual cuando se utiliza BannerView.
1
2
3
4
5
6
7
8
9
| // Analytics are automatically tracked when using BannerView
// Manual logging should not be used for default BannerView
// For custom implementations, use manual logging methods:
// Log impression
Braze.getInstance(context).logBannerImpression("sample_placement_id");
// Log click (with optional buttonId)
Braze.getInstance(context).logBannerClick("sample_placement_id", buttonId);
|

Importante
Los análisis se rastrean automáticamente cuando se usa BannerUIView. No se debe usar el registro manual para el BannerUIView predeterminado.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| // Analytics are automatically tracked when using BannerUIView
// Manual logging should not be used for default BannerUIView
// For custom implementations, use manual logging methods:
// Get banner for specific placement
braze.banners.getBanner(for: "sample_placement_id") { banner in
guard let banner = banner else { return }
// Log impression
banner.context?.logImpression()
// Log click (with optional buttonId)
banner.context?.logClick(buttonId: buttonId)
}
// Control groups are automatically handled by BannerUIView
|

Importante
Los análisis se rastrean automáticamente cuando se usa BrazeBannerView. No se requiere registro manual.
1
2
3
4
5
| // Analytics are automatically tracked when using BrazeBannerView
// No manual logging required
// Note: Manual logging methods for Banners are not yet supported in React Native
// Control groups are automatically handled by BrazeBannerView
|

Importante
Los análisis se rastrean automáticamente cuando se usa BrazeBannerView. No se requiere registro manual.
1
2
3
4
5
| // Analytics are automatically tracked when using BrazeBannerView
// No manual logging required
// Note: Manual logging methods for Banners are not yet supported in Flutter
// Control groups are automatically handled by BrazeBannerView
|
Obtener propiedades
Enfoque de Content Cards
1
2
3
| cards.forEach(card => {
console.log("Card id:", card.id, "Extras:", card.extras);
});
|
1
2
3
| cards.forEach { card ->
Log.d(TAG, "Card id: ${card.id} Extras: ${card.extras}")
}
|
1
2
3
| for card in cards {
print("Card id: \(card.id) Extras: \(card.extras)")
}
|
1
2
3
| cards.forEach(card => {
console.log("Card id:", card.id, "Extras:", card.extras);
});
|
1
2
3
| for (final card in cards) {
print("Card id: ${card.id} Extras: ${card.extras}");
}
|
Enfoque de banners
1
2
3
4
5
6
| const banner = braze.getBanner("sample_placement_id");
if (!banner) {
return;
}
console.log("Banner placement:", banner.placementId, "Properties:", banner.properties);
|
1
2
3
4
| val banner = Braze.getInstance(context).getBanner("sample_placement_id")
if (banner != null) {
Log.d(TAG, "Banner placement: ${banner.placementId} Properties: ${banner.properties}")
}
|
1
2
3
4
5
| braze.banners.getBanner(for: "sample_placement_id") { banner in
guard let banner = banner else { return }
print("Banner placement: \(banner.placementId) Properties: \(banner.properties)")
}
|
1
2
3
4
| const banner = await Braze.getBanner("sample_placement_id");
if (banner) {
console.log("Banner placement:", banner.placementId, "Properties:", banner.properties);
}
|
1
2
3
4
| final banner = await braze.getBanner("sample_placement_id");
if (banner != null) {
print("Banner placement: ${banner.placementId} Properties: ${banner.properties}");
}
|
Gestión de grupos de control
Enfoque de Content Cards
1
2
3
4
5
6
7
| cards.forEach(card => {
if (card.isControl) {
// Logic for control cards ie. don't display but log analytics
} else {
// Logic for cards ie. render card
}
});
|
1
2
3
4
5
6
7
| cards.forEach { card ->
if (card.isControl) {
// Logic for control cards ie. don't display but log analytics
} else {
// Logic for cards ie. render card
}
}
|
1
2
3
4
5
6
7
| for card in cards {
if card.isControl {
// Logic for control cards ie. don't display but log analytics
} else {
// Logic for cards ie. render card
}
}
|
1
2
3
4
5
6
7
| cards.forEach(card => {
if (card.isControl) {
// Logic for control cards ie. don't display but log analytics
} else {
// Logic for cards ie. render card
}
});
|
1
2
3
4
5
6
7
| for (final card in cards) {
if (card.isControl) {
// Logic for control cards ie. don't display but log analytics
} else {
// Logic for cards ie. render card
}
}
|
Enfoque de banners
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| braze.subscribeToBannersUpdates((banners) => {
const banner = braze.getBanner("sample_placement_id");
if (!banner) {
return;
}
const container = document.getElementById("global-banner-container");
// Always call insertBanner to track impression (including control)
braze.insertBanner(banner, container);
// Hide if control group
if (banner.isControl) {
container.style.display = "none";
}
});
|
1
2
3
4
5
| // BannerView automatically handles control groups
// No additional code needed
val bannerView = BannerView(context).apply {
placementId = "sample_placement_id"
}
|
1
2
3
4
5
6
| // BannerUIView automatically handles control groups
// No additional code needed
let bannerView = BrazeBannerUI.BannerUIView(
placementId: "sample_placement_id",
braze: braze
)
|
1
2
3
4
5
| // BrazeBannerView automatically handles control groups
// No additional code needed
<Braze.BrazeBannerView
placementId='sample_placement_id'
/>
|
1
2
3
4
5
| // BrazeBannerView automatically handles control groups
// No additional code needed
BrazeBannerView(
placementId: "sample_placement_id",
)
|
Limitaciones
Al migrar de Content Cards a Banners, ten en cuenta las siguientes limitaciones:
Migración de mensajes desencadenados
Los Banners solo admiten Campaigns de entrega programada. Para migrar un mensaje que anteriormente se activaba mediante API o era basado en acciones, conviértelo a segmentación basada en Segment:
- Ejemplo: En lugar de desencadenar una tarjeta “Completar perfil” con la API, crea un Segment para usuarios que se registraron en los últimos 7 días pero no han completado su perfil.
- Elegibilidad en tiempo real: Los usuarios califican o dejan de calificar para el Banner instantáneamente en cada actualización según su pertenencia al Segment.
Diferencias de características
| Característica |
Content Cards |
Banners |
| Estructura de contenido |
|
|
| Múltiples tarjetas en la fuente |
✅ Compatible |
✅ Puedes crear múltiples ubicaciones para lograr una implementación tipo carrusel. Solo se devuelve un banner por ubicación. |
| Múltiples ubicaciones |
N/A |
✅ Múltiples ubicaciones compatibles |
| Tipos de tarjeta (Clásica, Con subtítulo, Solo imagen) |
✅ Múltiples tipos predefinidos |
✅ Un solo banner basado en HTML (más flexible) |
| Gestión de contenido |
|
|
| Editor de arrastrar y soltar |
❌ Requiere un desarrollador para la personalización |
✅ Los especialistas en marketing pueden crear/actualizar sin ingeniería |
| HTML/CSS personalizado |
❌ Limitado a la estructura de la tarjeta |
✅ Compatibilidad total con HTML/CSS |
| Pares clave-valor para personalización |
✅ Necesarios para personalización avanzada |
✅ Pares clave-valor fuertemente tipados llamados “propiedades” para personalización avanzada |
| Extras de mensaje |
✅ Compatible |
❌ No compatible actualmente |
| Persistencia y expiración |
|
|
| Expiración de tarjeta |
✅ Compatible (límite de 30 días) |
✅ Compatible (sin límite de expiración) |
| Persistencia real |
❌ Máximo de 30 días |
✅ Persistencia ilimitada |
| Visualización y segmentación |
|
|
| Interfaz de fuente |
✅ Fuente predeterminada disponible |
❌ Solo basado en ubicaciones |
| Ubicación contextual específica |
❌ Basado en fuente |
✅ Compatibilidad nativa con ubicaciones |
| Priorización |
❌ Requiere lógica personalizada |
✅ Priorización nativa |
| Interacción del usuario |
|
|
| Descarte manual |
✅ Compatible |
✅ Compatible |
| Reelegibilidad después del descarte |
❌ Requiere filtros personalizados o lógica de Campaign |
✅ Período de espera predeterminado |
| Tarjetas ancladas |
✅ Compatible |
N/A |
| Análisis |
|
|
| Análisis automáticos (interfaz predeterminada) |
✅ Compatible |
✅ Compatible |
| Ordenación por prioridad |
❌ No compatible |
✅ Compatible |
| Actualizaciones de contenido |
|
|
| Actualización de plantillas Liquid |
❌ Una vez por tarjeta al enviar/lanzar |
✅ Se actualiza en cada actualización |
| Actualización de elegibilidad |
❌ Una vez por tarjeta al enviar/lanzar |
✅ Se actualiza en cada sesión |
Limitaciones del producto
- Hasta 25 mensajes activos por ubicación.
- Hasta 10 ID de ubicación por solicitud de actualización; las solicitudes que superen este límite se truncan.
Limitaciones del SDK
- Los Banners no son compatibles actualmente con .NET MAUI (Xamarin), Cordova, Unity, Vega ni plataformas de TV.
- Asegúrate de que estás utilizando las versiones mínimas del SDK indicadas en los requisitos previos.
Artículos relacionados