> ## Documentation Index
> Fetch the complete documentation index at: https://docs.interchange.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Set up TMP with Prebid

> Install the Scope3 module in Prebid.js or Prebid Server, wire the targeting keys into Google Ad Manager, and confirm real-time targeting is serving on your inventory.

## Overview

This is the install path for publishers who run **Google Ad Manager with
Prebid** — the established way to connect a storefront to
[real-time targeting (TMP)](/v2/storefront/tmp/overview). You add the Scope3
module to your existing Prebid setup; on each ad request it calls the hosted
TMP Router and returns targeting key-values that your GAM line items match
against. No new infrastructure, no change to how you sell — the module
enriches the requests you already serve.

Installing takes three steps: add the module with your credentials, make sure
the targeting keys reach GAM, and verify end-to-end. Most publishers complete
the page-side work in an afternoon.

<Note>
  Run your own ad stack or sales agent instead of GAM/Prebid? That's the
  self-hosted router path — see the
  [TMP overview](/v2/storefront/tmp/overview#how-you-connect--one-router-two-ways)
  and talk to Scope3 about onboarding.
</Note>

## Before you start

* **You run Prebid.js 10.9.0 or later.** The Scope3 RTD provider ships in
  the Prebid.js tree from 10.9.0; any version before that (10.8.x and
  below, including all of 9.x) does not include it and cannot build it.
  If you're on an older wrapper, plan the Prebid upgrade first.
* **Your storefront is set up** with your GAM connected as an inventory
  source (see [inventory sources](/v2/storefront/inventory-sources/overview)).
* **You have your Scope3 credentials.** Prebid.js needs your **org ID**;
  Prebid Server needs an **API key**. Both are issued by Scope3 during TMP
  onboarding — ask Murph in chat, or your Scope3 team, to get them issued.
  Use exactly the values you're given.
* **You know who runs your Prebid.** If a wrapper vendor manages your header
  bidding, the install below is theirs to make — send them this page and your
  credentials, and stay on the thread for the [GAM half](#configure-google-ad-manager),
  which is yours.

## Which integration — Prebid.js or Prebid Server?

|               | **Prebid.js (client-side)**                           | **Prebid Server**                                                        |
| ------------- | ----------------------------------------------------- | ------------------------------------------------------------------------ |
| Where it runs | In the browser, inside your existing wrapper          | In your Prebid Server deployment                                         |
| Install shape | Add a module to your Prebid.js build + a config block | Compile the module in + a YAML config block                              |
| Credential    | `orgId`                                               | `auth_key` (your Scope3 API key)                                         |
| Best when     | You run a standard Prebid.js wrapper on-page          | You already operate Prebid Server, or manage many properties server-side |

Both call the same hosted router and produce the same targeting keys. If
you're unsure, client-side Prebid.js is the shorter path.

## Install the module

<Tabs>
  <Tab title="Prebid.js (client-side)">
    <Steps>
      <Step title="Include the module in your Prebid.js build">
        The module is the **Scope3 RTD provider** (`scope3RtdProvider`) —
        a standard Prebid Real-Time Data module, built into your bundle like
        any other:

        ```bash theme={null}
        gulp build --modules=scope3RtdProvider,rtdModule,...yourOtherModules
        ```

        Full reference:
        [docs.prebid.org — Scope3 RTD provider](https://docs.prebid.org/dev-docs/modules/scope3RtdProvider.html).
      </Step>

      <Step title="Add the configuration">
        ```javascript theme={null}
        pbjs.setConfig({
          realTimeData: {
            auctionDelay: 100,
            dataProviders: [{
              name: "scope3",
              waitForIt: true,
              params: {
                orgId: "YOUR_ORG_ID" // issued by Scope3
              }
            }]
          }
        });
        ```

        | Parameter                   | Required | Default                            | What it does                                                                     |
        | --------------------------- | -------- | ---------------------------------- | -------------------------------------------------------------------------------- |
        | `orgId`                     | Yes      | —                                  | Your Scope3 organization ID — use exactly the value issued with your credentials |
        | `endpoint`                  | No       | `https://prebid.scope3.com/prebid` | The hosted router endpoint                                                       |
        | `timeout`                   | No       | `1000` (ms)                        | Max time to wait for the router's response                                       |
        | `bidders`                   | No       | all auction bidders                | Restrict which bidders receive the signals                                       |
        | `includeKey`                | No       | `axei`                             | Targeting key for include segments                                               |
        | `excludeKey`                | No       | `axex`                             | Targeting key for exclude segments                                               |
        | `macroKey`                  | No       | `axem`                             | Targeting key for creative macros                                                |
        | `cacheEnabled` / `cacheTtl` | No       | `true` / `300000` (ms)             | Response caching                                                                 |
      </Step>

      <Step title="Send targeting to GAM only after the auction ends">
        The module writes its keys (`axei`, `axex`, `axem`) onto your ad
        units at **auction end**. If your page calls
        `setTargetingForGPTAsync()` earlier, the keys silently never reach
        GAM.

        ```javascript theme={null}
        pbjs.onEvent('auctionEnd', function () {
          pbjs.setTargetingForGPTAsync();
        });
        ```

        Calling it inside `bidsBackHandler` (which runs after the auction)
        is equally correct. If your wrapper uses a `setTimeout` fallback,
        make sure it cannot fire before the auction completes.
      </Step>
    </Steps>

    <Warning>
      The auction-end timing above is the most common install mistake — the
      page looks fine, the module calls the router successfully, and GAM
      still never sees the keys. If you hand the install to a wrapper
      vendor, include this step verbatim.
    </Warning>
  </Tab>

  <Tab title="Prebid Server">
    <Steps>
      <Step title="Build with the module enabled">
        The module ships with Prebid Server (Go) behind a build tag:

        ```bash theme={null}
        go build -tags scope3_rtd
        ```

        Full reference:
        [docs.prebid.org — Scope3 real-time data module](https://docs.prebid.org/prebid-server/pbs-modules/scope3-real-time-data.html).
      </Step>

      <Step title="Add the configuration">
        ```yaml theme={null}
        hooks:
          enabled: true
          modules:
            scope3:
              rtd:
                enabled: true
                auth_key: ${SCOPE3_API_KEY} # issued by Scope3
                timeout_ms: 1000
                cache_ttl_seconds: 60
                add_to_targeting: true
        ```

        | Parameter           | Required | Default | What it does                              |
        | ------------------- | -------- | ------- | ----------------------------------------- |
        | `enabled`           | Yes      | —       | Turns the module on                       |
        | `auth_key`          | Yes      | —       | Your Scope3 API key                       |
        | `timeout_ms`        | No       | `1000`  | Router request timeout                    |
        | `cache_ttl_seconds` | No       | `60`    | Response cache window                     |
        | `add_to_targeting`  | No       | `false` | Writes the segments as GAM targeting keys |

        The module also needs its hooks registered on the
        `/openrtb2/auction` endpoint (entrypoint, raw auction request, and
        auction response stages) — the module reference shows the full
        `host_execution_plan` block.
      </Step>
    </Steps>

    <Warning>
      `add_to_targeting` defaults to **`false`**. For TMP campaigns to
      deliver through GAM line items, set it to **`true`** — without it the
      module runs but your ad server never receives the targeting keys.
    </Warning>
  </Tab>
</Tabs>

## Configure Google Ad Manager

The module puts key-values on your ad requests; GAM needs the matching keys
and line items. If your storefront runs a
[GAM sales agent](/v2/storefront/inventory-sources/overview), most of this is
automated:

* **Targeting keys** — the custom targeting keys (`axei`, `axex`, `axem`)
  are created by the **segment keys** task in your sales agent's setup panel.
  Complete it once; it's listed under your inventory source's setup tasks.
* **Line items** — when a buyer's media buy executes, your sales agent
  creates the GAM order and line item targeting the campaign's `axei` value
  automatically. You don't traffic these by hand; you'll see them appear
  under the advertiser your sales agent manages.
* **Authorize the creative tracker domain** — in GAM, authorize
  `https://ping.interchange.io` for creatives (Google's validation of the
  domain is in progress, so today this is a one-time manual authorization).

<Warning>
  Skipping the tracker-domain authorization is the most common reason a
  correctly-installed setup serves nothing: GAM blocks the creative with a
  domain error, and impressions stay at zero until the domain is authorized.
</Warning>

<Note>
  If your consent management platform maintains a vendor allowlist (e.g.
  Didomi), add `ping.interchange.io` as a custom vendor so consent tooling
  never blocks the tracker.
</Note>

## Verify it's working

<Steps>
  <Step title="Check the module is firing">
    Load a page with `?pbjs_debug=true` and confirm in the browser's network
    panel that a request goes to `prebid.scope3.com/prebid` and returns
    `200`.
  </Step>

  <Step title="Check the keys reach GAM">
    On the same page, inspect the GAM ad request and confirm the `axei` key
    appears in the request's custom targeting (for video/instream, check the
    `cust_params` of the video ad call — the keys must ride there too).
  </Step>

  <Step title="Check delivery end-to-end">
    Once a TMP-targeted media buy is live, its line item in GAM should show
    impressions against the `axei` targeting. In chat, ask Murph to check
    your TMP setup — it can confirm your enrollment state and flag anything
    missing.
  </Step>
</Steps>

## Troubleshooting

| Symptom                                                              | Likely cause                                                  | Fix                                                                                                                         |
| -------------------------------------------------------------------- | ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| Build fails on `scope3RtdProvider`, or the module never fires at all | Prebid.js older than 10.9.0 — the module isn't in your tree   | Upgrade Prebid.js to 10.9.0+; the module ships in-tree from that release                                                    |
| Module calls the router, but no `axei` in GAM requests               | `setTargetingForGPTAsync()` runs before auction end           | Move it to `auctionEnd` / `bidsBackHandler` (see install step 3)                                                            |
| Display works, video doesn't                                         | Keys aren't reaching the video call's `cust_params`           | Wire the same targeting keys into your video player's GAM ad-call parameters                                                |
| Line item exists but zero impressions                                | Creative blocked on the tracker domain                        | Authorize `https://ping.interchange.io` in GAM (see above)                                                                  |
| Campaign under-delivers                                              | Line-item price vs. your floors, or goal-type pacing behavior | Check the line item's CPM clears your GAM floor rules; note GAM does not pace price-priority line items with lifetime goals |

Still stuck? Ask Murph in chat — describe what you're seeing and it will help
diagnose or flag the Scope3 team with the details.

## Related

<CardGroup cols={2}>
  <Card title="Real-time targeting (TMP)" icon="tower-broadcast" href="/v2/storefront/tmp/overview">
    What TMP is, the capabilities it unlocks, and the two connection paths.
  </Card>

  <Card title="Frequency caps" icon="gauge-high" href="/v2/guides/frequency-caps">
    How buyer-side, cross-publisher caps work on TMP-connected storefronts.
  </Card>

  <Card title="Inventory sources" icon="plug" href="/v2/storefront/inventory-sources/overview">
    Connecting your GAM and managing your sales agent's setup tasks.
  </Card>

  <Card title="Scope3 RTD provider reference" icon="book" href="https://docs.prebid.org/dev-docs/modules/scope3RtdProvider.html">
    The module's full parameter reference on docs.prebid.org.
  </Card>
</CardGroup>
