RTB Architecture

    Prebid Server Analytics Modules and Debugging: Interfaces, Debug Flags and Metrics

    Published · Last updated
    Next scheduled review:

    Prebid Server analytics modules are server-side plug-ins that receive a record of every auction, AMP, video, cookie sync, setuid and event call. Debugging is a separate tool: send test: 1 or ext.prebid.debug: true and the response shows each bidder's raw HTTP call. Operational metrics go to Prometheus, InfluxDB or Graphite.

    Key terms on this page: Prebid Server · bidder adapter · log-level data · TCF · tmax · p99 latency · Prebid.js

    Contents

    Key facts

    • Both builds expose a module interface. PBS-Go modules implement six Log...Object methods plus Shutdown; PBS-Java reporters implement processEvent, vendorId and name (analytics/core.go; AnalyticsReporter.java, both accessed 9 November 2026).
    • Modules do ship. PBS-Go's repository holds file, Pubstack and Agma modules; PBS-Java's holds log, Pubstack, Greenbids, Agma and LiveIntent reporters (PBS-Go analytics; PBS-Java config-app.md).
    • Analytics needs its own consent. Under TCF 2.2, Prebid Server needs Purpose 7 to invoke an analytics adapter (Prebid Server privacy, accessed 9 November 2026).
    • Two flags, two behaviours. The test: 1 flag marks the request as a non-billable test and returns the merged request. The ext.prebid.debug: true flag returns the bidder HTTP calls without the test semantics (auction endpoint docs, accessed 9 November 2026).
    • Current versions. PBS-Go 4.11.1 (2 November 2026) and PBS-Java 4.5.0 (4 November 2026) (PBS-Go; PBS-Java).
    Jump to the table

    Definition

    Prebid Server analytics module: a component compiled into Prebid Server that the core calls after each transaction with a structured record of the request, response and outcome. The module decides what to keep and where to send it (Prebid.org, building an analytics adapter, accessed 9 November 2026).

    Hosting the server yourself is what gives you this choice of modules; the trade-offs are in the Prebid Server self-hosting guide, and managed hosts such as Magnite Prebid Server and PubMatic OpenWrap choose for you. A module is not a debugging tool and not a metrics exporter. It sees business events, such as which bidders bid and what won. Metrics count operational events, such as requests, errors and latency, and debug output answers one question about one request.

    4 of 4 rows

    Columns (4)

    Revenue, bid rates and win rates by bidder

    Analytics module

    Your analytics back end

    Runs on every request (sample if needed)

    Why one auction behaved as it did

    test, ext.prebid.debug, ext.prebid.trace

    The auction response

    Only on flagged requests

    Error rates, latency, timeouts

    Metrics

    Prometheus, InfluxDB, Graphite

    Counters, always on

    Live trace of one account or bidder

    PBS-Java admin logging endpoints

    Server logs

    Time-limited

    Revenue, bid rates and win rates by bidder

    Tool

    Analytics module

    Where it lands

    Your analytics back end

    Cost per request

    Runs on every request (sample if needed)

    Why one auction behaved as it did

    Tool

    test, ext.prebid.debug, ext.prebid.trace

    Where it lands

    The auction response

    Cost per request

    Only on flagged requests

    Error rates, latency, timeouts

    Tool

    Metrics

    Where it lands

    Prometheus, InfluxDB, Graphite

    Cost per request

    Counters, always on

    Live trace of one account or bidder

    Tool

    PBS-Java admin logging endpoints

    Where it lands

    Server logs

    Cost per request

    Time-limited

    Download JSON

    Table by AdSovereign, CC BY 4.0.

    The analytics module interface

    PBS-Go defines the contract in analytics/core.go. Each method receives a typed object for one endpoint (core.go).

    // github.com/prebid/prebid-server/v4/analytics (PBS-Go 4.11.x)
    type Module interface {
    	LogAuctionObject(*AuctionObject)                // /openrtb2/auction
    	LogVideoObject(*VideoObject)                    // /openrtb2/video
    	LogCookieSyncObject(*CookieSyncObject)          // /cookie_sync
    	LogSetUIDObject(*SetUIDObject)                  // /setuid
    	LogAmpObject(*AmpObject)                        // /openrtb2/amp
    	LogNotificationEventObject(*NotificationEvent)  // /event
    	Shutdown()
    }

    The auction object carries the HTTP status, errors, the bid response, the account, the start time, module hook outcomes, seat non-bids and the request wrapper. The code comment warns module authors not to marshal these objects directly, because their shape can change between releases. Map them to your own model instead.

    PBS-Java uses one generic method. The comment in the source adds a hard rule: the method "is executed on Vert.x event loop thread so it must never use blocking API" (AnalyticsReporter.java).

    // org.prebid.server.analytics (PBS-Java 4.5.x)
    public interface AnalyticsReporter {
        <T> Future<Void> processEvent(T event);   // AuctionEvent, AmpEvent, VideoEvent, CookieSyncEvent, SetuidEvent, NotificationEvent
        int vendorId();                           // IAB GVL ID, used for TCF checks
        String name();                            // the name used in analytics.global.adapters
    }

    To add a module, PBS-Go needs config properties in config/config.go, the module package under analytics/, and a line in the builder that reads the config. PBS-Java needs the reporter class and a Spring bean in AnalyticsConfiguration (building an analytics adapter). That page also states that "there aren't any open sourced analytics adapters for Prebid Server", which is out of date; the next table lists what both repositories contain today.

    Which analytics modules exist today

    5 of 5 rows

    Columns (5)

    File (Go) or log (Java)

    Yes

    Yes

    analytics.file.filename (Go); analytics.log.enabled (Java)

    Reference implementations that write sample records

    Pubstack

    Yes

    Yes

    analytics.pubstack.enabled, scopeid, endpoint

    Buffers events and pulls remote config every 2 hours by default in Go

    Agma

    Yes

    Yes

    analytics.agma.enabled, endpoint.url, accounts[]

    Buffers by size, count and time

    Greenbids

    No

    Yes

    analytics.greenbids.enabled

    Sampling options for exploration traffic

    LiveIntent

    No

    Yes

    n/d in config-app.md

    Reporter class present in source

    File (Go) or log (Java)

    PBS-Go

    Yes

    PBS-Java

    Yes

    Enable with

    analytics.file.filename (Go); analytics.log.enabled (Java)

    Notes

    Reference implementations that write sample records

    Pubstack

    PBS-Go

    Yes

    PBS-Java

    Yes

    Enable with

    analytics.pubstack.enabled, scopeid, endpoint

    Notes

    Buffers events and pulls remote config every 2 hours by default in Go

    Agma

    PBS-Go

    Yes

    PBS-Java

    Yes

    Enable with

    analytics.agma.enabled, endpoint.url, accounts[]

    Notes

    Buffers by size, count and time

    Greenbids

    PBS-Go

    No

    PBS-Java

    Yes

    Enable with

    analytics.greenbids.enabled

    Notes

    Sampling options for exploration traffic

    LiveIntent

    PBS-Go

    No

    PBS-Java

    Yes

    Enable with

    n/d in config-app.md

    Notes

    Reporter class present in source

    Download JSON

    Table by AdSovereign, CC BY 4.0.

    Sources: PBS-Go config.go and analytics folder; PBS-Java config-app.md and application.yaml; all accessed 9 November 2026.

    PBS-Java also runs adapters by name from a global list. Its bundled default is analytics.global.adapters: logAnalytics, pubstack, greenbids, agmaAnalytics, and each still needs enabled: true (application.yaml). Accounts can switch adapters off. Here are both builds with one module turned on; the Agma keys follow the module's own README (agma README).

    # pbs.yaml (PBS-Go): write records to a file and send to Agma
    analytics:
      file:
        filename: "/var/log/pbs/analytics.log"   # empty by default (off)
      agma:
        enabled: true                            # default false
        accounts:                                # required by the module
          - code: "agma-code"                    # yours: issued by agma
            publisher_id: "1001"                 # your Prebid Server account ID
        endpoint:
          url: "https://go.pbs.agma-analytics.de/v1/prebid-server"   # the default value
          timeout: "2s"
        buffers:
          size: "2MB"
          count: 100
          timeout: "15m"
    # prebid-config.yaml (PBS-Java): only the log reporter, nothing leaves the server
    analytics:
      global:
        adapters: logAnalytics
      log:
        enabled: true

    Getting data into and out of a module

    Requests can pass flags to a named module in ext.prebid.analytics.{module} (auction endpoint docs). PBS-Java can also send module "analytics tags" back to the browser. The account must allow it with analytics.allow-client-details: true, and the request must set ext.prebid.analytics.options.enableclientdetails: true. The tags then appear in ext.prebid.analytics.tags, and Prebid.js forwards them to client-side analytics through its pbsAnalytics event (getEvents docs, accessed 9 November 2026). Client-side events are covered in our Prebid.js guide.

    How to debug a Prebid Server auction

    6 of 6 rows

    Columns (4)

    "test": 1

    Top of the OpenRTB request

    ext.debug.httpcalls, ext.debug.resolvedrequest

    Bidders may treat it as non-billable or skip the auction

    "ext": {"prebid": {"debug": true}}

    Request extension

    ext.debug.httpcalls without the merged request

    None on billing

    "ext": {"prebid": {"trace": "basic"}} or "verbose"

    Request extension

    Module execution trace

    More response data

    debug=1

    AMP query string

    Same as ext.prebid.debug

    None on billing

    ?pbjs_debug=true

    Page URL with Prebid.js

    Prebid.js sends ext.prebid.debug: true

    Console logging in the browser

    x-pbs-debug-override header

    HTTP header with the host's token

    Debug output even where the account or bidder disables it

    Needs debug.override_token (Go) or debug.override-token (Java)

    "test": 1

    Where you set it

    Top of the OpenRTB request

    What you get

    ext.debug.httpcalls, ext.debug.resolvedrequest

    Side effect

    Bidders may treat it as non-billable or skip the auction

    "ext": {"prebid": {"debug": true}}

    Where you set it

    Request extension

    What you get

    ext.debug.httpcalls without the merged request

    Side effect

    None on billing

    "ext": {"prebid": {"trace": "basic"}} or "verbose"

    Where you set it

    Request extension

    What you get

    Module execution trace

    Side effect

    More response data

    debug=1

    Where you set it

    AMP query string

    What you get

    Same as ext.prebid.debug

    Side effect

    None on billing

    ?pbjs_debug=true

    Where you set it

    Page URL with Prebid.js

    What you get

    Prebid.js sends ext.prebid.debug: true

    Side effect

    Console logging in the browser

    x-pbs-debug-override header

    Where you set it

    HTTP header with the host's token

    What you get

    Debug output even where the account or bidder disables it

    Side effect

    Needs debug.override_token (Go) or debug.override-token (Java)

    Download JSON

    Table by AdSovereign, CC BY 4.0.

    Sources: auction endpoint docs, Prebid Server troubleshooting, PBS-Java config-app.md and the PBS-Go header constant in exchange/auction.go, all accessed 9 November 2026.

    Prebid's FAQ sums up the choice: the test flag "is the most appropriate thing to do" for true test requests, but "SSPs may not respond or log test requests" (Prebid Server FAQ). Use ext.prebid.debug when you need to see real production behaviour. Debugging on servers you run, rather than through a vendor's support desk, is one of the practical arguments on our publisher independence hub.

    Debug output can also be blocked. PBS-Go has an account setting, debug_allow, which defaults to true (config.go). PBS-Java checks the account's auction.debug-allow and each bidder's debug.allow. The override header bypasses both when the token matches.

    An annotated debug request and response

    Send this to /openrtb2/auction on a test server. The IDs are placeholders.

    {
      "id": "dbg-001",
      "test": 1,
      "tmax": 800,
      "site": { "page": "https://news.example.com/", "publisher": { "id": "1001" } },
      "imp": [
        {
          "id": "div-top",
          "banner": { "format": [ { "w": 300, "h": 250 } ] },
          "ext": { "prebid": { "bidder": { "pubmatic": { "publisherId": "156209" } } } }
        }
      ],
      "ext": { "prebid": { "returnallbidstatus": true } }
    }

    A trimmed response shows the parts you read first. Field names follow PBS-Go's response model (openrtb_ext/response.go).

    {
      "id": "dbg-001",
      "seatbid": [],
      "ext": {
        "debug": {
          "httpcalls": {
            "pubmatic": [
              {
                "uri": "https://hbopenbid.pubmatic.com/translator?source=prebid-server",
                "requestbody": "{\"id\":\"dbg-001\",\"imp\":[{\"id\":\"div-top\"}]}",
                "requestheaders": { "Content-Type": ["application/json;charset=utf-8"] },
                "responsebody": "",
                "status": 204
              }
            ]
          },
          "resolvedrequest": { "id": "dbg-001", "test": 1, "tmax": 800 }
        },
        "responsetimemillis": { "pubmatic": 87 },
        "tmaxrequest": 800,
        "usersync": {
          "pubmatic": { "status": "none", "syncs": [] }
        },
        "seatnonbid": [
          { "seat": "pubmatic", "nonbid": [ { "impid": "div-top", "statuscode": 0 } ] }
        ]
      }
    }

    Read it in this order. The httpcalls block shows the exact request each adapter sent and the raw answer; a 204 is a plain no-bid. The responsetimemillis map shows how close each bidder came to the deadline. The usersync.{bidder}.status value is none, expired or available, which tells you whether the bidder had a user ID (response.go). If it is none, start with Prebid Server cookie sync. The resolvedrequest object shows what stored requests merged in, explained in Prebid Server stored requests.

    Why a bidder did not bid: seat non-bid codes

    Set ext.prebid.returnallbidstatus: true and Prebid Server adds ext.seatnonbid, which follows the IAB Tech Lab Seat Non-Bid community extension (auction endpoint docs). Most codes are Java-only today.

    10 of 10 rows

    Columns (3)

    0

    General no bid

    Java

    101

    Timeout

    Java

    103

    Bidder unreachable (HTTP 503)

    Java

    202

    Not sent: media type not supported

    Java

    204

    Not sent: TCF Purpose 2

    Java

    300

    Response rejected, general (mostly DSA rules)

    Go and Java

    301

    Response rejected: below floor

    Java

    303

    Response rejected: category mapping invalid

    Go

    351

    Rejected: creative size not allowed

    Go and Java

    352

    Rejected: creative not secure

    Go and Java

    0

    Meaning

    General no bid

    Build

    Java

    101

    Meaning

    Timeout

    Build

    Java

    103

    Meaning

    Bidder unreachable (HTTP 503)

    Build

    Java

    202

    Meaning

    Not sent: media type not supported

    Build

    Java

    204

    Meaning

    Not sent: TCF Purpose 2

    Build

    Java

    300

    Meaning

    Response rejected, general (mostly DSA rules)

    Build

    Go and Java

    301

    Meaning

    Response rejected: below floor

    Build

    Java

    303

    Meaning

    Response rejected: category mapping invalid

    Build

    Go

    351

    Meaning

    Rejected: creative size not allowed

    Build

    Go and Java

    352

    Meaning

    Rejected: creative not secure

    Build

    Go and Java

    Download JSON

    Table by AdSovereign, CC BY 4.0.

    Source: the seat non-bid table on Prebid's auction endpoint page, accessed 9 November 2026. A spike in code 101 points at timeouts and region choice, covered in QPS, latency and bid performance. A spike in 301 points at floors.

    Metrics: what to scrape and alert on

    PBS-Go exports Prometheus metrics only when metrics.prometheus.port is set; the default is 0, which disables them (metrics configuration, accessed 9 November 2026). PBS-Java can report to Graphite, InfluxDB, Prometheus or the console (config-app.md).

    7 of 7 rows

    Columns (3)

    Requests by type and status

    requests

    requests.(ok, badinput, err, ...).(openrtb2-web, openrtb-app, amp, ...)

    End-to-end time

    request_time_seconds

    request_time

    Bidder latency

    adapter_request_time_seconds

    adapter.<bidder>.request_time

    Bidder errors and panics

    adapter_errors, adapter_panics

    n/d in metric list

    Requests without a user ID

    requests_without_cookie

    no_cookie_requests, adapter.<bidder>.no_cookie_requests

    Stored data health

    stored_request_fetch_time_seconds, stored_request_errors

    stored_requests_found, stored_requests_missing

    Debug traffic

    debug_requests

    debug_requests

    Requests by type and status

    PBS-Go Prometheus name

    requests

    PBS-Java metric name

    requests.(ok, badinput, err, ...).(openrtb2-web, openrtb-app, amp, ...)

    End-to-end time

    PBS-Go Prometheus name

    request_time_seconds

    PBS-Java metric name

    request_time

    Bidder latency

    PBS-Go Prometheus name

    adapter_request_time_seconds

    PBS-Java metric name

    adapter.<bidder>.request_time

    Bidder errors and panics

    PBS-Go Prometheus name

    adapter_errors, adapter_panics

    PBS-Java metric name

    n/d in metric list

    Requests without a user ID

    PBS-Go Prometheus name

    requests_without_cookie

    PBS-Java metric name

    no_cookie_requests, adapter.<bidder>.no_cookie_requests

    Stored data health

    PBS-Go Prometheus name

    stored_request_fetch_time_seconds, stored_request_errors

    PBS-Java metric name

    stored_requests_found, stored_requests_missing

    Debug traffic

    PBS-Go Prometheus name

    debug_requests

    PBS-Java metric name

    debug_requests

    Download JSON

    Table by AdSovereign, CC BY 4.0.

    Sources: metrics/prometheus/prometheus.go and PBS-Java metrics.md, accessed 9 November 2026. Alert on the ratio of requests_without_cookie to requests, on bidder latency near your tmax, and on stored-request errors. The container side of scraping, including the port, is in our AWS and Docker reference setup.

    PBS-Java adds admin endpoints for live investigation on port 8060. The logging-httpinteraction endpoint logs full requests for a given account, bidder or status code, up to a limit. The tracelog endpoint raises the log level for one account or bidder for a set number of seconds (admin-endpoints.md, accessed 9 November 2026). That difference between the builds is weighed in Prebid Server Go vs Java.

    A six-step triage routine

    1. Reproduce with ext.prebid.debug: true. Keep billing behaviour real; switch to test: 1 only on a test account.
    2. Read httpcalls for the silent bidder. No entry means the adapter never ran: check parameters, enablement and consent. An entry with a 4xx means a malformed request; a 204 means no bid.
    3. Read seatnonbid. On PBS-Java it names the reason, such as timeout, floor or privacy (codes).
    4. Check usersync. A bidder with no ID bids less on the open web.
    5. Check resolvedrequest. Confirm stored requests and defaults merged as you expected.
    6. Compare with metrics. One request proves a bug exists; the adapter error and latency series show how often it happens.

    When a bidder's parameters or code are the problem, the fix belongs in the adapter, as described in Prebid Server bidder adapters. When the problem is the timeout budget between page and server, start from the timers in header bidding explained.

    Common mistakes

    1. Using test: 1 in production to debug revenue. Some SSPs do not bid or log test requests, so you debug a different auction from the one that earns money.
    2. Expecting debug output with debug_allow off. The account setting suppresses it unless the override header carries the host's token.
    3. Shipping debug output to browsers by default. httpcalls contains full bidder requests and responses. Keep the override token secret and the flag off in page code.
    4. Blocking I/O in a Java reporter. processEvent runs on the Vert.x event loop; a blocking call stalls auctions.
    5. Marshalling Go analytics objects as-is. The interface comment warns their shape can change; map to your own schema.
    6. Forgetting consent for analytics. In GDPR scope, analytics modules need Purpose 7. The EU rules are summarised in GDPR, ePrivacy and the bidstream.
    7. Leaving Prometheus off. PBS-Go collects nothing until metrics.prometheus.port is set.

    FAQ

    Does Prebid Server have analytics adapters?
    Yes. PBS-Go includes file, Pubstack and Agma modules, and PBS-Java includes log, Pubstack, Greenbids, Agma and LiveIntent reporters (PBS-Go config.go; PBS-Java config-app.md). Hosts can also write their own against each build's interface.
    How do I debug Prebid Server?
    Add "ext": {"prebid": {"debug": true}} to the request, or ?pbjs_debug=true to the page when Prebid.js calls the server, or &debug=1 to an AMP call. The response then includes each bidder's HTTP request and response in ext.debug.httpcalls (Prebid Server troubleshooting).
    What is the difference between test and debug in Prebid Server?
    The test: 1 flag is the OpenRTB test flag. Bidders may treat the request as non-billable, and Prebid Server also returns the merged request. The ext.prebid.debug: true flag returns debug output without telling bidders it is a test (auction endpoint docs).
    Why is the debug output missing from my response?
    The account or bidder may disallow debug output: debug_allow in PBS-Go, auction.debug-allow and adapters.<bidder>.debug.allow in PBS-Java. The host can force it with the x-pbs-debug-override header and its configured token (config-app.md).
    How can I see why a bidder did not bid?
    Set ext.prebid.returnallbidstatus: true. The response then lists ext.seatnonbid with a status code per impression, such as 101 for a timeout or 301 for a bid below the floor; most codes are PBS-Java only (auction endpoint docs).
    Can Prebid.js analytics see what happened on the server?
    Partly. Prebid.js emits a pbsAnalytics event with seat non-bid data and, on PBS-Java with client details enabled, analytics tags (getEvents docs). Full server-side records stay in the server's analytics modules.

    How this works on owned infrastructure

    An analytics module receives every bid, price and non-bid reason your auctions produce, which is the raw material of log-level data. On a rented Prebid Server, the host chooses the modules, where their output goes and how long it is kept. AdSovereign runs Prebid Server in your environment and writes auction records to storage you own, so ad ops and data teams query the same events the debug flags reveal, under retention you set. Consent checks such as TCF Purpose 7 still apply, and the deployment is designed to honour them. The use cases page shows how publishers use those records, and security covers access and retention controls.

    Sources

    1. Prebid.org, "Prebid Server: Building an Analytics Adapter" (accessed 9 November 2026). https://docs.prebid.org/prebid-server/developers/pbs-build-an-analytics-adapter.html
    2. Prebid.org, "Prebid Server Endpoints: /openrtb2/auction" (debug, trace, stored responses, seat non-bid, analytics extensions; accessed 9 November 2026). https://docs.prebid.org/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html
    3. Prebid.org, "Prebid Server Troubleshooting" (accessed 9 November 2026). https://docs.prebid.org/troubleshooting/pbs-troubleshooting.html
    4. Prebid.org, "Prebid Server FAQ" (accessed 9 November 2026). https://docs.prebid.org/faq/prebid-server-faq.html
    5. Prebid.org, "Prebid Server Privacy Features" (accessed 9 November 2026). https://docs.prebid.org/prebid-server/features/pbs-privacy.html
    6. Prebid.org, "pbjs.getEvents" (accessed 9 November 2026). https://docs.prebid.org/dev-docs/publisher-api-reference/getEvents.html
    7. GitHub, prebid/prebid-server, analytics/core.go, analytics/ modules, config/config.go, openrtb_ext/response.go, exchange/auction.go, metrics/prometheus/prometheus.go, docs/developers/metrics-configuration.md (master, accessed 9 November 2026). https://github.com/prebid/prebid-server
    8. GitHub, prebid/prebid-server-java, AnalyticsReporter.java, docs/config-app.md, docs/metrics.md, docs/admin-endpoints.md, src/main/resources/application.yaml (master, accessed 9 November 2026). https://github.com/prebid/prebid-server-java
    9. GitHub, prebid/prebid-server release v4.11.1 (2 November 2026). https://github.com/prebid/prebid-server/releases/tag/v4.11.1
    10. GitHub, prebid/prebid-server-java release 4.5.0 (4 November 2026). https://github.com/prebid/prebid-server-java/releases/tag/4.5.0
    More sources (1)
    1. IAB Tech Lab, "Seat Non-Bid" OpenRTB community extension (accessed via Prebid's link, 9 November 2026). https://github.com/InteractiveAdvertisingBureau/openrtb/blob/main/extensions/community_extensions/seat-non-bid.md