System Design: Ad Server — Targeting, Real-Time Bidding, Impression Tracking, and Click Attribution

Overview

An ad server matches advertisers’ ads to available ad slots on publisher pages in real time. The two main models: direct (publisher sells inventory directly to advertisers at a fixed CPM) and programmatic (real-time bidding, RTB: advertisers bid for each impression in an auction lasting ~100ms). Google Display Network, Facebook Ads, and The Trade Desk use RTB. The components: a Supply-Side Platform (SSP, publisher-side), a Demand-Side Platform (DSP, advertiser-side), and an Ad Exchange that runs the auction between them.

Ad Request Flow (RTB)

User loads a page containing an ad slot. The publisher’s ad tag fires: it sends an ad request to the SSP with bid_request: {impression_id, publisher_id, page_url, ad_slot_size, user_id (cookie or device ID), geolocation, user_agent, floor_price}. The SSP fans out the bid request to multiple DSPs simultaneously (100ms deadline). Each DSP evaluates: does this user match any advertiser’s targeting criteria? What is the maximum bid for this impression? Returns bid_response: {bid_price, ad_markup}. The SSP runs a second-price auction (winner pays second-highest bid + $0.01). The winning ad markup is returned to the browser, which renders the ad. Total latency budget: 100ms end-to-end.

Targeting

Advertisers define targeting criteria: demographic (age, gender), geographic (country, city, zip), behavioral (retargeting users who visited the advertiser’s site), contextual (page content matches keywords), device (mobile, desktop), time of day, browser/OS. User matching: each user has a profile built from cookie data (browsing history, inferred interests, demographics). Stored in a user data platform (DMP): user_id → {segments: [sports_fan, tech_enthusiast], age_bracket: 25-34, location: NYC}. At bid time: the DSP loads the user profile from Redis (sub-millisecond lookup) and evaluates each active campaign’s targeting rules against the profile. Only matching campaigns generate bids.

Budget Pacing

Advertisers set daily budgets. If all impressions are served in the morning, the budget is exhausted and no ads run in the afternoon. Pacing: spread spend evenly across the day. Two approaches: throttling (set a probability P of bidding for each impression; adjust P to hit the target hourly spend rate), and target CPM bidding (the DSP dynamically adjusts bid prices down when ahead of pace, up when behind). Implementation: a pacing service runs every 5 minutes, computes each campaign’s ideal spend so far (budget * elapsed_fraction_of_day), compares to actual spend, and adjusts the bid multiplier. Store budget state in Redis: spend:{campaign_id}:{date} incremented on each win. Atomic INCR prevents race conditions.

Impression and Click Tracking

Impression tracking: when an ad is rendered, the browser fires a pixel (1×1 image) to the impression tracking URL: GET /impression?imp_id=XYZ&creative_id=ABC. The tracking server logs: {impression_id, campaign_id, creative_id, publisher_id, user_id, timestamp, bid_price}. Click tracking: the ad’s destination URL is wrapped: GET /click?imp_id=XYZ&url=https://advertiser.com. The click server logs the click, updates click count, and 302-redirects to the final URL. The redirect adds ~50ms but enables click attribution. Duplicate detection: SETNX imp_id in Redis with TTL=1 hour to deduplicate pixel fires from the same impression (browsers can fire pixels multiple times on slow connections).

Attribution

Attribution answers: which ad caused a conversion (purchase, signup)? Last-click attribution: credit the last ad clicked before the conversion. Multi-touch: distribute credit across all ads in the conversion path. Implementation: on conversion, the advertiser’s site fires a conversion pixel with the same user cookie. The attribution server looks up the user’s click history (last 30 days, stored in a clickstream table) and associates the conversion with the matching campaign. Report conversion counts back to the DSP for optimization. Privacy: third-party cookies are being deprecated. Modern attribution uses privacy-preserving APIs (Chrome’s Attribution Reporting API) and server-to-server postbacks using hashed email or phone as the match key.

Interview Tips

  • Frequency capping: limit impressions per user per campaign per day. Track in Redis: INCR freq:{campaign_id}:{user_id}:{date} with EX 86400. If count > cap, skip the campaign for this user.
  • Second-price auction: winner pays second-highest bid. Incentivizes truthful bidding (DSPs bid their true valuation). Vickrey auction theory.
  • Cold start for new users: no behavioral profile. Use contextual targeting (page content) or lookalike modeling (match to similar known users).

Asked at: Meta Interview Guide

Asked at: Twitter/X Interview Guide

Asked at: Snap Interview Guide

Asked at: LinkedIn Interview Guide

Scroll to Top