> For the complete documentation index, see [llms.txt](https://docs.relevant-digital.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.relevant-digital.com/technical/integration/formats-and-channels/prebid-mobile-extensions.md).

# Prebid Mobile Extensions

Extend Prebid Mobile requests with Relevant Yield server-side controls.

These extensions add no client-side dependencies beyond the Prebid Mobile SDK.

Start with [Setting up Prebid Mobile in HB Manager](/technical/integration/formats-and-channels/setting-up-prebid-mobile-in-hb-manager.md).

### Add custom dimensions

Add global first-party data to header-bid analytics with the `relevant_` prefix.

Use `TargetingParams.addContextData()`:

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

The `relevant_` prefix is not included in reporting.

This creates the **Article Type** and **Is Logged In** dimensions.

#### Modify the Prebid Server request directly

The Prebid Mobile SDK cannot modify the Prebid Server request directly.

If your integration can modify it, set dimensions in `ext.relevant.customParams`:

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

### Set dynamic bidder parameters

Some bidder parameters, including keywords, depend on the current user or request.

Set `ext_merge_json` with `addContextData()` on the Prebid Mobile ad unit.

Pass a stringified JSON object. Its bidder values merge with settings from HB Manager.

This example adds keywords for the **appnexus** bidder:

```
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));
```

{% hint style="info" %}
The server removes `ext_merge_json` immediately after parsing it. Other bid adapters cannot read it.
{% endhint %}

### Configure Relevant extensions

Use the `relevant` key inside `ext_merge_json` for Relevant Yield controls:

```
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));
```

#### Available settings

* **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 helper class

This helper class sets Xandr keywords and Relevant Yield extension values.

{% code title="RelevantData.java" expandable="true" collapsedlinecount="12" %}

```
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());
    }
}
```

{% endcode %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.relevant-digital.com/technical/integration/formats-and-channels/prebid-mobile-extensions.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
