Prebid Mobile Extensions

This document describes extensions available when using the the Prebid Mobile SDK. These are implemented server-side which means there are no further client side dependencies.

To get started using the Prebid Mobile SDK along with Relevant Yield, please read: Setting up Prebid Mobile in HB Manager.

Add custom dimensions for headerbid analytics reporting

To add custom dimensions you can add global first party data prefixed with "relevant_". To do this use the TargetingParams.addContextData() function. Example:

TargetingParams.addContextData("relevant_Article Type", "News");
TargetingParams.addContextData("relevant_Is Logged In", "Yes");

The "relevant_" prefix will not be logged for reporting, so in this example there will be two custom dimensions named "Article Type" and "Is Logged In" that you can report on in the HBA reports.

Alternative approach by directly modifying the Prebid Server request object

At the time of writing, there is no way to directly change the Prebid Server request object using the Prebid Mobile SDK. But in case you have the option to modify the request, there is also an alternative, and cleaner way, to supply the parameters via the ext.relevant.customParams object in the BidRequest sent to Prebid Server. Below is as an example using the same custom dimensions as above:

{
    "ext": {
        "relevant": {
            "customParams": {
            "Article Type": "News",
            "Is Logged In": "Yes"
            }
        },
  ...
},
imp: [...],
...
}

Setting arbitrary bid parameters.

Some bid parameters like keywords are dynamic and might depend on individual user etc. In this case they can't be setup in Yield the normal way but must be supplied via the App code.

For this purpose a special context data ext_merge_json is used that should be set using the addContextData() function in the Prebid Mobile ad unit. This should be a stringified JSON object containing the bid parameters per bidder you want to merge with the settings provided by Yield.

The following example using hypothetical JavaScript syntax shows how to set up keywords with bidder appnexus (Xandr):

BannerAdUnit adUnit = new BannerAdUnit(...);
...
const object = {
  "appnexus": {
    "keywords": [
      { "key": "some_key", "value": ["some_value"] },
      { "key": "other_key", "value": ["other_value"] },
    ],
  },
// add other bidder(s) here
};
adUnit.addContextData("ext_merge_json", JSON.stringify(object));

Notice: The ext_merge_json context data will be removed immediately after being parsed on the server. This ensures it won't be read by other bid adapters etc.

Other extensions

Some other Relevant-specific functionality can also be controlled via the ext_merge_json object described above. To do this there is a special key relevant that can be added to the object - containing these settings. Example:

BannerAdUnit adUnit = new BannerAdUnit(...);
...
const object = {
"appnexus": { /** bid paramters */ },
"rubicon": { /** bid paramters */ },
"relevant": { // Relevant specific settings
    "skip_imp_format": true, // Use dimensions specified in Yield instead of in App
"pre_creative_html": "<script src=\"https://example.com/inject.js\"></script>",
"adjust_bids_to_min_price": 0.1, // Adjust small/zero bids up
},
};
adUnit.addContextData("ext_merge_json", JSON.stringify(object));

The following settings exists:

  • skip_imp_format (boolean) - Use dimensions specified in Yield instead of in the App. This means that the dimensions used will not be the dimension(s) specified when setting up a BannerAdUnit object. Instead the dimensions in the Placement Type in Yield will be used. This makes it possible to change the dimensions for placements without updating the App.
  • pre_creative_html (string) - Inject a piece of html into the creative before the normal creative html returned by the bidder.
  • adjust_bids_to_min_price (number) - Force a minimum price of bids. One use case is the Prebid Mobile iOS SDK that else is currently filtering out bids with zero CPM.

Android example helper class

Below is an example of an helper-class for the Android Prebid Mobile SDK that can be used to set keywords in Xandr and to enable the skip_imp_format setting (see above).

package org.prebid.mobile.javademo.ads.gam;

import org.prebid.mobile.AdUnit;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONArray;

import java.util.Arrays;
import java.util.Map;

/**
* Custom bid parameters can be merged in the 'imp' object created for an ad unit. The bidder
* "relevant" is a special object that can contain custom settings.
*
* This is done by setting the context data "ext_merge_json" to a JSON-string.
* Example using "JavaScript syntax":
*
* const object = {
* "appnexus": {
* "keywords": [
* { "key": "some_key", "value": ["some_value"] },
* { "key": "other_key", "value": ["other_value"] },
* ],
* },
* "relevant": {
* "skip_imp_format": true, // Use dimensions specified in Yield instead of in App
* },
* };
* adUnit.addContextData("ext_merge_json", JSON.stringify(object));
*
* This example-class is used to add such data in a couple of specific ways.
*
* Example usage:
*
* RelevantData relevantData = new RelevantData();
* Map<String,String> kws = new HashMap<String,String>();
* kws.put("some_key", "some_value");
* kws.put("other_key", "other_value");
* try {
* relevantData.addXandrKeywords(kws);
* relevantData.setSkipImpFormat();
* relevantData.setPreCreativeHtml("<script src=\"https://example.com/inject.js\"></script>");
* relevantData.setRelevantValue("adjust_bids_to_min_price", 0.1);
* relevantData.apply(adUnit);
* } catch (JSONException e) {
* e.printStackTrace();
* }
*
*/
class RelevantData {
private JSONObject ext = new JSONObject();

private JSONObject objByPath(String[] path) throws JSONException {
JSONObject res = ext;
for (String p: path) {
JSONObject next = res.has(p) ? res.getJSONObject(p) : null;
if (next == null) {
next = new JSONObject();
res.put(p, next);
}
res = next;
}
return res;
}

private JSONArray arrByPath(String[] path) throws JSONException {
String name = path[path.length - 1];
JSONObject obj = objByPath(Arrays.copyOf(path, path.length - 1));
JSONArray res = obj.has(name) ? obj.getJSONArray(name) : null;
if (res == null) {
res = new JSONArray();
obj.put(name, res);
}
return res;
}

private JSONObject objByName(String name) throws JSONException {
return objByPath(new String[]{name});
}

public void addXandrKeywords(Map<String, String> keywords) throws JSONException {
JSONArray kws = arrByPath(new String[]{"appnexus", "keywords"});
for (String key : keywords.keySet()) {
JSONObject kvObj = new JSONObject();
JSONArray kvValues = new JSONArray();
kvValues.put(keywords.get(key));
kvObj.put("key", key);
kvObj.put("value", kvValues);
kws.put(kvObj);
}
}

public void setSkipImpFormat() throws JSONException {
setRelevantValue("skip_imp_format", true);
}

public void setPreCreativeHtml(String html) throws JSONException {
setRelevantValue("pre_creative_html", html);
}

public <T> void setRelevantValue(String key, T value) throws JSONException {
objByName("relevant").put(key, value);
}

public void apply(AdUnit adUnit) {
adUnit.addContextData("ext_merge_json", ext.toString());
}
}