Skip to main content

Standalone Prebid Integration

This article shows you how to deliver Teads ads on your application using a standalone Prebid integration where you don't use the official Prebid SDK but you do have your own integration with a Prebid Server.

This integration requires you to integrate the Teads Adapter on server side and the Teads SDK on mobile side as well.

Teads SDK is still relevant in this sort of integration since the Teads Prebid Adapter will serve non-standard demand which requires a dedicated player.

Experimental

Experimental API.


Sample App

The official Teads SDK sample application includes working Prebid integrations. Use it for implementation examples and as a reference while you set up this integration.

Teads Android Sample App on GitHub

Prerequisites​

Installation​

Gradle​

project/build.gradle

allprojects {
repositories {
...
maven { url "https://teads.jfrog.io/artifactory/SDKAndroid-maven-prod" }
}
}

app/build.gradle

dependencies {
...

// Teads inApp SDK
implementation("tv.teads.sdk.android:sdk:6.2.3@aar") {
transitive = true
}
}

Insert the Teads parameters in the bid request​

Teads needs additional parameters in the bid request in order to process the bidding on its adapter. Below you can see the part of the bid request JSON that concerns these additional parameters while other parts are omitted.

{
"imp":*,
"ext": {
"prebid": {
"sdk": {
"renderers": [
{
"name": "teads",
"version": "6.2.0",
"data": {
"extra1": true,
"extra2": "189"
}
}
]
}
}
}
}

Notice that such values are not static (the version and data fields are dynamically provided by the SDK at runtime) and you must retrieve them with the Teads SDK and embed the content in the node ext.prebid.sdk by yourself.

So in order to retrieve such values use the PrebidAdPlacement class as below. Do it at least once per app session.

import tv.teads.sdk.PrebidAdPlacement
import tv.teads.sdk.AdPlacementExtraKey
import tv.teads.sdk.AdPlacementSettings
import tv.teads.sdk.AdRequestSettings
import tv.teads.sdk.TeadsSDK

val placementSettings = AdPlacementSettings.Builder()
.enableDebug()
.build()

val requestSettings = AdRequestSettings.Builder()
.pageSlotUrl("http://your.url.com") // Ensure to inform your article url or domain url for brand safety matters
.addExtra(AdPlacementExtraKey.STANDALONE_PREBID_INTEGRATION, "1") // Add this extra to enable your standalone integration
.build()

val prebidAdPlacement = TeadsSDK.createPrebidPlacement(
context = this,
placementSettings = placementSettings
)

prebidAdPlacement.getPrebidRequestData(
adRequestSettings = requestSettings,
onComplete = { result ->
// result is a JSONObject with the renderers list, see a sample below
// e.g. {"renderers":[{"name":"teads","version":"6.2.0","data":{"extra2":"189","extra1":true}}]}
}
)
Kotlin-only

getPrebidRequestData has no clean Java-callable path (its callback is typed with kotlin.Result, which isn't usable from Java source) — this API is Kotlin-only; if your use case allows it, use loadAd(...) instead.

Teads bid response​

See below a simplified sample about what would be the bid response once Teads win the auction with the data that characterizes Teads as the winner of the auction:

{
"id": "f34bbf12-18c8-463d-80f1-1eba20e8f4bf",
"seatbid": [
{
"seat": "teads",
"bid": [
{
"id": "imp-video-300x250",
"impid": "f34bbf12-18c8-463d-80f1-1eba20e8f4bf",
"price": 3.91,
"nurl": "https://dummy.nurl.teads.tv",
"adm": "<html><body><p>Dummy creative content</p></body></html>",
"adid": "625187",
"adomain": ["teads.com"],
"cid": "1088501",
"crid": "625187",
"cat": ["IAB12"],
"ext": {
"prebid": {
"meta": {
"rendererName": "teads",
"rendererVersion": "6.2.0"
},
"targeting": {
"hb_pb": "3.91",
"hb_bidder": "teads"
}
}
},
"h": 250,
"w": 300
}
]
}
],
"cur": "USD"
}

Ad rendering & Ad listeners​

Once Teads win the auction, delegate the ad rendering to Teads SDK by passing to it the winning bid response and subscribe to the ad lifecycle as below.

See that an instance of AdRequestSettings is necessary with the key AdPlacementExtraKey.STANDALONE_PREBID_INTEGRATION with value "1" to enable this sort of integration.

import tv.teads.sdk.AdPlacementExtraKey
import tv.teads.sdk.AdPlacementSettings
import tv.teads.sdk.AdRequestSettings
import tv.teads.sdk.AdOpportunityTrackerView
import tv.teads.sdk.AdRatio
import tv.teads.sdk.InReadAdViewListener
import tv.teads.sdk.PrebidAdPlacement
import tv.teads.sdk.TeadsSDK
import tv.teads.sdk.renderer.InReadAdView

class PrebidCustomIntegrationActivity : AppCompatActivity() {

private var inReadAdView: InReadAdView? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val placementSettings = AdPlacementSettings.Builder()
.enableDebug()
.build()

val requestSettings = AdRequestSettings.Builder()
.pageSlotUrl("http://your.url.com") // Ensure to inform your article url or domain url for brand safety matters
.addExtra(AdPlacementExtraKey.STANDALONE_PREBID_INTEGRATION, "1") // Add this extra to enable your standalone integration
.build()

val prebidAdPlacement = TeadsSDK.createPrebidPlacement(
context = this,
placementSettings = placementSettings
)

// Load the ad with listener
prebidAdPlacement.loadAd(
adResponse = stringifiedWinningBidJSON, // insert here your winning bid JSON received from your prebid server
adRequestSettings = requestSettings,
inReadBaseListener = object : InReadAdViewListener {
override fun onAdReceived(ad: InReadAdView, adRatio: AdRatio) {
inReadAdView?.clean()
inReadAdView = ad
binding.containerAdView.addView(ad)
val layoutParams = binding.containerAdView.layoutParams
layoutParams.height = adRatio.calculateHeight(binding.containerAdView.measuredWidth)
binding.containerAdView.layoutParams = layoutParams
}

override fun adOpportunityTrackerView(trackerView: AdOpportunityTrackerView) {
binding.containerAdView.addView(trackerView)
}

override fun onAdRatioUpdate(adRatio: AdRatio) {
val layoutParams = binding.containerAdView.layoutParams
layoutParams.height = adRatio.calculateHeight(binding.containerAdView.measuredWidth)
binding.containerAdView.layoutParams = layoutParams
}

override fun onAdImpression() {}
override fun onAdClicked() {}
override fun onAdError(code: Int, description: String) {}
override fun onAdClosed() {}
override fun onAdExpandedToFullscreen() {}
override fun onAdCollapsedFromFullscreen() {}
override fun onFailToReceiveAd(failReason: String) {}
},
videoPlaybackListener = null // add a VideoPlaybackListener if you want to listen video events
)
}

override fun onDestroy() {
super.onDestroy()
inReadAdView?.clean()
}
}

Layout sample.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<FrameLayout
android:id="@+id/containerAdView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

<tv.teads.sdk.renderer.InReadAdView
android:id="@+id/inReadAdView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

</FrameLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

Ad Resizing​

This part is a must and not implementing it will drastically affect the fill rate from Teads demand.

Dynamic height

Teads ads can adopt flexible dimensions. Your app must dynamically resize the ad container when the creative requests a new ratio. AdRatio.calculateHeight(width) computes the correct height.

No action is required if the ad view height is set to wrap_content. Otherwise, implement the ratio update callback to resize programmatically.

As shown before, see the sample below where the containerAdView is the view group that encapsulates your InReadAdView

import tv.teads.sdk.InReadAdViewListener

val listener = object : InReadAdViewListener {
...

// Resize the ad container view
override fun onAdRatioUpdate(adRatio: AdRatio) {
val layoutParams = binding.containerAdView.layoutParams
layoutParams.height = adRatio.calculateHeight(binding.containerAdView.measuredWidth)
binding.containerAdView.layoutParams = layoutParams
}

...
}

Ad Formats​

Currently this integration supports Media (formerly inRead) only.

Image and video

Media can serve image and video.

Settings​

Find the full settings list in Settings Configuration — TeadsMediationSettings.

Prebid Server setup​

Notice that in order to turn your Standalone integration fully functional and leverage from Teads demand you need to wire the Teads Adapter to your Prebid Server, please find more here.

The following configuration for each of your ad slots name is required:

{
"name": "imp-300x250-banner"
}

A placement id provided by your publisher manager is required as the sample below:

{
"ext": {
"teads": {
"placementId": 204344
}
}
}

Checklist​