Registrar análisis
Al crear una interfaz de usuario personalizada para Content Cards, debes registrar manualmente los análisis, como las impresiones, los clics y los descartes, ya que esto solo se gestiona automáticamente para los modelos de tarjetas predeterminados. El registro de estos eventos es una parte estándar de la integración de Content Cards y es esencial para la elaboración de informes precisos sobre las Campaigns y la facturación. Para ello, rellena tu interfaz de usuario personalizada con datos de los modelos de datos de Braze y, a continuación, registra manualmente los eventos. Una vez que entiendas cómo registrar los análisis, podrás ver las formas habituales en que los clientes de Braze crean Content Cards personalizadas.
Registro de análisis
Al implementar tus Content Cards personalizadas, puedes analizar los objetos de Content Card y extraer los datos de su carga útil, como title, cardDescription e imageUrl. Luego, puedes usar los datos del modelo resultante para completar tu interfaz de usuario personalizada.
Para obtener los modelos de datos de Content Card, suscríbete a las actualizaciones de Content Cards. Hay dos propiedades a las que debes prestar especial atención:
id: Representa la cadena de ID de la Content Card. Es el identificador único utilizado para registrar análisis de Content Cards personalizadas.extras: Incluye todos los pares clave-valor del panel de Braze.
Todas las propiedades fuera de id y extras son opcionales de analizar para las Content Cards personalizadas. Para más información sobre el modelo de datos, consulta el artículo de integración de cada plataforma: Android, iOS, Web.
Registra una función de devolución de llamada con subscribeToContentCardsEvents() para recibir las tarjetas almacenadas en caché y las actualizaciones cuando se actualicen las tarjetas.
import * as braze from "@braze/web-sdk";
// - Available in version 7.0.0+
braze.subscribeToContentCardsEvents((event) => {
switch (event.type) {
case braze.ChannelEventType.CACHE_REPLAY:
case braze.ChannelEventType.CACHE_LOAD:
case braze.ChannelEventType.DATA_UPDATED: {
const cards = event.cacheSnapshot.contentCards.cards;
// For example:
cards.forEach(card => {
if (card.isControl) {
// Do not display the control card, but remember to call `logContentCardImpressions([card])`
}
else if (card instanceof braze.ClassicCard || card instanceof braze.CaptionedImage) {
// Use `card.title`, `card.imageUrl`, etc.
}
else if (card instanceof braze.ImageOnly) {
// Use `card.imageUrl`, etc.
}
});
break;
}
case braze.ChannelEventType.ERROR:
// Check `event.reason` and `event.retryState`
break;
}
});
braze.subscribeToContentCardsUpdates((updates) => {
const cards = updates.cards;
// For example:
cards.forEach(card => {
if (card.isControl) {
// Do not display the control card, but remember to call `logContentCardImpressions([card])`
}
else if (card instanceof braze.ClassicCard || card instanceof braze.CaptionedImage) {
// Use `card.title`, `card.imageUrl`, etc.
}
else if (card instanceof braze.ImageOnly) {
// Use `card.imageUrl`, etc.
}
})
});
braze.openSession();
Usa subscribeToContentCardsEvents en Web SDK 7.0.0 y versiones posteriores. subscribeToContentCardsUpdates es el patrón anterior, obsoleto a partir de la versión 7.0.0.

Las Content Cards solo se actualizan al iniciar la sesión si se llama a una solicitud de suscripción antes de openSession(). También puedes actualizar manualmente la fuente.
Para la lista completa de eventos que puedes recibir, consulta Crear Content Cards.
Paso 1: Crea una variable de suscriptor privada
Para suscribirte a los eventos de tarjetas, primero declara una variable privada en tu clase personalizada para contener tu suscriptor:
// - Available in version 44.0.0+
private IEventSubscriber<ContentCardsEvent> mContentCardsEventSubscriber;
private IEventSubscriber<ContentCardsUpdatedEvent> mContentCardsUpdatedSubscriber;
Paso 2: Suscríbete a los eventos
A continuación, añade el siguiente código para suscribirte a los eventos de Content Card de Braze, normalmente dentro del Activity.onCreate() de la actividad de tus Content Cards personalizadas:
// - Available in version 44.0.0+
// Remove the previous subscriber before rebuilding a new one with our new activity.
Braze.getInstance(context).removeSingleSubscription(mContentCardsEventSubscriber, ContentCardsEvent.class);
mContentCardsEventSubscriber = new IEventSubscriber<ContentCardsEvent>() {
@Override
public void trigger(ContentCardsEvent event) {
if (event instanceof ContentCardsEvent.CacheReplay) {
handleCards(((ContentCardsEvent.CacheReplay) event).getCacheSnapshot());
} else if (event instanceof ContentCardsEvent.CacheLoad) {
handleCards(((ContentCardsEvent.CacheLoad) event).getCacheSnapshot());
} else if (event instanceof ContentCardsEvent.DataUpdated) {
handleCards(((ContentCardsEvent.DataUpdated) event).getCacheSnapshot());
}
}
};
Braze.getInstance(context).subscribeToContentCardsEvents(mContentCardsEventSubscriber);
Braze.getInstance(context).requestContentCardsRefresh();
// Remove the previous subscriber before rebuilding a new one with our new activity.
Braze.getInstance(context).removeSingleSubscription(mContentCardsUpdatedSubscriber, ContentCardsUpdatedEvent.class);
mContentCardsUpdatedSubscriber = new IEventSubscriber<ContentCardsUpdatedEvent>() {
@Override
public void trigger(ContentCardsUpdatedEvent event) {
List<Card> allCards = event.getAllCards();
}
};
Braze.getInstance(context).subscribeToContentCardsUpdates(mContentCardsUpdatedSubscriber);
Braze.getInstance(context).requestContentCardsRefresh();
private void handleCards(ContentCardsCacheSnapshot cacheSnapshot) {
List<Card> allCards = cacheSnapshot.getCards();
}
Paso 3: Cancela la suscripción
También recomendamos cancelar la suscripción cuando tu actividad personalizada salga de la vista. Añade el siguiente código al método de ciclo de vida onDestroy() de tu actividad:
// - Available in version 44.0.0+
Braze.getInstance(context).removeSingleSubscription(mContentCardsEventSubscriber, ContentCardsEvent.class);
Braze.getInstance(context).removeSingleSubscription(mContentCardsUpdatedSubscriber, ContentCardsUpdatedEvent.class);
Paso 1: Crea una variable de suscriptor privada
Para suscribirte a los eventos de tarjetas, primero declara una variable privada en tu clase personalizada para contener tu suscriptor:
// - Available in version 44.0.0+
private var contentCardsEventSubscriber: IEventSubscriber<ContentCardsEvent>? = null
private var contentCardsUpdatedSubscriber: IEventSubscriber<ContentCardsUpdatedEvent>? = null
Paso 2: Suscríbete a los eventos
A continuación, añade el siguiente código para suscribirte a los eventos de Content Card de Braze, normalmente dentro del Activity.onCreate() de la actividad de tus Content Cards personalizadas:
// - Available in version 44.0.0+
// Remove the previous subscriber before rebuilding a new one with our new activity.
Braze.getInstance(context).removeSingleSubscription(contentCardsEventSubscriber, ContentCardsEvent::class.java)
contentCardsEventSubscriber = IEventSubscriber { event ->
when (event) {
is ContentCardsEvent.CacheReplay -> handleCards(event.cacheSnapshot)
is ContentCardsEvent.CacheLoad -> handleCards(event.cacheSnapshot)
is ContentCardsEvent.DataUpdated -> handleCards(event.cacheSnapshot)
else -> {}
}
}
Braze.getInstance(context).subscribeToContentCardsEvents(contentCardsEventSubscriber)
Braze.getInstance(context).requestContentCardsRefresh()
// Remove the previous subscriber before rebuilding a new one with our new activity.
Braze.getInstance(context).removeSingleSubscription(contentCardsUpdatedSubscriber, ContentCardsUpdatedEvent::class.java)
contentCardsUpdatedSubscriber = IEventSubscriber { event ->
val allCards = event.allCards
}
Braze.getInstance(context).subscribeToContentCardsUpdates(contentCardsUpdatedSubscriber)
Braze.getInstance(context).requestContentCardsRefresh()
private fun handleCards(cacheSnapshot: ContentCardsCacheSnapshot) {
val allCards = cacheSnapshot.cards
}
Paso 3: Cancela la suscripción
También recomendamos cancelar la suscripción cuando tu actividad personalizada salga de la vista. Añade el siguiente código al método de ciclo de vida onDestroy() de tu actividad:
// - Available in version 44.0.0+
Braze.getInstance(context).removeSingleSubscription(contentCardsEventSubscriber, ContentCardsEvent::class.java)
Braze.getInstance(context).removeSingleSubscription(contentCardsUpdatedSubscriber, ContentCardsUpdatedEvent::class.java)
Para saber cuándo se activa cada evento y qué significa cada motivo de actualización, estado de reintento, acción de análisis y motivo de error, consulta Suscripciones a eventos.
Usa subscribeToContentCardsEvents en Android SDK 44.0.0 y versiones posteriores. subscribeToContentCardsUpdates es el patrón anterior, obsoleto a partir de la versión 44.0.0.
Para acceder al modelo de datos de Content Cards, llama a contentCards.cards en tu instancia de braze.
let cards: [Braze.ContentCard] = AppDelegate.braze?.contentCards.cards

Leer contentCards.cards, contentCards.unviewedCards o contentCards.lastUpdate bloquea el hilo de llamada hasta que el SDK haya completado sus operaciones posteriores a la inicialización. Usa los accesores no bloqueantes en Accesores de instantánea no bloqueantes para contextos del hilo principal o sensibles a la latencia.
Además, también puedes suscribirte a los eventos de Content Cards para observar cambios en la caché, análisis y errores. Puedes hacerlo de dos maneras:
- Manteniendo un cancelable; o
- Manteniendo un
AsyncStream.
Cancelable
// - Available in version 19.0.0+
// This subscription is maintained through a Braze cancellable, which will observe for events until the subscription is cancelled.
// You must keep a strong reference to the cancellable to keep the subscription active.
// The subscription is canceled either when the cancellable is deinitialized or when you call its `.cancel()` method.
let cancellable = AppDelegate.braze?.contentCards.subscribeToEvents { [weak self] event in
switch event {
case .cacheReplay(let cacheSnapshot):
// Initial cache snapshot, delivered immediately after subscribing
break
case .cacheLoad(let cacheSnapshot):
// Cache loaded at the start of a user session (for example, after `changeUser()`)
break
case .dataUpdated(let cacheSnapshot, let reason):
// Cache changed after the initial replay
break
case .impressionEvent(let card, let action):
break
case .clickEvent(let card, let action):
break
case .dismissEvent(let card, let action):
break
case .error(let reason, let retryState):
break
}
}
let cancellable = AppDelegate.braze?.contentCards.subscribeToUpdates { [weak self] contentCards in
// Implement your completion handler to respond to updates in `contentCards`.
}
AsyncStream
// - Available in version 19.0.0+
Task {
for await event in AppDelegate.braze?.contentCards.eventsStream ?? AsyncStream { _ in } {
// Same switch statement as the cancellable example above.
}
}
let stream: AsyncStream<[Braze.ContentCard]> = AppDelegate.braze?.contentCards.cardsStream
Usa subscribeToEvents(_:) o eventsStream en Swift SDK 19.0.0 y versiones posteriores. subscribeToUpdates(_:) y cardsStream son el patrón anterior, obsoleto a partir de la versión 19.0.0.
Para saber cuándo se activa cada evento y qué significa cada motivo de actualización, estado de reintento, acción de análisis y motivo de error, consulta Suscripciones a eventos.
Accesores de instantánea no bloqueantes
Usa estos métodos para leer el estado actual de la caché sin bloquear el hilo de llamada. Cada controlador de finalización siempre se entrega en el hilo principal.
// All cached cards.
AppDelegate.braze?.contentCards.getCachedContentCards { cards in
// Use `cards` here.
}
// Unviewed cards only (excludes control cards).
AppDelegate.braze?.contentCards.getUnviewedCards { cards in
// Use `cards` here.
}
// Date of the last server sync for the current user (nil until the first sync completes).
AppDelegate.braze?.contentCards.getLastUpdate { date in
// Use `date` here.
}
NSArray<BRZContentCardRaw *> *contentCards = AppDelegate.braze.contentCards.cards;
Además, si quieres suscribirte a los eventos de Content Cards, puedes llamar a subscribeToEvents:. Cada tipo de evento se mapea a su propia clase (por ejemplo, BRZContentCardsDataUpdatedEvent), que puedes discriminar con isKindOfClass:. La reproducción inicial de la caché y las actualizaciones de datos posteriores se mapean a BRZContentCardsDataUpdatedEvent; comprueba reason contra BRZContentCardsDataUpdatedEvent.cacheReplayReason para distinguirlos:
// - Available in version 19.0.0+
// This subscription is maintained through a Braze cancellable, which will continue to observe for events until the subscription is cancelled.
BRZCancellable *cancellable = [self.braze.contentCards subscribeToEvents:^(BRZContentCardsEvent *event) {
if ([event isKindOfClass:[BRZContentCardsDataUpdatedEvent class]]) {
BRZContentCardsDataUpdatedEvent *updated = (BRZContentCardsDataUpdatedEvent *)event;
if (updated.reason == BRZContentCardsDataUpdatedEvent.cacheReplayReason) {
// Initial cache snapshot, delivered immediately after subscribing
} else {
// Cache changed after the initial replay
}
} else if ([event isKindOfClass:[BRZContentCardsCacheLoadEvent class]]) {
// Cache loaded at the start of a user session (for example, after `changeUser()`)
}
}];
BRZCancellable *cancellable = [self.braze.contentCards subscribeToUpdates:^(NSArray<BRZContentCardRaw *> *contentCards) {
// Implement your completion handler to respond to updates in `contentCards`.
}];
Usa subscribeToEvents: en Swift SDK 19.0.0 y versiones posteriores. subscribeToUpdates: es el patrón anterior, obsoleto a partir de la versión 19.0.0.
Para leer el estado actual de la caché sin bloquear el hilo de llamada, usa los siguientes métodos. Cada controlador de finalización se entrega en el hilo principal.
// All cached cards.
[AppDelegate.braze.contentCards getCachedContentCardsWithCompletion:^(NSArray<BRZContentCardRaw *> *cards) {
// Use `cards` here.
}];
// Unviewed cards only (excludes control cards).
[AppDelegate.braze.contentCards getUnviewedCardsWithCompletion:^(NSArray<BRZContentCardRaw *> *cards) {
// Use `cards` here.
}];
// Date of the last server sync for the current user (nil until the first sync completes).
[AppDelegate.braze.contentCards getLastUpdateWithCompletion:^(NSDate * _Nullable date) {
// Use `date` here.
}];
Para escuchar actualizaciones, suscríbete a los eventos de actualización de Content Cards:
const subscription = Braze.addListener(Braze.Events.CONTENT_CARDS_UPDATED, (update) => {
const cards = update.cards;
cards.forEach(card => {
if (card.isControl) {
// Do not display the control card, but remember to log an impression
} else {
// Use card.title, card.cardDescription, card.image, etc.
}
});
});
Para obtener los datos más recientes de Content Cards almacenados en caché:
import Braze from "@braze/react-native-sdk";
const cachedCards = await Braze.getCachedContentCards();
Para solicitar una actualización manual de Content Cards desde los servidores de Braze:
Braze.requestContentCardsRefresh();
Registro de eventos
Registrar métricas valiosas como impresiones, clics y descartes es rápido y sencillo. Configura un listener de clics personalizado para gestionar manualmente estos análisis.
Registra eventos de impresión cuando los usuarios visualizan las tarjetas usando logContentCardImpressions:
import * as braze from "@braze/web-sdk";
braze.logContentCardImpressions([card1, card2, card3]);
Registra eventos de clic en tarjetas cuando los usuarios interactúan con una tarjeta usando logContentCardClick:
import * as braze from "@braze/web-sdk";
braze.logContentCardClick(card);
El BrazeManager puede hacer referencia a las dependencias del SDK de Braze, como la lista de arrays de objetos Content Cards, para obtener el Card y llamar a los métodos de registro de Braze. Usa la clase base ContentCardable para hacer referencia fácilmente y proporcionar datos al BrazeManager.
Para registrar una impresión o un clic en una tarjeta, llama a Card.logClick() o Card.logImpression() respectivamente.
Puedes registrar manualmente o marcar una Content Card como “descartada” en Braze para una tarjeta en particular con isDismissed. Si una tarjeta ya está marcada como descartada, no se puede marcar como descartada de nuevo.
Para crear un listener de clics personalizado, crea una clase que implemente IContentCardsActionListener y regístrala con BrazeContentCardsManager. Implementa el método onContentCardClicked(), que se invocará cuando el usuario haga clic en una Content Card. Luego, indica a Braze que use tu listener de clics de Content Cards.
Por ejemplo:
BrazeContentCardsManager.getInstance().setContentCardsActionListener(new IContentCardsActionListener() {
@Override
public boolean onContentCardClicked(Context context, Card card, IAction cardAction) {
return false;
}
@Override
public void onContentCardDismissed(Context context, Card card) {
}
});
Por ejemplo:
BrazeContentCardsManager.getInstance().contentCardsActionListener = object : IContentCardsActionListener {
override fun onContentCardClicked(context: Context, card: Card, cardAction: IAction): Boolean {
return false
}
override fun onContentCardDismissed(context: Context, card: Card) {
}
}

Para gestionar variantes de control de Content Cards en tu interfaz personalizada, pasa tu objeto com.braze.models.cards.Card y luego llama al método logImpression como lo harías con cualquier otro tipo de Content Card. El objeto registrará implícitamente una impresión de control para informar a nuestros análisis de cuándo un usuario habría visto la tarjeta de control.
Implementa el protocolo BrazeContentCardUIViewControllerDelegate y configura tu objeto delegado como la propiedad delegate de tu BrazeContentCardUI.ViewController. Este delegado se encargará de pasar los datos de tu objeto personalizado a Braze para que se registren. Para ver un ejemplo, consulta el tutorial de interfaz de Content Cards.
// Set the delegate when creating the Content Cards controller
contentCardsController.delegate = delegate
// Method to implement in delegate
func contentCard(
_ controller: BrazeContentCardUI.ViewController,
shouldProcess clickAction: Braze.ContentCard.ClickAction,
card: Braze.ContentCard
) -> Bool {
// Intercept the content card click action here.
return true
}
// Set the delegate when creating the Content Cards controller
contentCardsController.delegate = delegate;
// Method to implement in delegate
- (BOOL)contentCardController:(BRZContentCardUIViewController *)controller
shouldProcess:(NSURL *)url
card:(BRZContentCardRaw *)card {
// Intercept the content card click action here.
return YES;
}

Para gestionar variantes de control de Content Cards en tu interfaz personalizada, pasa tu objeto Braze.ContentCard.Control y luego llama al método logImpression como lo harías con cualquier otro tipo de Content Card. El objeto registrará implícitamente una impresión de control para informar a nuestros análisis de cuándo un usuario habría visto la tarjeta de control.
Registra eventos de impresión cuando los usuarios visualizan las tarjetas:
Braze.logContentCardImpression(card.id);
Registra eventos de clic en tarjetas cuando los usuarios interactúan con una tarjeta:
Braze.logContentCardClicked(card.id);
Registra eventos de descarte cuando un usuario descarta una tarjeta:
Braze.logContentCardDismissed(card.id);
Gestión del comportamiento al hacer clic
Cuando un usuario hace clic en una Content Card en una fuente personalizada, el comportamiento al hacer clic (como navegar a una URL, vinculación en profundidad o registrar un evento personalizado) no se gestiona automáticamente. Usa handleBrazeAction para procesar la URL de la tarjeta y ejecutar la acción al hacer clic configurada, incluidas las acciones de Braze (URLs brazeActions://).
import * as braze from "@braze/web-sdk";
// In your card click handler
function onCardClick(card) {
// Log the click
braze.logContentCardClick(card);
// Handle the on-click behavior
if (card.url) {
braze.handleBrazeAction(card.url);
}
}
| Parámetro | Descripción |
|---|---|
url |
Una URL válida, o una URL de acción de Braze válida con el esquema brazeActions://. |
openLinkInNewTab |
(Opcional) Si la URL debe abrirse en una nueva pestaña. El valor predeterminado es false. |

Si no llamas a handleBrazeAction(), los comportamientos al hacer clic configurados en el panel de Braze (como “Registrar evento personalizado” o “Navegar a URL”) no se ejecutarán para las tarjetas mostradas en una fuente personalizada.
El comportamiento al hacer clic se gestiona automáticamente mediante la interfaz de usuario predeterminada de Content Cards. Para implementaciones personalizadas, usa la interfaz IContentCardsActionListener descrita en Registro de análisis.
El comportamiento al hacer clic se gestiona automáticamente mediante la interfaz de usuario predeterminada de Content Cards. Para implementaciones personalizadas, usa el protocolo BrazeContentCardUIViewControllerDelegate descrito en Registro de análisis.
Cuando un usuario hace clic en una Content Card en una fuente personalizada, el comportamiento al hacer clic no se gestiona automáticamente. Después de registrar el clic con Braze.logContentCardClicked(cardId), llama a Braze.processContentCardClickAction(cardId) para procesar vínculos profundos, URLs y acciones brazeActions://. Para referencia de métodos, consulta Content Cards en React Native.
import Braze from "@braze/react-native-sdk";
function onCardPress(card) {
Braze.logContentCardClicked(card.id);
if (card.url) {
Braze.processContentCardClickAction(card.id);
}
}

Si no llamas a processContentCardClickAction(), los comportamientos al hacer clic configurados en el panel de Braze no se ejecutarán para las tarjetas en una fuente personalizada.
Descartes únicos superiores a impresiones únicas
Si los descartes únicos superan a las impresiones únicas, tu integración personalizada de Content Cards registró descartes sin registrar impresiones para esas mismas tarjetas. La interfaz predeterminada de Content Cards de Braze registra ambos automáticamente, por lo que esta discrepancia solo aparece cuando utilizas una interfaz personalizada.
Registra una impresión cada vez que muestres una tarjeta, y registra un descarte cuando el usuario la descarte. Para los nombres de los métodos y ejemplos, consulta las secciones de plataforma a continuación.
Análisis de Content Cards faltantes
Si las Content Cards aparecen correctamente en tu aplicación pero no recibes ningún análisis de forma consistente (impresiones, clics, etc.), es probable que se trate de un problema de integración de SDK.
- Vistas personalizadas de Content Cards (Android, iOS, Web): La interfaz predeterminada de Braze registra impresiones y clics automáticamente en todas las plataformas. Si estás utilizando una vista o implementación personalizada de Content Cards, debes llamar explícitamente a los métodos de registro apropiados dentro de tu aplicación. Consulta Registrar análisis para tu plataforma. Para implementaciones Web personalizadas específicamente, asegúrate de que el SDK Web de Braze esté cargado, revisa la consola del navegador en busca de errores y verifica que se estén recibiendo los datos de las tarjetas.
- Inicialización del SDK e identificación de usuarios: Asegúrate de que el SDK esté completamente inicializado antes de mostrar las tarjetas. Los eventos se descartan silenciosamente (no se ponen en cola) si el SDK no está inicializado, está en modo de inicialización diferida o tiene el RGPD desactivado. El SDK sí registra análisis para usuarios anónimos, pero las métricas del panel como “impresiones diarias únicas” requieren una identidad de usuario resuelta, así que llama a
changeUserantes de que se muestren las tarjetas siempre que sea posible.
ID de Content Card
Cada envío de una Campaign a un destinatario genera un nuevo ID de Content Card. Si el mismo usuario recibe la Campaign de nuevo en un envío posterior, Braze asigna un nuevo ID. Haz referencia al id de la tarjeta al registrar impresiones, clics y descartes en implementaciones personalizadas.