Skip to main content

Standalone Prebid Integration

warning

Important: Experimental API


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.

Sample Teads App on GitHub Teads inApp SDK Sample App

Prerequisites

Installation

CocoaPods

If your project is managing dependencies through CocoaPods, you just need to add this pod to your Podfile.

It will install the Teads adapter along with the Teads inApp SDK.

  1. Add the following Pod in your Podfile:
pod 'TeadsSDK', '~> 6.0'
  1. Run the following console command to install it in your project.
$ pod install --repo-update

Swift Package Manager

Installing from Xcode

  1. Add a package by selecting FileAdd Packages… in Xcode's menu bar.
  2. Search for the Teads iOS SDK using the repo's URL:
https://github.com/teads/TeadsSDK-iOS
  1. Next, set the Dependency Rule to be Up to Next Major Version and keep 6.0.0 < 7.0.0.
  2. Choose the Teads product that you want to be installed in your app: TeadsSDK

Alternatively, add Teads to your Package.swift manifest

  1. Add it to the dependencies of your Package.swift:
dependencies: [
.package(url: "https://github.com/teads/TeadsSDK-iOS", .upToNextMajor(from: "6.0.0"))
]
  1. in any target that depends on a Teads product, add it to the dependencies array of that target:
.target(
name: "MyTargetName",
dependencies: [
.product(name: "TeadsSDK", package: "Teads"),
]
),

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.0.1",
"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 TeadsPrebidAdPlacement class as below. Do it at least once per app session.

import TeadsSDK

let placementSettings = TeadsAdPlacementSettings { settings in
settings.enableDebug() // remove in production
}

let placement = Teads.createPrebidPlacement(settings: placementSettings, delegate: self)

let requestSettings = TeadsAdRequestSettings { settings in
settings.addExtras("1", for: TeadsAdapterSettings.prebidStandaloneKey)
}

do {
let teadsBidRequestExtraData = try placement.getData(requestSettings: requestSettings)
// result is a dictionary with the renderers list, see a sample below
// e.g. {"renderers":[{"name":"teads","version":"6.0.1","data":{"extra2":"189","extra1":true}}]}
} catch {
// handle error
}

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.0.1"
},
"targeting": {
"hb_pb": "3.91",
"hb_bidder": "teads"
}
}
},
"h": 250,
"w": 300
}
]
}
],
"cur": "USD"
}

Ad rendering & Ad listeners

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

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

import TeadsSDK

class MyViewController : UIViewController, TeadsInReadAdPlacementDelegate {

@IBOutlet weak var inReadView: TeadsInReadAdView!
@IBOutlet weak var slotHeightConstraint: NSLayoutConstraint!

var placement: TeadsPrebidAdPlacement?

override func viewDidLoad() {
super.viewDidLoad()

let placementSettings = TeadsAdPlacementSettings { settings in
settings.enableDebug()
}

let requestSettings = TeadsAdRequestSettings { settings in
// Ensure to inform your article url or domain url for brand safety matters
settings.pageUrl("https://www.your.url.com")

// Add this extra to enable your standalone integration
settings.addExtras("1", for: TeadsAdapterSettings.prebidStandaloneKey)
}

placement = Teads.createPrebidPlacement(settings: placementSettings, delegate: self)

placement?.loadAd(adResponse: stringifiedWinningBidJSON, requestSettings: requestSettings)
}

func didReceiveAd(ad: TeadsInReadAd, adRatio: TeadsAdRatio) {
inReadView.bind(ad)
resizeTeadsAd(adRatio: adRatio)
}

func didUpdateRatio(ad: TeadsInReadAd, adRatio: TeadsAdRatio) {
resizeTeadsAd(adRatio: adRatio)
}

func didFailToReceiveAd(reason: AdFailReason) { }

func adOpportunityTrackerView(trackerView: TeadsAdOpportunityTrackerView) {
inReadView.addSubview(trackerView)
}

func resizeTeadsAd(adRatio: TeadsAdRatio) {
slotHeightConstraint.constant = adRatio.calculateHeight(for: inReadView.frame.width)
}
}

Ad Resizing

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

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

It is mandatory to programmatically adapt the size of the ad container via the ratio update delegate method.

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

import TeadsSDK

class MyViewController : UIViewController, TeadsInReadAdPlacementDelegate {

@IBOutlet weak var teadsAdView: TeadsInReadAdView!
@IBOutlet weak var slotHeightConstraint: NSLayoutConstraint! // set to 0 in InterfaceBuilder

func didReceiveAd(ad: TeadsInReadAd, adRatio: TeadsAdRatio) {
teadsAdView.bind(ad)
resizeTeadsAd(adRatio: adRatio)
}

func didUpdateRatio(ad: TeadsInReadAd, adRatio: TeadsAdRatio) {
resizeTeadsAd(adRatio: adRatio)
}

func resizeTeadsAd(adRatio: TeadsAdRatio) {
slotHeightConstraint.constant = adRatio.calculateHeight(for: teadsAdView.frame.width)
}
}

Ad Formats

Currently this integration supports Media (formerly InRead) only.

ℹ️ Notice that Media could serve image and video as well.

Settings

Find the full settings list here

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

  • ✅ Insert the Teads parameters in the bid request
  • ✅ Load your ad by informing the winning bid JSON
  • ✅ Subscribe to the event listeners
  • ✅ Implement ad view resizing
  • ✅ Setup your Prebid Server with the Teads Adapter
  • ✅ Ensure Brand Safety is enabled
  • ✅ Ensure you comply with privacy legal requirements (GDPR/CCPA/GPP)
  • ✅ Comply with app-ads.txt