What actually happens between a page load and an ad appearing

By Luca Passani, @Scientia_CTO, May 2026

Note: this article assumes that you are familiar with certain programmatic/ad tech concepts, such as SSPs and DSPs. If not, please refer to the first installment of this article series.

Do you remember the stock exchange scene in the “Trading Places” movie? It’s 1983. Dan Aykroyd and Eddie Murphy are standing still in the middle of people shouting their buy and sell orders. Plenty of movies from the 80s and 90s portray open outcry situations, but recent movies don’t. Why is that? The reason is simple. Technology computerized all of that away. Buy and sell orders are now processed by machines in a split second. No need to shout anymore.

I’m not aware of movies that portray the minutiae of ad space buying and selling in the old days, but I can tell you that those tasks happened and required humans. Letting advertisers buy ad space from publishers programmatically, by bidding in real-time auctions for advertising space. 

You open a news article, and your browser starts loading the page. Somewhere in that process — before the headline has fully rendered, before the images have loaded, before you’ve read a single word — a real-time auction fires, a winner is selected, and an ad is served into the space the publisher reserved for it. The whole thing takes roughly 1 second.

In this blog post, I go into the black box that makes banners and videos automatically appear. If you are a newbie to programmatic, this will make the machinery snap into focus. 

Meet our hypothetical user, you.

You read a long-form tech article on a mid-tier publisher’s website. The publisher has three ad slots on the page. The moment your browser starts loading, all three slots trigger auctions simultaneously. I’m going to follow one of them — the banner in the middle of the article — from start to finish.

The diagram below maps the complete flow — refer back to it as we walk through each step.

Figure: The full header bidding auction flow, from page load to creative delivery

Step 1: The bid request is born

The publisher’s website runs a JavaScript library called Prebid.js. Because Prebid is open-source and modular, publishers don’t just “download it” from Prebid.org; they “build it”. A publisher goes to Prebid.org and checks the boxes for the specific SSPs they want to invite to the party (like Magnite or Xandr) and the features they need (like GDPR consent handling). The result is a bespoke, minified JavaScript file that contains only the code necessary for their specific ecosystem, keeping the “plumbing” as light as possible.

<script src="//cdn.example.com/js/prebid.js" async></script>

The next part is about configuring the advertising space made available for programmatic sale.

var adUnits = [{
    code: 'mid-article-banner',
    mediaTypes: {
        banner: {
            sizes: [[300, 250]]
        }
    },
    bids: [
        { bidder: 'rubicon', params: { accountId: '1234', siteId: '5678', zoneId: '9012' } },
        { bidder: 'pubmatic', params: { publisherId: '15678', adSlot: 'mid_article_300x250' } },
        { bidder: 'indexExchange', params: { id: '1', siteId: '234567' } }    ]
}];

// Prebid.js adds the units and starts the race
pbjs.que.push(function() {
    pbjs.addAdUnits(adUnits);
    pbjs.requestBids({
        timeout: 1000,
        bidsBackHandler: initAdserver
    });
});

The moment the page loads, Prebid.js wakes up, looks at that ad slot, and assembles a bid request — a structured packet of data describing the opportunity. Think of it as a “snapshot” of the impression, compiled in real time, containing:

    • The publisher’s domain and the specific placement (mid-article banner, 300×250)

    • Your approximate location (Manhattan, inferred from IP)

    • The device and browser (say Samsung Galaxy S24, Chrome — or at least, what the browser claims to be)

    • Any audience “signals” available: consent flags under privacy regulations, first-party data segments the publisher has built, and — if you’re logged in somewhere — a universal ID that lets buyers recognize you across sites (you work in advertising, you are not surprised, right?)

Note: A “signal” is programmatic speech for any piece of data passed through the ad ecosystem that helps buyers and sellers understand a user or the context of a webpage.

Prebid.js fires this bid request simultaneously to every SSP the publisher has integrated — say: Magnite, PubMatic, Index Exchange, OpenX, and Xandr. All five receive the same info at the same moment.

{
  "id": "89b7c12...34a",
  "imp": [{
  "id": "1",
  "banner": { "w": 300, "h": 250 },
       "bidfloor": 0.50
   }],
 "site": {
  "domain": "tech-publisher.com",
   "page": "https://tech-publisher.com/articles/the-future-of-chips",
    "publisher": { "id": "pub123", "name": "Global Tech News" }
  },
   "device": {
    "ua": "Mozilla/5.0 (Linux; Android 10; K) 
                AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Mobile Safari/537.36",
   "geo": { "city": "New York", "zip": "10001", "lat": 40.7128, "lon": -74.0060 },
    "make": "Generic",
    "model": "Android Device",
    "os": "Android"
  },
  "user": {
    "id": "u-987654321",
    "ext": { "eids": [{ "source": "id5.io", "uids": [{ "id": "..." }] }] }
  },
  "regs": { "ext": { "gdpr": 0 } }
}

Gotcha alert: This confused me a bit the first time I approached Prebid.js. I didn’t immediately grasp the role of SSP adapters, the ones that publishers will include in their Prebid.js build to support their agreement with each SSP.  You can’t just point a generic script at an SSP and hope for the best; you need a Bidder Adapter. Think of these adapters as specialized translators. While OpenRTB is the “common language”, every SSP has its own specific accent, its own required data fields, and most importantly, its own unique endpoint (in the REST sense of the term).  If a publisher wants to work with Magnite, they must include the Magnite adapter in their build. Without that URL, the browser literally doesn’t know where to send the data or how to format it to meet Magnite’s specific requirements. This is why the file size of Prebid.js varies—a publisher working with 15 SSPs will have a heftier library than one working with three, because they’re carrying 15 different sets of instructions for 15 different endpoints.

Note about video ads: Display banners are the simplest case, and the one I’ve walked through above. In practice, the same auction logic applies to video, with two important differences. First, the bid request has a different object structure: instead of a banner object, it contains a video object with parameters like minimum and maximum duration, playback method, and supported formats. Second, the stakes are considerably higher — video ad prices (CPM, see later), particularly for in-stream pre-roll, run several times higher than display. That makes the quality of every signal in the request way more important.

Little Aside: Prebid Server

While the browser often talks directly to SSPs, there’s a more “industrial” way to handle the auction: the Prebid Server (PBS). Instead of forcing the user’s device to juggle twenty individual connections—which can be a recipe for battery drain and slow page loads—the browser sends a single, unified request to this central hub. The Prebid Server then does the heavy lifting, “fanning out” the request to dozens of bidders at once from the safety of a high-speed data center. 

Figure: Prebid Server (Diagram from Prebid.org)

Figure: Prebid Server Architecture (freely inspired by a similar diagram on Prebid.org)

Large, tech-savvy publishers often host their own PBS instances for maximum control, but it’s increasingly common to see “Managed Service” versions run by third parties like SSPs, Ad Exchanges, or publisher Monetization Partners. It’s essentially the difference between calling every guest individually to invite them to a party versus hiring a professional coordinator to handle the logistics for you. 

Note: Publisher Monetization Partners/Platforms (also known as Yield Optimization Partners/Platforms): companies like Freestar, Raptive, Mediavine, and Assertive Yield that help publishers set up and run their programmatic ad stack in exchange for a cut of their ad revenue. 

Note: Why would an SSP/Ad Exchange run an instance of Prebid Server that would send bids to its competitors? This question puzzled me initially. The fact is that, for most publishers, relying on an Ad Exchange’s hosted instance is the most common way to use Prebid Server (PBS). While the code for Prebid Server is open-source (Go and Java), setting up, scaling, and maintaining a server cluster capable of handling millions of requests per second is a massive engineering headache. Most publishers would rather outsource that “plumbing”. For SSPs, there are mainly three reasons to run a PBS server. “Stickiness”(a publisher is more likely to keep that SSP as their primary one). Performance (the auction happens in a high-speed data center). Data Visibility (while Prebid is transparent, the company hosting the server has the best view of the auction’s health, latency, and success rates).

Step 2: The SSPs go shopping

To provide a clear picture of what happens once a bid request leaves the publisher’s environment, we need to look at the “enrichment” phase. To make an impression “bid-worthy” for a DSP, the SSP acts as a quality filter and data enhancer, calling out to a suite of specialized third-party subsystems in the few milliseconds it has available.

The SSP’s External Ecosystem

Once the bid request hits the SSP’s servers, it triggers a series of lightning-fast side-calls to these essential partners:

    • Identity Resolution (Universal IDs): Since third-party cookies are increasingly “not guaranteed”, SSPs call Identity Providers to attach a deterministic or probabilistic ID to the request. This allows a DSP to recognize “you” as the same person who looked at a car site yesterday, even without a cookie. Main players in this area are ID5, The Trade Desk (UID2.0) and LiveRamp (RampID/ATS). A long tail of regional and specialized IDs exist — Zeotap ID+, Lotame Panorama, Neustar Fabrick — just to name a few.

    • Invalid Traffic (IVT) & Fraud Protection: Before a DSP will even consider a bid, they need an independent guarantee that the “user” isn’t a bot and the site isn’t a domain-spoofing operation. SSPs use “Pre-Bid” fraud filtering to drop suspicious requests before they ever reach the auction. Main players in this area are DoubleVerify (DV), Pixalate, Integral Ad Science (IAS), HUMAN, and Confiant.

    • Contextual Intelligence & Brand Safety: If your company sold toys for kids, you wouldn’t want your ads to show up on a page that shows war, terrorism, or adult content. To help advertisers avoid situations like this, SSPs call contextual engines that scan page URLs in real time to categorize sentiment and topics.  Main players in this area are Peer39 and Comscore.

Each SSP receives the bid request and forwards it — enriched with their own data — to the DSPs in their network. This is where a technical standard called OpenRTB earns its keep.

The “Standardized” Handover

All of this gathered intelligence—the ID, the safety score, and the contextual category—is bundled into the expanded OpenRTB JSON object. The SSP is essentially acting as a “quality certifier”, taking a raw, messy signal from the browser and turning it into a verified, bankable asset that a DSP can bid on with confidence.

By the time the DSP receives the request, it isn’t just looking at a URL and an IP; it’s looking at a verified human user on a brand-safe tech news site with a high probability of viewability. This “enriched” bid request is what ultimately determines whether a DSP bids $0.50 or $5.00.

Message from the sponsor — a note on the device signal:  The bid request example I showed above refers to a publisher who is not making any particular effort to determine the make and model of the user’s device, an additional “signal” which the buy-side (DSPs and advertisers) will likely find valuable to determine the value of a bid. Coincidentally, ScientiaMobile is behind WurflRTD, a Prebid.js add-on (technically a Real-Time Data provider) that will deliver exactly that. We will discuss signals further in Article 4.

OpenRTB is the electrical socket standard of programmatic advertising. Just as any appliance can plug into any wall outlet because everyone agreed on the voltage and pin configuration, any SSP can talk to any DSP because everyone agreed on the format of a bid request. It’s a standardized JSON structure, maintained by the IAB Tech Lab, with defined fields for device information, user data, impression details, and floor prices. Without OpenRTB, every SSP-DSP relationship would require a custom integration. The ecosystem as it exists today would be physically impossible.

Each SSP contacts the DSPs most likely to be interested in “your impression”. Each DSP now has milliseconds to decide: do I bid? And if so, how much?

Step 3: The DSPs decide

This is where the real intelligence lives. A DSP receives the bid request and runs it through its bidding engine, answering several questions simultaneously:

    • Does this impression match any of my active campaigns?

    • Is the device and location relevant to those campaigns?

    • What do I know about this publisher’s inventory quality?

    • What’s my optimal bid given my remaining budget and campaign pacing?

Note: Answering these questions well is the core competency of a DSP — and the logic behind it belongs entirely to the “Audient” side of the Ad Tech mountain. We cover this in
The Accidental Architecture: How programmatic advertising was never designed — it evolved
‘. Audience segmentation, campaign targeting, bid optimization algorithms, attribution modeling: that’s a world unto itself, and one I’m deliberately leaving for another day. This series is focused on the supply side — the plumbing that gets an impression to market in the first place. If you work on the buy side and feel shortchanged, noted. You’ll get your article eventually.

The unit of currency is CPM — cost per mille, or cost per thousand impressions. A DSP bidding $2.50 CPM says it will pay $2.50 per thousand impressions of this type. Which means that for that single impression, the actual transaction value if this DSP wins is $0.0025. Fractions of fractions of a dollar, a million times a second, across the entire internet. This is why programmatic needs to be fast.

Some DSPs will pass entirely — your profile doesn’t match their campaigns, or they’ve already spent their daily budget, or the signals in the bid request aren’t reliable enough to act on confidently. Others submit a bid.

Step 4: Winners bubble up

Each SSP also runs its own internal auction — it collects the bids it received from the DSPs and identifies a winner. That winning bid goes back to Prebid.js on the publisher’s page. Remember, five SSPs ran this process in parallel. Prebid.js collects all five winning bids, compares them against each other and against the publisher’s floor price — the minimum CPM they’ll accept for that slot — and selects the overall winner.

Note: Today’s auctions are first-price, i.e., the winner pays exactly what they bid, not the second-highest bid plus a cent, as was standard until a few years ago. The shift changed bidding strategy significantly: DSPs now shade their bids downward to avoid overpaying, rather than bidding their true maximum. Google Ad Manager, the dominant publisher ad server, accelerated this transition when it moved its own AdX exchange to first-price in 2019 — and given GAM’s market position, most of the industry followed. More on how Google leveraged that position in Step 5. 

Here’s what a bid response from the SSP to the publisher looks like:

{
    bidderCode: 'rubicon', // Which SSP sent this (rubicon = Magnite)
    width: 300,
    height: 250,
    statusMessage: 'Bid available',
    ad: '<html>...</html>', // The 'adm' from above
    cpm: 5.25, // The price Prebid will use for the auction
    currency: 'USD',
    netRevenue: true, // Tells Prebid if SSP fees are already deducted
    requestId: '22b31f0', // Links this back to the specific request
    creativeId: 'crid_456',
    ttl: 300 // How many seconds this bid is valid
}

Notice the netRevenue field. It’s a boolean that tells Prebid.js whether the quoted CPM is net of SSP fees or gross. You’d think this would be standardized — after all, knowing the actual cost of an impression is fairly basic information if you’re a publisher trying to compare bids from five SSPs simultaneously. But here’s how it actually works: each SSP reports back to the publisher’s page using whatever gross/net basis it was configured with at integration time. If SSP1 reports gross and SSP2 reports net, Prebid is comparing apples to oranges. The netRevenue flag is the only mechanism available to signal the difference — and it is self-reported, non-binding, and unverified. An SSP can set it to true and still be wrong, deliberately or otherwise. Nobody checks.

The industry’s formal answer to this problem is Prebid’s bidCpmAdjustment function, which lets publishers manually encode a correction factor per SSP adapter to normalize bids before the final comparison. Which means the publisher — or their monetization platform — has to independently know each SSP’s fee structure and configure it themselves. Most don’t.

It’s a small thing, but it tells you something about how this industry resolves disputes between parties with opposite incentives: when no one has enough leverage to force a standard, the standard that emerges is a flag that says “trust me”. This pattern is not that unusual.

Step 5: The Ad Server has the final word

Now, you’d think that we are done and we have a winner. Not so. This surprised me the first time I heard about it. The story isn’t quite done yet. The winning Prebid bid goes to the publisher’s ad server — almost always Google Ad Manager (GAM, also known as DFP for historic reasons) at the time of this writing. The ad server weighs the Prebid winner against any direct deals or guaranteed campaigns the publisher is also running. If a brand pays upfront for guaranteed placement, that can override the auction result entirely, no matter what the winning CPM was.

Note: Google has also been known to use its “last look” privilege — the ability to review the winning Prebid bid before making a final decision — in ways that attracted significant antitrust scrutiny: in April 2025, a federal court ruled that Google had willfully engaged in anticompetitive acts to acquire and maintain monopoly power in the open-web display advertising market, finding it had unlawfully tied its publisher ad server to its ad exchange (AdX). The DOJ is currently pushing for Google to divest both. But that’s a story for another day.

Assuming the Prebid bid wins, the creative gets fetched and served into your browser. The banner appears. The auction is over. You have barely noticed that the page has loaded.

Three numbers that obsess everyone in the room

Across this entire chain, three metrics are tracked constantly:

Bid rate — the percentage of bid requests an SSP sends that a DSP actually responds to with a bid. When bid rates are low, it usually means the inventory doesn’t match campaign criteria — or that the signals in the bid request aren’t trustworthy enough for a DSP to act on confidently. Either way, the publisher loses.

Win rate — the percentage of auctions a DSP wins after placing a bid. A high bid rate but a low win rate means DSPs are interested but getting outbid. Low bid rate means the inventory isn’t “legible”, i.e., not interesting enough to bid on at all.

Fill rate — the number the publisher actually feels: what percentage of available ad slots got filled with a paying ad. Fill rate is the downstream consequence of everything that happens upstream. Low bid rates and win rates are the cause; low fill rate is the bill.

The reconciliation problem

Once an auction closes and an impression is served, every party in the chain — the DSP, the SSP, the publisher’s ad server — independently logs what just happened. And their numbers rarely agree. Each entity logs and interprets the same event slightly differently, producing a handful of records that capture the same event but at slightly different times. The DSP counts an impression the moment it sends the creative. The SSP counts it when the ad call is received. The publisher’s ad server counts it when the ad actually renders in the browser. A user who closes the tab halfway through page load might be counted by one system and not another. An ad-blocker might suppress the impression client-side but not server-side. The result is that, at the end of the month, everyone’s numbers differ, and someone has to reconcile them before any money changes hands.

Since the numbers never balance, the DSP will typically overestimate to ensure it bills the agency or advertiser the correct amount — but if it overbills its clients prior to SSP reconciliation and then pays the SSP less than originally estimated, the advertiser ends up paying higher effective fees than stated in the contract. The IAB’s official position on all of this is (unsurprisingly by now) pragmatic: a discrepancy of up to 10% is considered acceptable — anything higher is a signal to review tags, platforms, and how impressions are counted across partners. 

Again, that’s ten percent. In an industry that processes hundreds of billions of dollars a year. Reconciliation is largely manual, routinely disputed, and has become even more arduous with header bidding, which increases bid density per impression by making it available to multiple SSPs simultaneously.  Every layer of the stack that solved a problem created a new one. Reconciliation is no exception.

The signal problem

Every bid request is a snapshot — a real-time portrait of an impression opportunity assembled in milliseconds and fired across the ecosystem. DSPs make consequential decisions — bid or don’t bid, how much to pay — based entirely on that snapshot. And the quality of that snapshot varies enormously.

Sometimes it’s accurate and rich. Sometimes the device is misidentified. Sometimes the location is wrong. Sometimes the field that tells the ecosystem what device and browser you are using is truncated, spoofed, or simply absent. The auction mechanism is elegant. The data flowing through it is considerably messier than most buyers realize.

That messiness is the subject of one of the next pieces. But before we go there, it’s worth understanding who all these players actually are — and why their incentives don’t always align.

Next installmentThe Players and Their Incentives — The Supply Side. Publishers, SSPs, and the business of selling attention.

Want to stay updated on future posts? Follow me on X @Scientia_CTO. Spotted any inaccuracies? Slide into my DMs @Scientia_CTO


This article is part of a larger series of articles. Find other articles in this series below:

    1. The Accidental Architecture: How programmatic advertising was never designed — it evolved.

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

Want access to the latest mobile device trends?

Download the Mobile Overview Report.

>