First, create an instance of AdsProvider using the Builder. This object should be scoped to a single conversation and ideally tied to a lifecycle-aware component, like a ViewModel.
Copy
import so.kontext.ads.AdsProviderval adsProvider = AdsProvider.Builder( context = applicationContext, publisherToken = "", // Your unique publisher token from your account manager. userId = "user-uuid-123", // A unique string that should remain the same during the user’s lifetime. conversationId = "conversation-uuid-456", // Unique ID of the conversation, used for ad pacing. enabledPlacementCodes = listOf("inlineAd") // A list of placement codes that identify ad slots in your app.) .variantId("variant-id") // A string provided by the publisher to identify the user cohort in order to compare A/B test groups (optional) .advertisingId("advertising-id") // Device-specific identifier provided by the operating systems (GAID) .regulatory( // Regulatory compliance object Regulatory( gdpr = null, // Flag that indicates whether or not the request is subject to GDPR regulations (0 = No, 1 = Yes, null = Unknown). gdprConsent = "<gdpr-consent>", // Transparency and Consent Framework's Consent String data structure coppa = null, // Flag whether the request is subject to COPPA (0 = No, 1 = Yes, null = Unknown). gpp = "<gpp>", // Global Privacy Platform (GPP) consent string gppSid = listOf(1, 2), // List of the section(s) of the GPP string which should be applied for this transaction usPrivacy = "<us-privacy>" // Communicates signals regarding consumer privacy under US privacy regulation under CCPA and LSPA ) ) .character( // The character object used in this conversation Character( id = UUID.randomUUID().toString(), // Unique ID of the character name = "John Doe", // Name of the character avatarUrl = "", // URL of the character’s avatar isNsfw = false, // Whether the character is NSFW greeting = "Hello", // Greeting of the character persona = "", // Description of the character’s personality tags = listOf() // Tags of the character (list of strings) ) ) .build()
To provide context for ad targeting, your app’s chat messages must be represented in a way the SDK understands. You have two options:Option 1: Conform to MessageRepresentableYou can make your existing message data class conform to the MessageRepresentable interface. This involves overriding the required properties to map to your class’s fields.
Copy
import so.kontext.ads.MessageRepresentableimport so.kontext.ads.domain.Role// Your existing chat message classdata class MyChatMessage( val uniqueId: String, val text: String, val author: String, // "user" or "assistant" val creationDate: String // e.g., ISO 8601 format) : MessageRepresentable { // Map your properties to the interface requirements override val id: String get() = uniqueId override val role: Role get() = if (author == "user") Role.User else Role.Assistant override val content: String get() = text override val createdAt: String get() = creationDate}
Option 2: Use the AdsMessage Data ClassIf you cannot or prefer not to modify your existing data class, you can map your message objects to the AdsMessage type provided by the SDK. AdsMessage already conforms to MessageRepresentable.
Copy
import so.kontext.ads.AdsMessageimport so.kontext.ads.domain.Role// When you update the SDK, map your list of messagesval messagesForSdk = myChatMessages.map { myMessage -> AdsMessage( id = myMessage.uniqueId, role = if (myMessage.author == "user") Role.User else Role.Assistant, content = myMessage.text, createdAt = myMessage.creationDate )}// Then pass this new list to the provideradsProvider.setMessages(messagesForSdk)
Whenever your list of messages changes, pass the new list to the AdsProvider.The adsProvider.ads property is a kotlinx.coroutines.flow.Flow that emits a Map<String, List<AdConfig>>. The map’s key is the message ID, and the value is a list of ads to be displayed for that message.Collect this flow from a CoroutineScope to receive and display ads.
Once you collected the ads Map in your ViewModel, you can use it in your Composable UI to display the ads. The InlineAd composable is provided for this purpose. It takes an AdConfig object and handles the ad rendering.
For View support use InlineAdView.
Here is a simplified example of how to integrate the AdsProvider into an Android ViewModel. For a complete, working implementation, please see the example module in SDK repository.
Copy
import androidx.lifecycle.ViewModelimport androidx.lifecycle.viewModelScopeimport kotlinx.coroutines.flow.MutableStateFlowimport kotlinx.coroutines.flow.collectimport kotlinx.coroutines.launchimport so.kontext.ads.AdsProviderimport so.kontext.ads.MessageRepresentableclass ChatViewModel(application: Application) : ViewModel() { private val adsProvider: AdsProvider private val _messages = MutableStateFlow<List<MyChatMessage>>(emptyList()) init { adsProvider = AdsProvider.Builder( context = application, publisherToken = "nexus-dev", userId = "...", conversationId = "...", enabledPlacementCodes = listOf("inlineAd") ).build() // Collect the flow of ads viewModelScope.launch { adsProvider.ads.collect { result -> when (result) { is AdResult.Error -> { // handle error } is AdResult.Success -> { updateMessagesWithAds(result.ads) } } } } } fun onNewMessage(message: MyChatMessage) { // Update your local message list val updatedMessages = _messages.value + message _messages.value = updatedMessages // Pass the updated list to the SDK viewModelScope.launch { adsProvider.setMessages(updatedMessages) } } override fun onCleared() { // IMPORTANT: Clean up SDK resources adsProvider.close() super.onCleared() }}