---
title: "Header bidding: what a publisher installs"
description: "For a publisher whose network sells through Prebid — what the network hands you for each setup (our Prebid.js, your own Prebid.js, a Prebid Server, Prebid Mobile in an app), where each piece goes, and what to check when a slot stays empty."
type: "howto"
audience: [publisher]
keywords: [header bidding, prebid, prebid.js, prebid server, prebid mobile, publisher, install, script, data-eas-ad, bids entry, epom_as, configId, slot id, google ad manager, line item, app, floor, consent, wordpress]
---

Fetch the complete documentation index at: https://epom.com/ad-server/docs/llms.txt. Use this file to discover all available pages before exploring further. Append .md to any documentation page URL to get its markdown version.

# Header bidding: what a publisher installs

When your network sells your inventory through header bidding, its demand prices each ad position
**before** your own ad server is asked, through Prebid. You do not build anything for it: the
network sets up a header-bidding tag for your site and hands you a few lines to install once.
After that, every change is made on the network's side, with nothing to re-install.

There is no Epom SDK. Epom takes part as an ordinary Prebid bidder called `epom_as`.

## Who this is for

Publishers whose network sells their pages or apps through Prebid. The stock Publisher role has
no **Header Bidding** tab, so the network builds the tag and sends you what to install. If your
network adds the tab to your role, you can build the tags for sites you may edit yourself; the
full guide is [Header bidding](https://epom.com/ad-server/docs/guides/inventory/header-bidding.md).

## Prerequisites

- Your site or app set up in the network, with placements for the ad positions you want sold — your
  network manager creates them or tells you which ones to use.
- Edit access to the page `<head>` (or the WordPress theme header), your Prebid.js configuration,
  or the app code — whichever the integration below needs.
- For Google Ad Manager pages: rights in your Ad Manager to create key-values, an order, a line item
  and a creative.
- For your own Prebid.js or your own Prebid Server: a build that includes the `epom_as` bidder
  adapter, which you get from your network — see [Getting the adapter](#getting-the-adapter).
- For apps: Prebid Mobile in the app, and on Android the `AD_ID` permission.

## What you receive

Tell your network manager how ads are served today; that decides what you get.

| How your pages or app serve ads today | What the network sends you | Where it goes |
|---|---|---|
| Google Ad Manager, no Prebid | One script and one container per ad position, plus a line item to set up in your Ad Manager | The script in the page `<head>`, the containers where the ads go |
| Google Ad Manager with your own `googletag` code you must keep | The same script; the network lists your slot ids or ad unit paths in the tag | The page `<head>`, above the Google tag |
| Your own Prebid.js | One `bids` entry per ad unit (and an alias line, if the network bids under its own name) | Your Prebid configuration |
| An app (Prebid Mobile), or a server-side auction | The Prebid Server address, an account id and one slot id per ad unit | Your app code |
| Your own Prebid Server | The address your server reads the slots from, or one document per slot | Your Prebid Server's configuration |

## Getting the adapter

You need the `epom_as` adapter only when the auction runs in **your own** Prebid.js or **your own**
Prebid Server. With the network's script, or with the Prebid Server address the network sends,
there is nothing to add.

The adapter is Epom's and is not in the standard Prebid.js download or in a released Prebid Server
build. It has been submitted to the Prebid projects and is under review; until it is released
there, you get it from your network, which gets it from Epom:

- **Prebid.js** — the module to add to your own build, or a ready build that carries it.
- **Prebid Server** — your server has to be built with the adapter. Ask your network; Epom helps
  with the setup.

The `epom_dsp` adapter in the standard download is a different Epom product, for buying media,
and cannot take part in these auctions.

## Steps: a page with Google Ad Manager

1. Paste the script into the page `<head>`, **above** the Google Publisher Tag, exactly as sent:

   ```html
   <script src="https://{serving-domain}/eas/t/{tag-id}.js"></script>
   ```

   Do not add `async` and do not defer it: it has to run before Google's tag to hold the ad
   request until the bids are in.
2. Where each ad should appear, place the container the network sent, for example
   `<div data-eas-ad="leaderboard"></div>`. If the network adopted your existing Google slots, skip
   this step: your own `googletag` slots stay.
3. In your Google Ad Manager, create what the network describes: the key-values `hb_pb`, `hb_adid`,
   `hb_size`, `hb_bidder` and `hb_deal_epom_as`, an order with a line item targeted at your ad units,
   and the Prebid universal creative. The network's guide to this is
   [The Google Ad Manager line item](https://epom.com/ad-server/docs/guides/inventory/header-bidding-gam.md#the-google-ad-manager-line-item).
4. Load the page. Positions the network's campaigns buy show their ads; the rest are filled by
   Google exactly as before.

On WordPress, put the script in the theme's header area, not in a post block, so it loads above
the Google tag on every page. A later change to the tag reaches pages that already carry the
script within about five minutes.

## Steps: your own Prebid.js

1. Make sure your Prebid.js build includes the `epom_as` bidder adapter — see
   [Getting the adapter](#getting-the-adapter).
2. Add each `bids` entry to the existing ad unit it names — an extra object in that unit's `bids`
   array, next to your other bidders. Keep your `mediaTypes`, sizes and other bidders unchanged.
   With the values the network sent, an ad unit looks like this:

   ```js
   pbjs.addAdUnits([{
     code: 'article-leaderboard',                      // your ad unit, unchanged
     mediaTypes: { banner: { sizes: [[728, 90], [970, 90]] } },
     bids: [
       { bidder: 'yourOtherBidder', params: { /* unchanged */ } },
       {
         bidder: 'epom_as',
         params: {
           networkId: 'n1234',                         // your network
           host: 'ads.example.com',                    // the network's serving domain
           placementKey: 'a4f21c9e7b'                  // the placement for this position
         }
       }
     ]
   }]);
   ```

   Copy the values from what the network sent rather than typing them:

   | Param | Required | What it is |
   |---|---|---|
   | `networkId` | Yes | Your network, as `n` and a number |
   | `host` | When sent | The network's serving domain, as a bare hostname — no `https://`, no path |
   | `placementKey` | Yes | The placement that sells this position |
   | `channel` | No | A traffic label the network targets and reports on; sent only if the placement has one |
   | `customParams` | No | Key-value pairs the network targets on, for example `{ section: 'sport' }` |
   | `bidFloor`, `bidFloorCur` | No | A floor for this position, in USD — a floor in any other currency is read as USD, not converted; a floor from the Price Floors module wins over it |

   If the network bids under its own name, the entry's `bidder` is that name (for example
   `epom_n1234`) instead of `epom_as`, and the alias line in the next step comes with it.
3. If the network sent an alias line (`pbjs.aliasBidder('epom_as', '…')`), run it once per page
   before the auction; rename `pbjs` if your Prebid uses another global.
4. Run your auction as usual. Do not add a second wrapper or the network's own script beside your
   Prebid: two auctions on the same ad units overwrite each other's results.

For video units, your Prebid needs a cache setting or it drops our VAST bids before your
`bidsBackHandler` runs; see *Instream video* under
[What the publisher does with it](https://epom.com/ad-server/docs/guides/inventory/header-bidding-own-prebid-js.md#3-what-the-publisher-does-with-it).

## Steps: an app with Prebid Mobile

1. Point the SDK at the Prebid Server address and account the network sent — a small-volume
   shared server or a dedicated one, as described under
   [Which Prebid Server to use](https://epom.com/ad-server/docs/guides/inventory/header-bidding-prebid-server.md#which-prebid-server-to-use). For example on
   Android:

   ```java
   PrebidMobile.setPrebidServerAccountId("<networkId>");
   PrebidMobile.setPrebidServerHost(Host.createCustomHost("https://<prebid-server>/openrtb2/auction"));
   ```

2. Use each slot id (it looks like `<networkId>-26`) as the `configId` of one ad unit. One id
   serves one kind of creative: a rewarded video and a rewarded playable are two ad units with two
   ids.
3. Start the ad units from the SDK's initialisation callback, so the first request is not lost.
4. On Android, declare the `AD_ID` permission; without it frequency caps cannot apply to your
   users.

The [example apps for iOS and Android](https://github.com/epom/epom-prebid-mobile-demo) show each
format end to end. If the app logs *Prebid server does not recognize Config Id*, compare the id
character by character with the list the network sent, then see
[When the app gets nothing](https://epom.com/ad-server/docs/guides/inventory/header-bidding-prebid-mobile.md#when-the-app-gets-nothing).

## Options you keep

- **Floors.** A floor you set in Prebid — the Price Floors module, `params.bidFloor`, or
  `imp.bidfloor` from the SDK — is honoured before Epom bids. Floors are in US dollars.
- **Consent.** Your consent manager's TCF string is passed on with every bid request; nothing to
  change on your side. A page without a consent manager still bids.
- **Your other bidders and Google demand.** They compete as before; header bidding adds one bidder,
  it does not replace your ad server.

## Corner cases and gotchas

> **Corner case:** the tag script must load before the Google tag. Loaded after it — moved to the
> footer, given `async`, or delayed by a script-optimisation plugin — it cannot hold Google's first
> ad request, so the page's first impressions go without the bids and header bidding joins only from
> the first refresh. The browser console says so.

> **Corner case:** in your own Prebid, a creative bids only in a size your ad unit lists. If an ad
> unit never shows Epom demand, check that its `mediaTypes.banner.sizes` include the sizes the
> network sells there.

> **Corner case:** a slot id is fixed once created. If the network removes a slot and adds it again,
> it has a new id, and the app has to be updated with it.

## Per-role notes

- **Publisher (stock role):** no Header Bidding tab; you install what the network sends and see the
  results in your usual reports.
- **Publisher with the Header Bidding tab:** build tags for sites you can edit — see
  [Header bidding](https://epom.com/ad-server/docs/guides/inventory/header-bidding.md).

## Related

- [Header bidding (network guide)](https://epom.com/ad-server/docs/guides/inventory/header-bidding.md)
- [Publisher playbook](https://epom.com/ad-server/docs/roles/publisher.md)
- [Quick start for publishers](https://epom.com/ad-server/docs/start/quick-start-publisher.md)
- [Ad tags, invocation codes and the API](https://epom.com/ad-server/docs/guides/inventory/ad-tags-and-api.md)