OpenWrap-InApp Developer Guide: Android InApp Header Bidding for DFP

Document created by catherine.racette on Aug 7, 2017Last modified by catherine.racette on Aug 24, 2017
Version 5Show Document
  • View in full screen mode

(Version 1.2.1)

Introduction

In-App Header Bidding allows publishers to allocate ad inventory using a technology and methodology that bypasses inefficiencies that have kept apps from finding the best prices.


Header bidding is the process of sending out an initial ad call to one or more buyers to solicit an exact price for inclusion in the ad server’s inventory allocation process.

 

At a high level this is a 3-step process:

  1. The prefetch/header bidding ad call needs to be initiated before requesting ad from Primary SDK.
  2. Buyers get first look at the inventory and submit a pre-bid price.
  3. This pre-bid price then becomes the bid floor for the ad server call, which checks if any other buyers in the same priority tier can beat it. As a result, inventory gets allocated to the highest yielding buyer while respecting other publisher controls that may have been set up in the ad server.

 

Header bidding primarily benefits publishers who use third party SDKs (e.g., DFP) to manage their ads. However, DFP doesn’t allow publishers to effectively pull in programmatic buyers that compete against AdX and direct deals, so publishers are limited as to which buyers they can utilize.

 

When a page in the publisher's app is loaded, the code reaches out to PubMatic for bids before the ad server’s direct sales are called. Bidding is essentially simultaneous instead of sequential, and focuses on all available impressions, not just ones available after direct sales.

 

The diagram below shows how PubMatic non-SDK header bidder integrates with publisher’s app.

If desired, publishers can also allow the winning bid to compete with prices available from the direct-sold ads.

This header bidding arrangement accomplishes several objectives:

  • All the demand sources are bidding at the same time, which replaces waterfall’s preferential ordering of buyers.
  • Advertisers have a chance at obtaining the best ad inventory.
  • Stats have shown publisher gains as high as 50 percent in CPMs.

Supported Ad Format

Simple Banner is supported

Prerequisite

Integration of DFP SDK
DFP banner ad view

 

In-App Code Integration

  1. Integrate the PubMatic Sample Code to Publisher App
  2. Adding Permissions to the Manifest file
  3. Creating a header bidding request
  4. Prefetching bids using PMPrefetchManager
  5. Handling Prefetched Bids from PMPrefetchManager
  6. Receiving DFP App Event Callback
  7. Rendering Prefetched creative
  8. Using HeaderBiddingBannerHelper (Optional)
  9. Setting Refresh interval (Optional)
  10. App debugging

Integrate the PubMatic Sample Code to Publisher App Code

Publisher can refer to the PubMatic's Sample application for faster & easier integration. Highlighted 'core' package need to be copied to Publisher's android application.

 

The following classes need to be imported for integration in the Header Bidding Request:

import com.pubmatic.headerbidding.core.PMAdSize;
import com.pubmatic.headerbidding.core.PMBannerImpression;
import com.pubmatic.headerbidding.core.PMBannerPrefetchRequest;
import com.pubmatic.headerbidding.core.PMBid;
import com.pubmatic.headerbidding.core.PMPrefetchManager;
import com.pubmatic.headerbidding.core.PubMaticBannerAdRequest;
import com.pubmatic.headerbidding.core.PubMaticConstants;

Adding Permissions to the Manifest File

Declare the following security permissions in your manifest file (AndroidManifest.xml).
Table 1. Basic Permissions for the Manifest File

PermissionDescription and Manifest file entry
InternetAccess the Internet. Required for ad-content download.
<uses-permission android:name="android.permission.INTERNET" />
Network StateAccess the Network state. Required for retrieving network details from ConnectivityManager
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

 

Creating a Header Bidding Request

  1. Create Impression objects that contain the information about specific ad slots like impressionId (Unique identifier), slot name, sizes and slot index. Separate object of
    PMBannerImpression class needs to be created for each ad slot.
    PMBannerImpression bannerImpression = new PMBannerImpression(<ImpressionId>, <SlotName>, <AdSizes>, <SlotIndex>);

    ImpressionId: It is used to identify unique ad slot/banner of mopub on screen, this should match with imp_id configured at step 2 in Ad Server Set-Up at Mopub section below

    SlotName: It is a string identifier. It should be the same slot name mapped to PubMatic ad tag. Please refer mapping in xls sheet in section PubMatic side set-up.

    SlotIndex: It is required when same slot name is used multiple times on the screen. If there are two slot name on the screen, testAd (Above the fold) and testAd (Below the fold), then slotindex can be used to differentiate between slots with same name.

    AdSizes: Different add sizes can be provided for requesting Ad with different sizes.

  2. Create a prefetch request object by specifying publisher id and impressions, from step 1, to prefetch bids. It is required to make an ad request to PubMatic against impression objects. 
    PMBannerPrefetchRequest adRequest = PMBannerPrefetchRequest.initHBRequestForImpression(<Context>, <pubId>,
    List<PMBannerImpression>);

     

  3. Specify targeting information on the prefetch request object such as store URL, app domain, gender, ethnicity and much more.
    Sample code for creating ad request & setting basic parameters:
    PMBannerPrefetchRequest adRequest = PMBannerPrefetchRequest.initHBRequestForImpression(mContext, <Publisher ID>, bannerImpressions);
    adRequest.setAWT(PubMaticBannerAdRequest.AWT_OPTION.WRAPPED_IN_JS);
    adRequest.addKeyword("entertainment");
    adRequest.addKeyword("sports");
    adRequest.setEthnicity(PubMaticBannerAdRequest.ETHNICITY.ASIAN_AMERICAN);
    adRequest.setDoNotTrack(false);
    adRequest.setApplicationPaid(false);
    // Designated market area (DMA) code of the user.
    // This field is applicable for US users only. For example, dma=734
    adRequest.setDMA("734");
    adRequest.setCoppa(true);
    adRequest.setOrmmaComplianceLevel(1);
    adRequest.setAppCategory("Game");
    adRequest.setIABCategory("IAB1-1,IAB1-7");

    For additional parameter details, please refer Table 2 mentioned in Parameter details section.

Prefetching Bids Using PMPrefetchManager

  1. Create an object of PMPrefetchListener:
    PMPrefetchManager.PMPrefetchListener listener = new PMPrefetchManager.PMPrefetchListener () {
                @Override
                public void onBidsFetched(Map<String, PMBid> hBResponse) {
                    Log.d(TAG, "onBidsFetched");

                    // Header bidding completed.
         // Now send the custom data to DFP.
                    requestDFPAd(hBResponse);
                }

                @Override
                public void onBidsFailed(String errorMessage) {
                    Log.d(TAG, "Header Bidding failed. " + errorMessage);

                    // Get on with requesting DFP for ads without HB data.
                    requestDFPAd(null);
                }
            };

     

  2. Create a Prefetch Manager object by specifying the context.
    PMPrefetchManager pmPrefetchManager = PMPrefetchManager.getInstance(<Context>);
    pmPrefetchManager.setPrefetchListener(listener);
  3. Set a network timeout using setNetworkTimeout(<timeout in seconds>) method on PMPrefetchManager instance. Default network timeout is 3 seconds, defined as NETWORK_TIMEOUT_SECONDS in PubMaticConstants.java. It can be customized as per requirement. It defines the maximum timeout required to get the response from PubMatic ad server. DFP call will be sent either PubMatic responds before this timeout or on elapsing this timeout.
    pmPrefetchManager.setNetworkTimeout(<TIMEOUT>);
  4. Call prefetchCreatives() on instance of PMPrefetchManager created in step 1.
    pmPrefetchManager.prefetchCreatives(<PMBannerPrefetchRequest>);

Handling Prefetched Bids from PMPrefetchManager

  1. On Success, the Prefetch Manager will respond with a callback onBidsFetched() with a map of PMBid objects.

    The keys for this map will be the impression ids. The PMBid object will contain impression ids and price information.
  2. Create a PublisherAdRequest object (in DFP SDK) providing it with all the targeting information using addCustomTargeting.
    //Include string variables in class
      private final String BID              = "bid";
      private final String BID_ID           = "bidid";
      private final String WDEAL_ID         = "wdeal";
      private final String BID_STATUS       = "bidstatus";
      private final String PUBMATIC_WIN_KEY = "pubmaticdm";
    //Code to fetch the winning bid details for the impressionId & send to DFP
        PMBid pubResponse = hBResponse.get(<impressionId>);
        if (pubResponse != null) {

            PublisherAdRequest.Builder requestBuilder = new PublisherAdRequest.Builder();

            if(!TextUtils.isEmpty(pubResponse.getDealId()))
                requestBuilder.addCustomTargeting(WDEAL_ID, pubResponse.getDealId());

            if(!TextUtils.isEmpty(pubResponse.getImpressionId()))
                requestBuilder.addCustomTargeting(BID_ID, pubResponse.getImpressionId());

            String price = String.valueOf(pubResponse.getPrice());

            if(!TextUtils.isEmpty(price)) {
                double bidPrice = Double.valueOf(price);

                if(bidPrice > 0.0d) {
                    requestBuilder.addCustomTargeting(BID, price);
                    requestBuilder.addCustomTargeting(BID_STATUS, "1");
                } else {
                    requestBuilder.addCustomTargeting(BID_STATUS, "0");
                }
            }

            adRequest = requestBuilder.build();

        } else {
            adRequest = new PublisherAdRequest.Builder().build();

     

  3. Call loadAd() from PublisherAdView class object & pass the publisherAdRequest created in step 2.

Receiving DFP App Event Callback

For every winning bid, a DFP app event callback is received via AppEventListener (from DFP SDK).

public void onAppEvent(String key, final String winningImpressionId) {
    //Check if event is for PubMatic then Render the Prefetched creative
}

Rendering Prefetched Creative

Call getPubMaticAdView() method on PMPrefetchManager class object passing the impressionId and publisherAdView instance.

 

pmPrefetchManager.getPubMaticAdView(<impressionId>);

 

It will return the PubMatic’s customized WebView instance loaded with prefetched creative and send the impression tracker. Publisher needs to attach it on parent layout. Customized webview also sends the click tracker on user click over ad. Sample code is shown below:

@Override
public void onAppEvent(String key, final String winningImpressionId) {

    //If PubMatic's bid win then render the creative in WebView
    if (TextUtils.equals(key, PUBMATIC_WIN_KEY)) {

        //Get the PubMatic Ad view
        ViewGroup parent = (ViewGroup) adSlotInfo.adView.getParent();

        PublisherAdView dfpAdView = adSlotInfo.adView;
        if(dfpAdView.getHeight() >= dfpAdView.getAdSize().getHeight() &&
                dfpAdView.getWidth() >= dfpAdView.getAdSize().getWidth()) {

            WebView pubmaticAdView = pmPrefetchManager.getPubMaticAdView(winningImpressionId);

            //Add Pubmatic AdView in screen
            if(pubmaticAdView!=null) {
                pubmaticAdView.setLayoutParams(dfpAdView.getLayoutParams());
//Remember to remove all PubMatic's ad view in case of refresh
                parent.addView(pubmaticAdView, adSlotInfo.adView.getLayoutParams());
            }
        }
    }
}

Using HeaderBiddingBannerHelper (Optional)

The HeaderBiddingBannerHelper class will be a part of Publisher's app. This class can be used as a convenient way to integrate PubMatic's header bidding solution with DFP. Please refer this class in PubMatic’s sample app.


Customize this class to integrate any other header bidding partner in addition to PubMatic.

  1. Create an AdSlotInfo object for each ad slot by providing slot name, list of ad sizes and PublisherAdView.
    HeaderBiddingBannerHelper.AdSlotInfo adSlotInfo = new HeaderBiddingBannerHelper.AdSlotInfo(<SlotName>,
    <List[AdSizes]>, <PublisherAdView>);
  2. Create a list of AdSlotInfo objects.
  3. Create an object of HeaderBiddingBannerHelper giving it the context and the ad slot list created in step 2. Now just call execute.
    HeaderBiddingBannerHelper hbBannerHelper = new HeaderBiddingBannerHelper(<Context>, <AdSlotInfoList>);
    hbBannerHelper.execute();

Setting Refresh Interval (Optional)

This solution provides an optional feature to auto refresh the banner ad after a specified interval.
The default value for refresh interval is 0 seconds, i.e., by default auto refresh feature is disabled. The publisher can set an appropriate refresh interval using the setRefreshInterval(<value in sec>) of PMPrefetchManager. Expected value should be in range of 12 to 120.

 

Table 3. Ad refresh behavior on setting refresh interval value

Value (X) in secondsBehavior
X<=0Ad will not refresh
X > 0 & X <= 12Ad will get refreshed after every 12 seconds.
X > 12 & X <=120Ad will get refreshed after every X seconds
X > 120Ad will get refreshed after every 120 seconds

Note: To use this feature, please disable third party (e.g., DFP) refresh functionality.

      

App debugging

Header bidding code logs the request & response from the PubMatic server in debug mode. This debug log can help to see if PubMatic is providing proper bids or not. Below is a sample log from the Header bidding sample application.

PubMatic Prefetch API Parameter Details

Please refer the following setter functions for sending the targeting parameter values.

 

Table 2. PMBannerPrefetchRequest APIs/Setters

S. noMethodDescription
1setStoreURL(String storeUrl)URL of the app store from where a user can download this application. This URL must match the storeurl that is whitelisted in the UI.
2setAppDomain(String appDomain)Indicates the domain of the mobile application
3setApplicationPaid(boolean paid)

Indicates whether the mobile application is a paid version or not. Possible values are:

false - Free version
true - Paid version

4setAWT(AWT_OPTION awtOption)

Indicates whether the tracking URL has been wrapped or not in the creative tag.

Possible options are:

 

DEFAULT - Indicates that the tracking URL is sent separately in the response JSON as tracking_url. In this case, the tracking_url field is absent in the JSON response.

 

WRAPPED_IN_IFRAME - Indicates that the tracking_url value is wrapped in an Iframe and appended to the creative_tag.

 

WRAPPED_IN_JS - Indicates that the tracking_url value is wrapped in a JS tag and appended to the creative_tag.

5setPMZoneId(String pmZoneId)This parameter is used to pass a zone ID for reporting.
6setEthnicity(ETHNICITY ethnicity)Numeric code of ethnicity
7setIncome(String income)User's income or income range in dollars (whole numbers). For example, inc=50000 or 50000-75000. 
8setYearOfBirth(String yearOfBirth)Visitor's birth year as a four-digit integer. For example, 1975.
9setGender(String gender)Gender of the visitor. Possible values are:
M - Male
F - Female
O - Others
10setCity(String city)City of the user. For example, city=New York
11setZip(String zip)Home zip code if the visitor is present in the U.S.; otherwise it indicates the postal code. 
12setCoppa(boolean coppa)

Indicates whether the visitor is COPPA-specific or not. For COPPA (Children's Online Privacy Protection Act) compliance, if the visitor's age is below 13, then such visitors should not be served targeted ads.

 

Possible options are:
false - Indicates that the visitor is not COPPA-specific and can be served targeted ads.
true - Indicates that the visitor is COPPA-specific and should be served only COPPA-compliant ads.

 

The United States Federal Trade Commission has written a comprehensive FAQ on complying with COPPA at http://business.ftc.gov/documents/Complying-with-COPPA-Frequently-Asked-Questions.

13setOrmmaComplianceLevel(int ormmaaComplianceLevel)Minimum compliance level. Possible values are 0, 1 and 2.
14setIABCategory(String iabCategory)

List of IAB content categories for the overall site/application. Refer the "Table 6.1 Content Categories" in the Open RTB 2.1 / 2.2 specifications document.

If the site/application falls under multiple IAB categories, you can send categories separated by comma

15addKeyword(String keyword)list of keywords indicating the consumer's interests or intent. 
16setLocation(Location location)Location object
17setDoNotTrack(boolean state)If set, it restricts user and device targeting. Default value is false.
This can also be set by end user, on enabling the “Opt out of Ads Personaization” option in an android phone.
Settings > Google > Ads > Opt out of Ads Personalization
18setAndroidAidEnabled(boolean isAndroidAidEnabled)

If set, it uses advertisement id otherwise it uses android id for targeting.

 

This has effect only if DoNotTrack is set to false.

19setAppCategory(String appCategory)Application primary category as displayed on storeurl page for the respective platform.
20setUdidHash(HASHING_TECHNIQUE hash)

Based on the given hashing type, UDID value hashed & sent to the ad server.

 

Note: If setAndroidAidEnabled(true) is invoked & hashing type is also set then hashed as well as raw advertising id would be sent to ad server.

Note: For more details about these parameters, please refer to HTTP Parameters Details (SSP Ad Server) 

      

PubMatic: See PubMatic Setup - Internal to PubMatic for details on Admin UI set up.

Attachments

    Outcomes