> 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/hb-analytics/setup/adding-custom-dimensions.md).

# Adding Custom Dimensions

### What are Custom Parameters?

Adding Custom Dimensions or Parameters can be really useful to measure specific events or themes on your website. Examples of this can be anything from a specific website section to screen dimensions or more content-oriented things, such as "Car brands", for articles featuring different car brands.

With this added information you can do more in-depth analysis of your Header Bidder (both technically and from a revenue perspective). So what Custom parameters you want to add (if any) is really down to your imagination and needs for your website.

### Adding Custom Parameters:

{% hint style="info" %}
This article is about web. To learn about how to use custom dimensions in Mobile Apps, please read about [Prebid Mobile Extensions](broken://spaces/thyujPhgXh1WtJZy8bjr/pages/8e369759e40746c367eef702e9a89c1b534a429a).
{% endhint %}

Custom parameters can be used to add more dimensions and filters in the reports, such as “Is user logged in”, “Is there consent”, etc.

What is needed is to create a function named `RELEVANT_ANALYTICS_SETTINGS.getCustomParams`. This function needs to exist before *either* Prebid.js is loaded *or* our tag is loaded. It will, however, not be *called* until after the first auction has completed.

```html
<script>
 window.RELEVANT_ANALYTICS_SETTINGS = window.RELEVANT_ANALYTICS_SETTINGS || {};
 RELEVANT_ANALYTICS_SETTINGS.getCustomParams = function() {
   return {

     // A string (new report dimension + filter)
     'Is logged in': isUserLoggedIn() ? 'Yes' : 'No',

     // Number (new report filter)
     'Times visited': getTimesVisited(),
   };
 };
</script>
```

* If the value is a string it will appear as a new dimension + filter in the report.
* If the value is a number it will appear only as a filter in the reports, where you can filter by *min* and *max* values.

The system scans for custom parameters that have occurred during the last 2 hours when populating the report settings. There is also an up to 5 minute delay in these checks. Therefore there might be situations where you can’t find new custom parameters immediately in the report settings.

{% hint style="warning" %}
Avoid using string custom parameters where the different values will be in the *millions*, such as “user id”, “timestamp”, “pageview id”, etc. This will not work for reporting and it might also degenerate performance for all types of HBA reports on your instance.
{% endhint %}

### To simplify the deployment of custom parameters you can use the JavaScript fields that will inject code in the HBA tags.

For code (e.g. a custom parameter function) that should be *global* for all publishers, override **Custom Global JavaScript code** under **Configuration** => **Global Programmatic Tag:**

![screenshot\_setup](/files/2365d7898e04ef8b6653fb0498bc942d14d09b64)

For code that should execute for a single *publisher* use **Custom Publisher JavaScript code** under **Master Programmatic Tag** on the publisher page for the publisher:

![screenshot\_master\_programmatic\_data](/files/4e8c2d598def5b35d9e1206e0953e0a9f59264a7)

![](/files/fd13942f676e4f00cc57a2b81b247fb5d537baf1)

For code that should execute for a single *site* within a publisher use **Custom Site JavaScript code** under **Programmatic Tag** for the *site*. This is important if you want to use different custom parameters for different websites:

![](/files/9c6d7dc6b5d5c6f2e324858d4fca61162a37deea)

For example, this shows a simple implementation of a “Is Reload” custom parameter for a publisher (notice that this is just an example and will not work for all page designs):

![](/files/d33c951e06c8aa3b4bcfa632450b64046f0facdf)

{% hint style="warning" %}
All codes in the “JavaScript” boxes will run in a *function scope*, so in the example above the “calls” variable will not be global.
{% endhint %}

### **Combining Global / Per Publisher / Per Site Custom Parameters**

The custom JavaScript code is executed in the following order:

1. Custom Global JavaScript code
2. Custom Publisher JavaScript code
3. Custom Site JavaScript code

This means that if you e.g. have *global* custom parameters and want to add *publisher*-specific custom parameters you can for example save the **getCustomParams()** function, get the result from it and combine it with the publisher specific parameters:

```javascript
window.RELEVANT_ANALYTICS_SETTINGS = window.RELEVANT_ANALYTICS_SETTINGS || {};

// Save global/previous function
var prevCustomFn = RELEVANT_ANALYTICS_SETTINGS.getCustomParams;

RELEVANT_ANALYTICS_SETTINGS.getCustomParams = function() {

 // Get the global/previous parameters
 var res = prevCustomFn ? prevCustomFn() : {};

 // Then add more specific parameter(s)
 res['Publisher specific parameter'] = getPublisherSpecificParameter();

 return res;
};
```

### **Example: IAB consent custom parameter**

Let’s take the previous example-code and expand it so that a “Has Consent” custom parameter is logged based upon the response from a TCF 2.0 compatible CMP.

```javascript
window.RELEVANT_ANALYTICS_SETTINGS = window.RELEVANT_ANALYTICS_SETTINGS || {};

// Save global/previous functions
var prevCustomFn = RELEVANT_ANALYTICS_SETTINGS.getCustomParams;
var prevWaitFn = RELEVANT_ANALYTICS_SETTINGS.waitInit;

var consent;

RELEVANT_ANALYTICS_SETTINGS.waitInit = function(doneCb) {
  function initConsentData() {
     // Notice that the CMP “stub” code must have been loaded at this stage.
     // Else __tcfapi will not exist
     if (!consent && window.__tcfapi) {
        __tcfapi("getTCData", 2, function (data) {
           // Let's use Rubicon (vendor-id 52) as our "benchmark"
           consent = data.vendor.consents[52] ? 'Yes' : 'No';
           doneCb();
        });
        // "Failsafe timeout" after 2 seconds
        setTimeout(doneCb, 2000);

     } else {
        doneCb();
     }
  }

  // If needed wait for global/previous waitInit function
  if(prevWaitFn) {
    prevWaitFn(initConsentData)
  } else {
    initConsentData();
  }
};

RELEVANT_ANALYTICS_SETTINGS.getCustomParams = function() {

  // Get the global/previous parameters
  var res = prevCustomFn ? prevCustomFn() : {};

  // Add our parameter
  res['Has Consent'] = consent || 'CMP Not loaded';

  return res;
};
```

In this example we’re defining a **waitInit()** function that will delay sending any analytics even until the **doneCb** function has been called. This is used here to make sure that we receive the callback from the CMP (or times out) *before* **getCustomParams()** is called. We also consider that we might have already defined another **waitInit()** function and make sure to call it before we run our code.

Notice that “having consent” is a bit blurry as the user theoretically might have ticked/unticked different vendors and purposes in the UI dialog. So in the example we check a specific vendor (Rubicon) that we expect to have consent to using the default settings in the CMP.

Sounds tricky? Our support and Onboarders are there to help you, so you can always ask us for assistance regarding setting up the custom Parameters.


---

# 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/hb-analytics/setup/adding-custom-dimensions.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.
