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...Objectmethods plusShutdown; PBS-Java reporters implementprocessEvent,vendorIdandname(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: 1flag marks the request as a non-billable test and returns the merged request. Theext.prebid.debug: trueflag 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).
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
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 |
| 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
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
File (Go) or log (Java) | Yes | Yes |
| Reference implementations that write sample records |
Pubstack | Yes | Yes |
| Buffers events and pulls remote config every 2 hours by default in Go |
Agma | Yes | Yes |
| Buffers by size, count and time |
Greenbids | No | Yes |
| Sampling options for exploration traffic |
LiveIntent | No | Yes | n/d in | 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
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: trueGetting 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
| Top of the OpenRTB request |
| Bidders may treat it as non-billable or skip the auction |
| Request extension |
| None on billing |
| Request extension | Module execution trace | More response data |
| AMP query string | Same as | None on billing |
| Page URL with Prebid.js | Prebid.js sends | Console logging in the browser |
| HTTP header with the host's token | Debug output even where the account or bidder disables it | Needs |
"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.httpcallswithout 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) ordebug.override-token(Java)
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
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
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
Requests by type and status |
|
|
End-to-end time |
|
|
Bidder latency |
|
|
Bidder errors and panics |
| n/d in metric list |
Requests without a user ID |
|
|
Stored data health |
|
|
Debug traffic |
|
|
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
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
- Reproduce with
ext.prebid.debug: true. Keep billing behaviour real; switch totest: 1only on a test account. - Read
httpcallsfor 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. - Read
seatnonbid. On PBS-Java it names the reason, such as timeout, floor or privacy (codes). - Check
usersync. A bidder with no ID bids less on the open web. - Check
resolvedrequest. Confirm stored requests and defaults merged as you expected. - 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
- Using
test: 1in 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. - Expecting debug output with
debug_allowoff. The account setting suppresses it unless the override header carries the host's token. - Shipping debug output to browsers by default.
httpcallscontains full bidder requests and responses. Keep the override token secret and the flag off in page code. - Blocking I/O in a Java reporter.
processEventruns on the Vert.x event loop; a blocking call stalls auctions. - Marshalling Go analytics objects as-is. The interface comment warns their shape can change; map to your own schema.
- Forgetting consent for analytics. In GDPR scope, analytics modules need Purpose 7. The EU rules are summarised in GDPR, ePrivacy and the bidstream.
- Leaving Prometheus off. PBS-Go collects nothing until
metrics.prometheus.portis set.
FAQ
Does Prebid Server have analytics adapters?
How do I debug Prebid Server?
"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?
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?
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?
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?
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
- 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
- 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
- Prebid.org, "Prebid Server Troubleshooting" (accessed 9 November 2026). https://docs.prebid.org/troubleshooting/pbs-troubleshooting.html
- Prebid.org, "Prebid Server FAQ" (accessed 9 November 2026). https://docs.prebid.org/faq/prebid-server-faq.html
- Prebid.org, "Prebid Server Privacy Features" (accessed 9 November 2026). https://docs.prebid.org/prebid-server/features/pbs-privacy.html
- Prebid.org, "pbjs.getEvents" (accessed 9 November 2026). https://docs.prebid.org/dev-docs/publisher-api-reference/getEvents.html
- 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 - 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 - GitHub, prebid/prebid-server release v4.11.1 (2 November 2026). https://github.com/prebid/prebid-server/releases/tag/v4.11.1
- 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)
- 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