Fetch and Display Content Cards

This tutorial explains how to fetch and display content cards in your application.

Pre-requisites

Integrate and register AEPMessaging extension in your app.

Fetch Content Cards

To fetch the content cards for the surfaces configured in Adobe Journey Optimizer campaigns, call the updatePropositionsForSurfaces API. You should batch requests for multiple surfaces in a single API call when possible. The returned content cards are cached in-memory by the Messaging extension and persist through the application's lifecycle.

data-slots=heading, code
data-repeat=1
data-languages=Kotlin

Kotlin

val surfaces = mutableListOf<Surface>()
val surface = Surface("homepage")
Messaging.updatePropositionsForSurfaces(surfaces)

Retrieve Content Cards

To retrieve the content cards for a specific surface, call getContentCardUIFlow. This API returns a flow of Result containing AepUI objects representing content cards for which the user is qualified.

AepUI objects are created only for content cards with templates recognized by the Messaging extension. The flow of AepUI objects may contain multiple content card template types: SmallImageUI, LargeImageUI, and ImageOnlyUI.

data-slots=heading, code
data-repeat=1
data-languages=Kotlin

Kotlin

// create a view model or reuse existing one to hold the aepUIList
class AepContentCardViewModel(private val contentCardUIProvider: ContentCardUIProvider) : ViewModel() {
    // State to hold AepUI list
    private val _aepUIList = MutableStateFlow<List<AepUI<*, *>>>(emptyList())
    val aepUIList: StateFlow<List<AepUI<*, *>>> = _aepUIList.asStateFlow()

    // Obtain the flow outside of a coroutine — no suspend needed
    val contentCardFlow = contentCardUIProvider.getContentCardUIFlow()

    init {
        // Collect the flow; content is fetched lazily on first collection
        viewModelScope.launch {
            contentCardFlow.collect { result ->
                result.onSuccess {
                  aepUi -> _aepUIList.value = aepUi
                }
                result.onFailure { throwable ->
                // handle onFailure if needed
                }
            }
        }
    }

    // Function to refresh the aepUIList from the ContentCardUIProvider
    fun refreshContent() {
        viewModelScope.launch {
            contentCardUIProvider.refreshContent()
        }
    }
}
data-variant=info
data-slots=text
Only content cards for which the user has qualified are returned by the getContentCardUIFlow API. Client-side rules are defined in the Adobe Journey Optimizer campaign.

Display Content Cards

The Content Card user interface is implemented using Jetpack Compose, which is the recommended toolkit for Android development. To display content cards in your app, pass the AepUI objects returned by the getContentCardUIFlow API to the appropriate Content Card composable. The currently supported composables are:

  1. SmallImageCard composable for SmallImageUI
  2. LargeImageCard composable for LargeImageUI
  3. ImageOnlyCard composable for ImageOnlyUI

Display Content Cards in Compose UI application

Below is an example of how to display content cards in a Compose UI application:

data-slots=heading, code
data-repeat=1
data-languages=Kotlin

Kotlin

@Composable
private fun AepContentCardList(viewModel: AepContentCardViewModel) {
  val aepUiList by viewModel.aepUIList.collectAsStateWithLifecycle()
  val provider = viewModel.contentCardUIProvider

  LazyRow {
    items(aepUiList) { aepUI ->
      when (aepUI) {
        is SmallImageUI -> {
          val state = aepUI.getState()
          if (!state.dismissed) {
            SmallImageCard(
                ui = aepUI,
                style = SmallImageUIStyle.Builder().build(),
                observer = ContentCardEventObserver(contentCardCallback, provider)
            )
          }
        }
        is LargeImageUI -> {
          val state = aepUI.getState()
          if (!state.dismissed) {
            LargeImageCard(
                ui = aepUI,
                style = LargeImageUIStyle.Builder().build(),
                observer = ContentCardEventObserver(contentCardCallback, provider)
            )
          }
        }
        is ImageOnlyUI -> {
          val state = aepUI.getState()
          if (!state.dismissed) {
            ImageOnlyCard(
                ui = aepUI,
                style = ImageOnlyUIStyle.Builder().build(),
                observer = ContentCardEventObserver(contentCardCallback, provider)
            )
          }
        }
      }
    }
  }
}

Refer to this TestApp for a complete example of how to display, customize and listen to UI events from content cards in a Compose UI application.

Retrieve ContentCardSchemaData from the Messaging extension

You may retrieve the ContentCardSchemaData for a Content Card with the template ID using the ContentCardMapper:

data-slots=heading, code
data-repeat=1
data-languages=Kotlin

Kotlin

private fun AepContentCardList(viewModel: AepContentCardViewModel) {
  // Collect the state from ViewModel
  val aepUiList by viewModel.aepUIList.collectAsStateWithLifecycle()

  // Get the ContentCardSchemaData for the AepUI list if needed
  val contentCardSchemaDataList = aepUiList.map {
    when (it) {
      is SmallImageUI ->
        ContentCardMapper.Companion.instance.getContentCardSchemaData(it.getTemplate().id)
      else -> null
    }
  }
}