You can use the Prebid SDK to monetize your app with a custom ad server or even without an ad server at all.
This guide outlines how to integrate the Prebid SDK into your app if you don’t fit into any of the other approaches documented on the site. Since there are many unknown details about your specific situation, guidance will remain general.
General components:
Custom integrations will need to determine whether they want to utilize Prebid SDK’s full rendering capacity, or just obtain bids to do their own rendering.
Here are the tradeoffs between two integration approaches:
Aspect | Bidding-Only Integration | Prebid-Rendered Integration |
---|---|---|
Direct access to bids | ![]() |
|
Support for MRAID 3.0 | ![]() |
|
Support for SKAdnetwork | ![]() |
|
Loads data from Prebid Cache | ![]() |
|
Supports instream video | ![]() |
|
Triggers billing and Notice URLs | ![]() |
|
Supports Third Party Rendering libraries | ![]() |
Notes:
The technical implementation of Prebid mobile into your app will involve these major steps:
If you’re using an ad server, the Ad Operations team will need to create line items. If you’re not using an ad server, the app code will need to generate an appropriate response to render the winning ad.
The creatives used depend on which media formats your adunits can utilize. The details for what creatives are needed for each ad format will depend on the type of integration:
The code implementation details depend on which rendering approach you’ve chosen:
While the default ad server for Prebid’s Mobile SDK is GAM, it can be expanded to include support for 3rd party ad servers through the fetchDemand function. This function returns the Prebid Server bidder key/values (targeting keys), which can then be passed to the ad server of choice.
In this mode, the developer is responsible for the following actions:
fetchDemand()
method with specific callbackBidInfo
callback parameterThis approach is available for the following ad formats:
BannerAdUnit
VideoAdUnit
(The class has been removed in the PrebidMobile 3.0.0
. Use the InStreamVideoAdUnit
instead)InterstitialAdUnit
VideoInterstitialAdUnit
(The class has been removed in the PrebidMobile 3.0.0
. Use the InterstitialAdUnit
with video ad format instead)RewardedVideoAdUnit
NativeRequest
PrebidAdUnit
The basic steps for these ad units you can find at the page for GAM Bidding Only integration. The diference is that you should use the fetchDemand
function with following signature:
public func fetchDemand(adObject: AnyObject, request: PrebidRequest,
completion: @escaping (BidInfo) -> Void)
Examples:
adUnit.fetchDemand(adObject: gamRequest, request: prebidRequest) { [weak self] bidInfo in
guard let self = self else { return }
//Publisher should provide support for converting keys into format of 3rd party ad server and loading ads
let keywords = convertDictToAdServerKeywords(dict: bidInfo.targetingKeywords)
AdServerLoadAds.loadAd(withAdUnitID: "46d2ebb3ccd340b38580b5d3581c6434", keywords: keywords)
}
The BidInfo
provides the following properties:
resultCode
- the object of type ResultCode
describing the status of the bid request.targetingKeywords
- the targeting keywords of the winning bidexp
- the number of seconds that may elapse between the auction and the actual impression. In this case, it indicates the approximate TTL of the bid in the Prebid Cache. Note that the actual expiration time of the bid will be less than this number due to the network and operational overhead. The Prebid SDK doesn’t make any adjustments to this value.nativeAdCacheId
- the local cache ID of the winning bid. Applied only to the native
ad format.events
- the map of some publically available event URLs attached to the bid. These can be used to enable Prebid Server-based analytics when the Prebid Universal Creative (PUC) is not involved in the rendering process. If the PUC is used for rendering, it will take care of hitting these events. These are the available event URLs:
seatbid.bid.ext.prebid.events.win
field. (requires SDK v2.1.6)seatbid.bid.ext.prebid.events.imp
field. (requires SDK v2.1.6)Code sample to extract the events:
let win = bidInfo.events[BidInfo.EVENT_WIN]
let imp = bidInfo.events[BidInfo.EVENT_IMP]
The Rendering API integration and usage are similar to any other ad SDK. In this case, Prebid SDK sends the bid requests to the Prebid Server and renders the winning bid.
Integration example:
// 1. Create an Ad View
let banner = BannerView(frame: CGRect(origin: .zero, size: adSize),
configID: CONFIG_ID,
adSize: adSize)
banner.delegate = self
// 2. Load an Ad
banner.loadAd()
Initialize the BannerAdView
with properties:
frame
- the frame rectangle for the viewconfigID
- an ID of the Stored Impression on the Prebid Serversize
- the size of the ad unit which will be used in the bid request.Call the method loadAd()
which will:
Banner Video is the same as HTML banner, but you also need to specify the ad format:
banner.adFormat = .video
Integration example:
// 1. Create an Interstitial Ad Unit
interstitial = InterstitialRenderingAdUnit(configID: CONFIG_ID,
minSizePercentage: CGSize(width: 30, height: 30))
interstitial.delegate = self
// 2. Load an Ad
interstitial.loadAd()
// .....
// 3. Show An Ad
if interstitial.isReady {
interstitial.show(from: self)
}
The default ad formats for interstitial are .banner and video. In order to make a banner-only or video-only request, set the respective values into the adFormats
property.
// Make bid request for video ad
adUnit?.adFormats = [.video]
// Make bid request for both video and banner ads (default behaviour)
adUnit?.adFormats = [.video, .banner]
// Make bid request for banner ad
adUnit?.adFormats = [.banner]
Initialize the Interstitial Ad Unit with properties:
configID
- an ID of Stored Impression on the Prebid ServerminSizePercentage
- specifies the minimum width and height percent an ad may occupy of a device’s real estate.NOTE: minSizePercentage - plays an important role in a bidding process for banner ads. If provided space is not enough demand partners won’t respond with the bids.
Call the method loadAd()
which will make a bid request to Prebid server.
Wait until the ad will be loaded and present it to the user in any suitable time.
// MARK: InterstitialRenderingAdUnitDelegate
func interstitialDidReceiveAd(_ interstitial: InterstitialRenderingAdUnit) {
// Now the ad is ready for display
}
The Rewarded Ad Unit assumes special behavior that should be configurable by the platform or publisher according to the application or ad experience guides.
Configuration of rewarded ad unit can be done by defining the Prebid Server passthrough extension or by using a stored impression-level request on the server.
Prebid SDK will search for a particular rwdd
object in $.seatbid.bid.ext.prebid.passthrough
of bid response to configure the behavior and rendering of the Rewarded Ad Unit. The following table describes the structure and usage purpose of rwdd
configuration parameters.
Attribute | Type | Description | Example |
---|---|---|---|
reward |
object (optional) |
Metadata provided by the publisher to describe the reward. | { |
reward.type |
string | Type of the reward in the app’s coins. | "SuperDollars" |
reward.count |
integer | Amount of coins. | 10 |
reward.ext |
object | For future extensions. | { |
completion |
object (optional) |
Describes the condition when the SDK should send a signal to the app that the user has earned the reward. | { |
completion.banner |
object | Details for banner ad completion. | { |
completion.banner.time |
integer | Period of time the banner ad is on screen. | 5 |
completion.banner.event |
string | URL with custom schema sent by the creative to indicate that the user did earn a reward. | "rwdd://userDidEarnReward" |
completion.video |
object | Details for video ad completion. | { |
completion.video.time |
integer | Period of time the video ad is on screen. | 10 |
completion.video.playbackevent |
string | The playback event stage in the video. |
"start" , "firstquartile" , "midpoint" , "thirdquartile" , "complete"
|
completion.video.endcard |
object | Properties for the end card. | { |
completion.video.endcard.time |
integer | Period of time the end card is on screen. | 5 |
completion.video.endcard.event |
string | URL with custom schema sent by the creative for end card. | "rwdd://userDidEarnReward" |
close |
object (optional) |
Describes the ad close behavior after the reward is earned. | { |
close.postrewardtime |
integer | Time interval (seconds) after reward event when SDK should close interstitial. | 3 |
close.action |
string | Action SDK should make: "autoclose" (close interstitial) or "closebutton" (show close button) |
"autoclose" |
An example of an impression-level stored request:
{
"video": {
"h": 480,
"w": 320,
"mimes": ["video/mp4"],
"linearity": 1,
"placement": 2,
"playbackmethod": [2]
},
"ext": {
"prebid": {
"passthrough": [
{
"type": "prebidmobilesdk",
"rwdd": {
"reward": {
"type": "SuperDollars",
"count": 10
},
"completion": {
"video": {
"endcard": {
"time": 5
}
}
},
"close": {
"postrewardtime": 3,
"action": "autoclose"
}
}
}
]
}
}
}
More details about the SDK behavior according to the rwdd
configuration you can find in the GitHub Proposal.
// 1. Create an Ad Unit
rewardedAd = RewardedAdUnit(configID: CONFIG_ID)
rewardedAd.delegate = self
// 2. Load an Ad
rewardedAd.loadAd()
/// .......
// 3. Display the Ad
if rewardedAd.isReady {
rewardedAd.show(from: self)
}
Create the RewardedAdUnit
object with the parameter:
configID
- an ID of Stored Impression on the Prebid ServerYou can also customize ad unit by setting additional properties:
adFormats
- the set of ad formats supported by the ad unit(the default value is [.banner, .video]
formats);bannerParameters
- the banner parameters used for configuring ad unit;videoParameters
- the video parameters used for configuring ad unit.Call the loadAd()
method which will make a bid request to Prebid server.
Wait until the ad is loaded and present it to the user at any suitable time.
// MARK: RewardedAdUnitDelegate
func rewardedAdDidReceiveAd(_ rewardedAd: RewardedAdUnit) {
// Now the ad is ready for display - call `show` method.
if rewardedAd.isReady {
rewardedAd.show(from: self)
}
}
Handle the reward in the appropriate method.
// MARK: RewardedAdUnitDelegate
func rewardedAdUserDidEarnReward(_ rewardedAd: RewardedAdUnit, reward: PrebidReward) {
let type = reward.type
let count = reward.count
let ext = reward.ext
// Process the reward
}
The adPosition
property allows developers to specify the position of the ad within the publisher’s content. This property maps to the pos
field in the OpenRTB specification under the imp[].banner
or imp[].video
objects, depending on the ad format. The possible values for this field could be found in the respective specification.
You can set adPosition
by using the following property:
adUnit.adPosition = .footer