Migration Guide for Existing Teads SDK Users
Welcome to the Teads Unified SDK! If you're currently using Teads SDK v5.x.x, this guide will help you understand what's new and how to take advantage of the enhanced features while maintaining full backward compatibility.
Key Points
✅ No Breaking Changes - Your existing code continues to work without modifications
✅ New Placements Available - Access to Feed and Recommendations placements
✅ Enhanced Event System - More granular event tracking and monitoring
✅ Complete Backward Compatibility - All existing APIs remain fully functional
Compatibility Matrix
| Feature | Teads SDK v5.x.x | Unified SDK v6.0.0 | Notes | 
|---|---|---|---|
| Media Placement | ✅ | ✅ | Fully backward compatible | 
| inFeed Native Placement | ✅ | ✅ | Fully backward compatible | 
| User Consent Signals Management | ✅ | ✅ | Fully backward compatible | 
| Media | ❌ | ✅ | New placement type that encapsulates inRead | 
| Media Native | ❌ | ✅ | New placement type that encapsulates inFeed Native | 
| Feed | ❌ | ✅ | New placement | 
| Recommendations | ❌ | ✅ | New placement | 
| Unified Ad Lifecycle Events | ❌ | ✅ | New optional interface | 
What's New for You
1. Current Placements Updates
While your existing code still works, you now have access to new interfaces:
| Legacy Placement | New Unified Placement | Description | What is New | 
|---|---|---|---|
| Media | Media Placement | Premium video advertising that integrates with content | Ad resizing can now be handled under the hood. New ad lifecycle event interface. More straightforward way to request and load ads. | 
| InFeed Native | Media Native Placement | Native video advertising with custom layouts | New Ad Lifecycle event interface. More straightforward way to request and load ads. | 
Previous Approach (Still Works)
// Traditional Teads SDK approach - still fully supported
val inReadPlacement = TeadsSDK.createMediaPlacement(
    applicationContext, 
    84242, 
    placementSettings
)
inReadPlacement.requestAd(
    adRequestSettings, 
    inReadListenerCallback, 
    videoPlaybackListenerCallback
)
New Approach (Recommended)
// New unified interface - cleaner and more intuitive
val config = TeadsAdPlacementMediaConfig(
    pid = 84242,
    articleUrl = "https://yoursite.com/article".toUri()
)
val mediaPlacement = TeadsAdPlacementMedia(config, delegate = teadsAdPlacementEventsDelegateCallback)
val adView = mediaPlacement.loadAd()
Media Placement Sample
Media placements display premium video advertisements within your content.
import tv.teads.sdk.combinedsdk.adplacement.TeadsAdPlacementMedia
import tv.teads.sdk.combinedsdk.adplacement.config.TeadsAdPlacementMediaConfig
import tv.teads.sdk.combinedsdk.adplacement.interfaces.TeadsAdPlacementEventsDelegate
import tv.teads.sdk.combinedsdk.TeadsAdPlacementEventName
import android.net.Uri
class ContentActivity : AppCompatActivity(), TeadsAdPlacementEventsDelegate {
    private var mediaPlacement: TeadsAdPlacementMedia? = null
    private lateinit var binding: ActivityArticleBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityArticleBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        setupMediaPlacement()
    }
    private fun setupMediaPlacement() {
        // Create configuration
        val config = TeadsAdPlacementMediaConfig(
            pid = 84242,  // Your unique Placement ID
            articleUrl = Uri.parse("https://yoursite.com/article")
        )
        // Create placement with delegate
        mediaPlacement = TeadsAdPlacementMedia(
           this, // Context
           config, // Placement config
           this // Event delegate
        )
        // Load the ad
        val mediaAdView = mediaPlacement?.loadAd()
        
        // Add to your view hierarchy
       binding.myContainerAdView.addView(mediaAdView)
    }
   
    override fun onPlacementEvent(
       placement: TeadsAdPlacement<*, *>, 
       event: TeadsAdPlacementEventName, 
       data: Map<String, Any>?
    ) {
       // Listen the ad lifecycle events
    }
   override fun onDestroy() {
      super.onDestroy()
      teadsAdPlacementMedia?.clean()
   }
}
Important: When using Media Placement, it's mandatory to set your ad container to dynamic sizing instead of fixed dimensions.
This is because ad creatives served for Media Placement have not a fixed size. The VPAID standard allows them to have dynamic dimensions and aspect ratios, meaning they can change size and shape on the fly.
By using dynamic sizing, you ensure the ad container can automatically resize to perfectly fit the creative's content, preventing issues like cropping or blank spaces. This dynamic resizing is crucial for delivering a great user experience and accurately measuring ad performance throughout the entire ad lifecycle, not just at initialization.
XML Implementation: Use android:layout_height="wrap_content" for your ad container.
Compose Implementation: Use Modifier.wrapContentHeight() or Modifier.height(IntrinsicSize.Min) for your ad container.
Media Native Placement Sample
Media Native placements allow you to create custom layouts for video ads that match your app's design.
import tv.teads.sdk.combinedsdk.adplacement.TeadsAdPlacementMediaNative
import tv.teads.sdk.combinedsdk.adplacement.config.TeadsAdPlacementMediaNativeConfig
import tv.teads.sdk.combinedsdk.adplacement.interfaces.TeadsAdPlacementEventsDelegate
import tv.teads.sdk.combinedsdk.TeadsAdPlacementEventName
import tv.teads.sdk.renderer.NativeAdView
import android.net.Uri
class ContentActivity : AppCompatActivity(), TeadsAdPlacementEventsDelegate {
    private var nativePlacement: TeadsAdPlacementMediaNative? = null
    private var nativeAdView: NativeAdView? = null
    private lateinit var binding: ActivityNativeAdBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityNativeAdBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        setupNativeAd()
    }
    private fun setupNativeAd() {
        // Create custom native ad view
        nativeAdView = createCustomNativeAdView()
        // Create configuration
        val config = TeadsAdPlacementMediaNativeConfig(
            124859, // Your unique Placement ID
            Uri.parse("https://yoursite.com/article")
        )
        // Create placement
        nativePlacement = TeadsAdPlacementMediaNative(
           this, // Context 
           config, // Placement config
           this // Event delegate
        )
        // Load and bind the ad
        nativePlacement
            ?.loadAd()
            ?.let { binder ->
               // Bind the ad native object to your native ad view
               binder(binding.myContainerAdView.nativeAdView)
           }
    }
    override fun onPlacementEvent(
       placement: TeadsAdPlacement, 
       event: TeadsAdPlacementEventName, 
       data: Map<String, Any>?
    ) {
       // Listen the ad lifecycle events
    }
   override fun onDestroy() {
      super.onDestroy()
      nativePlacement?.clean()
   }
}
2. Unified Ad Lifecycle Event System
The new unified event system provides consistent event handling across all placement types:
class MyActivity : AppCompatActivity(), TeadsAdPlacementEventsDelegate {
    
    override fun onPlacementEvent(
        placement: TeadsAdPlacement<*, *>,
        event: TeadsAdPlacementEventName,
        data: Map<String, Any>?
    ) {
        // Listen the ad lifecycle
        Log.d("TeadsSDK", "Event: $event from $placement with data $data")
    }
}
Check the full Comprehensive Event Handling sample.
New Placements
1. Feed
Feed placements display content recommendation widgets, perfect for keeping users engaged with related content.
import tv.teads.sdk.combinedsdk.adplacement.TeadsAdPlacementFeed
import tv.teads.sdk.combinedsdk.adplacement.config.TeadsAdPlacementFeedConfig
import tv.teads.sdk.combinedsdk.adplacement.interfaces.TeadsAdPlacementEventsDelegate
import tv.teads.sdk.combinedsdk.TeadsAdPlacementEventName
import android.net.Uri
class ContentActivity : AppCompatActivity(), TeadsAdPlacementEventsDelegate {
    private var feedPlacement: TeadsAdPlacementFeed? = null
    private lateinit var binding: ActivityContentBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityContentBinding.inflate(layoutInflater)
        setContentView(binding.root)
        setupFeedPlacement()
    }
    private fun setupFeedPlacement() {
        // Create configuration
        val config = TeadsAdPlacementFeedConfig(
            articleUrl = Uri.parse("https://yoursite.com/article"),
            widgetId = "MB_1", // Your unique Placement ID
            installationKey = "YOUR_INSTALLATION_KEY",
            widgetIndex = 0,
            userId = null,  // Optional user ID for personalization
            darkMode = false,
            testDisplay = false,
            extId = null,  // External ID
            extSecondaryId = null,  // External Secondary ID
            obPubImpl = null   // OB Publisher Implementation
        )
        // Create placement
        feedPlacement = TeadsAdPlacementFeed(
           this, // Context
           config, // Placement config
           this // Event delegate
        )
        // Load the feed
        val feedView = feedPlacement?.loadAd()
        // Add to your view hierarchy
        binding.myContainerAdView.addView(feedView)
    }
   override fun onConfigurationChanged(newConfig: Configuration) {
      super.onConfigurationChanged(newConfig)
      feedPlacement?.onActivityConfigurationChanged()
   }
    override fun onPlacementEvent(
       placement: TeadsAdPlacement<*, *>,
       event: TeadsAdPlacementEventName,
       data: Map<String, Any>?
    ) {
        // Listen the ad lifecycle events
        if (placement is TeadsAdPlacementFeed && event == TeadsAdPlacementEventName.CLICKED_ORGANIC) {
            val url = data?.get("url") as? String
            url?.let {
                // Programmatically open browser with the url 
            }
        }
    }
}
2. Recommendations
For programmatic access to content recommendations with custom UI:
import tv.teads.sdk.combinedsdk.adplacement.TeadsAdPlacementRecommendations
import tv.teads.sdk.combinedsdk.adplacement.config.TeadsAdPlacementRecommendationsConfig
import tv.teads.sdk.combinedsdk.adplacement.interfaces.TeadsAdPlacementEventsDelegate
import tv.teads.sdk.combinedsdk.TeadsAdPlacementEventName
import com.outbrain.OBSDK.Entities.OBRecommendation
import com.outbrain.OBSDK.Entities.OBRecommendationsResponse
import android.net.Uri
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.TextView
class ContentActivity : AppCompatActivity(), TeadsAdPlacementEventsDelegate {
   private var recommendationsPlacement: TeadsAdPlacementRecommendations? = null
   private lateinit var binding: ActivityRecommendationsBinding
   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      binding = ActivityRecommendationsBinding.inflate(layoutInflater)
      setContentView(binding.root)
      loadRecommendations()
   }
   private fun loadRecommendations() {
      // Create configuration
      val config = TeadsAdPlacementRecommendationsConfig(
         Uri.parse("https://yoursite.com/article"),
         "SDK_1" // Your unique Placement ID
      )
      // Create placement
      recommendationsPlacement = TeadsAdPlacementRecommendations(
         config, // Placement config
         this // Event delegate
      )
      // Fetch recommendations
      lifecycleScope.launch {
         try {
            val recommendations = recommendationsPlacement?.loadAdSuspend()
            recommendations?.let { displayRecommendations(it) }
         } catch (e: Exception) {
            Log.e("TeadsSDK", "Failed to load recommendations: ${e.message}")
         }
      }
   }
   private fun displayRecommendations(recommendations: OBRecommendationsResponse) {
      binding.recommendationsContainer.removeAllViews()
      if (recommendations.all.isNotEmpty()) {
         recommendations.all.forEach { recommendations ->
            val recommendationView = createRecommendationView(recommendations)
            binding.recommendationsContainer.addView(recommendationView)
         }
      }
   }
   private fun createRecommendationView(recommendation: OBRecommendation): View {
      val binding = RecommendationItemBinding.inflate(LayoutInflater.from(this))
      binding.recommendationTitle.text = recommendation.content
      binding.recommendationSource.text = recommendation.sourceName
      // Load image (using your preferred image loading library)
      recommendation.thumbnail?.url?.let { imageUrl ->
         // E.g. Glide.with(this).load(imageUrl).into(binding.recommendationImage)
      }
      // Handle click
      binding.root.setOnClickListener {
         TeadsAdPlacementRecommendations.getUrl(recommendation)?.let { url ->
            // Open URL in browser
         }
      }
      return binding.root
   }
   override fun onPlacementEvent(
      placement: TeadsAdPlacement<*, *>,
      event: TeadsAdPlacementEventName,
      data: Map<String, Any>?
   ) {
      // Listen the ad lifecycle events
   }
}
Common Questions
Q: Do I need to update my existing code?
A: No. Your existing code continues to work without any changes. Migration is optional.
Q: Can I use both old and new APIs in the same app?
A: Yes. Both APIs can coexist in the same application without issues.
Q: Will the old APIs be deprecated?
A: No immediate plans. The traditional APIs remain fully supported.
Q: Is there a performance benefit to migrating?
A: Minor improvements. The new APIs have some optimizations but the difference is minimal.
Q: Can I access Feed and Recommendations placements with the old API?
A: No. It is required the new unified API.
Q: How do I handle privacy settings?
A: Check the guide Privacy & Compliance.
Migration Checklist
- Update to Teads SDK v6.x.x. For detailed installation instructions, see Installation.
- Test existing implementations to confirm they still work
- Identify opportunities to add Feed and Recommendations placements
- Plan gradual migration for existing placements
- Implement new unified event handling
- Add advanced privacy management (optional)
- Test thoroughly in development environment
- Monitor performance and events in production
Support
If you encounter any issues during migration:
- Check the Integration Guide for detailed examples
- Contact Support for assistance
Remember: Migration is optional. Your existing code continues to work, and you can adopt new features at your own pace.
Happy coding with the enhanced Teads Unified SDK!