Welcome to OpenAdServe Documentation
Welcome to the complete documentation for OpenAdServe, a publisher-first ad server designed to educate developers about advertising technology while providing a fully functional serving platform. This documentation will guide you from initial setup to advanced customization, teaching core ad tech concepts along the way.
What is OpenAdServe?
OpenAdServe is a single-instance ad server built with Go that demonstrates modern ad serving architecture through clean, production-quality code. It provides the complete serving stack from API requests to analytics, with every component designed for clarity and extensibility.
Educational Mission: This project exists to demystify ad serving technology. Every architectural decision prioritizes learning and understanding, with comprehensive documentation explaining the "why" behind each implementation choice.
Publisher-First Design: Unlike black-box ad servers where selection logic is hidden, OpenAdServe gives publishers complete control over ad selection algorithms, targeting rules, and pacing strategies. You own the code, you control the decisions.
Production-Ready Implementation: While designed for education, this is not toy code. OpenAdServe handles real traffic with sub-100ms response times, comprehensive analytics, and battle-tested ad serving patterns used by major platforms.
Who Should Use This?
Students & Educators - Learn how real ad servers work through complete implementations of targeting, pacing, frequency capping, and analytics. Every feature includes documentation explaining core concepts.
Publishers - Understand what happens behind the scenes when you integrate third-party ad servers. Evaluate alternatives or run direct campaigns with full control over the serving logic.
Software Engineers - Study a complete ad serving implementation with modern Go practices, clean architecture patterns, and extensible design. All core logic uses pluggable interfaces for easy customization.
Product Managers - Gain technical depth on ad serving capabilities, trade-offs, and limitations. Understand the complexity involved in features you might take for granted.
Quick Start
New to OpenAdServe? Get running in under 5 minutes with Docker Compose:
git clone https://github.com/patrickwarner/openadserve.git
cd openadserve
cp .env.example .env
docker compose up -d
docker compose exec openadserve go run ./tools/fake_data
Then visit the Quick Start Guide for detailed instructions, validation steps, and your first ad request.
Learning Paths
Choose your path based on your goal:
I'm Learning Ad Tech
Start here to understand ad serving fundamentals:
- Project Overview - Understand the problem space and target audience
- Systems Architecture - See how components fit together
- Ad Decisioning - Learn how the system selects winning ads
- Pacing System - Understand budget distribution algorithms
- Analytics - Explore event tracking and reporting
Key Concepts to Master:
- Line items, campaigns, and placements
- eCPM calculation and bid competition
- Targeting, frequency capping, and pacing
- Real-time decision-making under latency constraints
I'm Integrating OpenAdServe
Get your site serving ads quickly:
- Quick Start - Get running in 10 minutes with Docker
- API Reference - Understand request/response formats
- Integration Guide - JavaScript SDK and server-to-server integration
- Trafficking Guide - Create campaigns and line items
- Analytics - Monitor performance with Grafana dashboards
Common Integration Tasks:
- Embed JavaScript SDK on your pages
- Configure placements for different ad units
- Set up targeting rules for your content
- Track performance and optimize campaigns
I'm Customizing or Extending
Build on the platform:
- Development Guide - Setup, testing, and debugging
- Systems Architecture - Understand the component model
- Ad Decisioning - Implement custom selection algorithms
- Dimension Registration - Add custom targeting dimensions
- Configuration Guide - Environment variables and tuning
Extension Points:
- Custom ad selection algorithms via
Selectorinterface - Registered dimensions for type-validated targeting
- Custom pacing algorithms (ASAP, Even, PID, or your own)
- ML models for CTR prediction
I'm Evaluating Ad Servers
Understand capabilities and limitations:
- Project Overview - Architecture and feature summary
- Limitations - Design constraints and scaling considerations
- Inventory Forecasting - Advanced bid-aware conflict detection
- CTR Optimization - ML-based CPC campaign optimization
- Programmatic Demand - Header bidding and Prebid integration
Evaluation Criteria:
- Single-instance vs. distributed architecture
- Performance characteristics and latency
- Customization and extensibility
- Analytics and reporting capabilities
Core Concepts
Understanding these concepts will help you work effectively with OpenAdServe. For a comprehensive reference of all ad tech terminology used throughout the documentation, see the Glossary.
Key Terminology
Campaign Hierarchy
Publishers → Placements → Campaigns → Line Items → Creatives
- Publishers: Top-level entity representing your site or app
- Placements: Specific ad slots on your pages (header, sidebar, in-content)
- Campaigns: Groups of line items with shared budgets and goals
- Line Items: Individual ad configurations with targeting and pacing rules
- Creatives: The actual ad content (HTML, images, native elements)
Learn more in the Trafficking Guide.
Line Item Budgets
Line items support multiple budget types that determine how they compete:
- CPM (Cost Per Mille): Pay per 1000 impressions - bid is the CPM value
- CPC (Cost Per Click): Pay per click - bid converted to eCPM using CTR prediction
- No Budget: Remnant inventory with configurable priority
eCPM normalization ensures fair competition between CPM and CPC line items. Learn more in Ad Decisioning.
Targeting
Control which requests match each line item:
- Device/OS/Browser: Automatically detected from User-Agent headers
- GeoIP: Country and region targeting using MaxMind GeoLite2
- Registered Dimensions: Type-validated custom dimensions with analytics indexing
- Custom Key-Values: Flexible targeting for any custom attributes
Learn more in Dimension Registration.
Pacing
Distribute impressions evenly over time to avoid spending budgets too quickly:
- ASAP: Serve as fast as possible until budget exhausted
- Even: Target uniform distribution across the flight
- PID Controller: Advanced algorithm that adapts to traffic patterns
Learn more in Pacing System.
Frequency Capping
Limit how often individual users see the same ad:
- Per-User Limits: Cap impressions per user across configurable time windows
- Redis Storage: Fast lookups using user cookies or device IDs
- TTL-Based Cleanup: Automatic expiration of old frequency data
Learn more in Ad Decisioning.
eCPM (Effective Cost Per Mille)
Normalized bid value that allows fair competition between different budget types:
- CPM Line Items: eCPM = CPM bid value
- CPC Line Items: eCPM = CPC × Predicted CTR × 1000
- No Budget: eCPM based on configurable priority
Line items compete on eCPM at the same priority level. Learn more in Ad Decisioning.
Features
Campaign Management
Placements and Creatives
- Define ad slots with sizes and formats
- Support for HTML, banner, and native creatives
- Responsive image sizing with automatic srcset generation
- Click URL macro expansion and tracking
Line Item Configuration
- CPM and CPC budget types with eCPM competition
- Priority-based ordering (1-10, where 1 is highest)
- Flight date scheduling with timezone support
- Daily and total budget caps
Frequency Capping
- Per-user impression limits across time windows
- Cookie and device ID-based tracking
- Automatic expiration via Redis TTL
Pacing Controls
- ASAP, Even, and PID pacing algorithms
- Budget and impression-based pacing modes
- Real-time adaptation to traffic patterns
Learn more: Trafficking Guide | Pacing System
Optimization and Forecasting
CTR Prediction
- Optional ML-based click-through rate prediction
- Context-aware features (device, GeoIP, time, placement)
- eCPM boost for CPC campaigns based on predicted CTR
- Synthetic data generation for model training
Inventory Forecasting (Beta)
- Predict available impressions for potential line items
- Bid-aware conflict detection (10% eCPM threshold)
- Priority-based preemption modeling
- Historical traffic pattern analysis via ClickHouse
- Note: Algorithm needs revision - use as rough estimates only
Rate Limiting
- Token bucket algorithm per line item
- Protect against traffic spikes and abuse
- Configurable refill rates and bucket sizes
Learn more: CTR Optimization | Inventory Forecasting | Rate Limiting
Integration and Extensibility
JavaScript SDK
- Automatic ad rendering and tracking
- Responsive image sizing
- Error handling and fallbacks
- Customizable styling
Server-to-Server API
- RESTful ad request endpoint
- Signed impression and click tracking URLs
- Custom event tracking
- OpenRTB compatibility (partial)
Programmatic Demand
- Optional Prebid Server integration
- Header bidding alongside direct campaigns
- Unified auction with eCPM competition
- S2S and client-side bidding support
Pluggable Architecture
Selectorinterface for custom ad selection algorithms- Registered dimensions for type-validated targeting
- Custom pacing algorithm implementations
- Extensible analytics event schema
Learn more: Integration Guide | Programmatic Demand | Ad Decisioning
Analytics and Observability
Event Tracking
- ClickHouse storage for impressions, clicks, and custom events
- Sub-second latency for event ingestion
- Registered dimension indexing for fast queries
- Retention policies for cost-effective storage
Metrics and Dashboards
- Prometheus metrics for request rates, latencies, and errors
- Pre-built Grafana dashboards for campaign performance
- Custom event aggregation queries
- Real-time monitoring and alerting
Distributed Tracing
- OpenTelemetry integration with Tempo backend
- Automatic trace ID injection in all logs
- End-to-end request tracing across components
- Performance profiling and debugging
Quality Control
- Built-in ad reporting API for user feedback
- Configurable moderation workflows
- Report aggregation for publisher review
- Content policy enforcement
Learn more: Analytics | Ad Reporting | Custom Events
Advanced Features
AdCP (Ad Context Protocol)
- AI-powered advertising automation via MCP server
- Natural language campaign creation and management
- Inventory forecasting through conversational interface
- OpenAI integration for intelligent ad workflows
Dimension Registration
- Promote custom key-values to first-class dimensions
- Type validation (enum, number, string) with constraints
- ClickHouse column indexing for analytics performance
- Backward compatibility with custom key-values
Multi-Tenancy
- Support multiple publishers in single instance
- Publisher-scoped placements and campaigns
- Isolated analytics and reporting per publisher
- Optional publisher-specific rate limits
Learn more: AdCP Integration | Dimension Registration | Multi-Tenancy
Data Architecture
OpenAdServe uses a multi-store architecture optimized for different access patterns:
PostgreSQL - Source of Truth
- Campaigns, line items, placements, and creatives
- Publisher configuration and settings
- Slowly-changing reference data
Redis - Operational Counters
- Frequency cap tracking (user impression counts)
- Pacing counters (budget and impression spent)
- Rate limiting buckets (per line item)
- TTL-based automatic cleanup
ClickHouse - Analytics Events
- Impressions, clicks, and custom events
- Registered dimension columns for fast aggregation
- Time-series partitioning for query performance
- Retention policies for cost management
In-Memory Store
- Campaign data loaded from PostgreSQL
- Single-instance deployment model
/reloadendpoint or automatic refresh- Optimized for sub-100ms ad selection
Learn more: Systems Architecture | Data Stores
Request Flow
Understanding how ad requests flow through the system:
- Client Request → POST /ad with placement, device, and targeting data
- GeoIP Lookup → Automatic country/region detection from IP address
- Campaign Loading → Retrieve active campaigns from in-memory store
- Single-Pass Filter → Apply targeting, frequency, pacing, and rate limits efficiently
- CTR Prediction → Optional eCPM boost for CPC campaigns (if enabled)
- Ranking → Sort candidates by priority, then eCPM within priority
- Winner Selection → Return highest-ranked eligible line item
- Token Generation → Create signed URLs for impression and click tracking
- Response → JSON payload with creative content and tracking URLs
Tracking Events:
- GET /impression → Verify token → Record to ClickHouse → Update Redis counters
- GET /click → Verify token → Record to ClickHouse → Redirect to advertiser URL
Learn more: Ad Decisioning | Systems Architecture
Configuration and Deployment
Environment Variables:
POSTGRES_URL- PostgreSQL connection for campaigns and configurationREDIS_ADDR- Redis connection for operational countersCLICKHOUSE_URL- ClickHouse connection for analytics eventsRELOAD_INTERVAL- Auto-reload campaign data (e.g., "5m")DIMENSIONS_CONFIG_PATH- Path to dimensions.yaml (optional)TRACING_ENABLED- Enable distributed tracing (default: true)TEMPO_ENDPOINT- Tempo endpoint for traces (default: tempo:4317)
Development Tools:
fake_data- Generate demo campaigns and line itemstraffic_simulator- Simulate realistic ad traffic patternscampaign_report- Generate performance reports for campaignsquery_events- Query ClickHouse analytics by request IDgenerate_clickhouse_schema- Create SQL for registered dimensions
Pre-commit Hooks:
goimports- Format code and organize importsgo vet- Detect suspicious constructsgolangci-lint- Comprehensive static analysisgo mod tidy- Clean dependenciesgo test- Run all tests before commit
Learn more: Configuration Guide | Development Guide | Deployment Guide
Limitations and Considerations
OpenAdServe is designed for single-instance deployments with specific trade-offs:
Scaling Constraints:
- In-memory campaign data limits horizontal scaling
- Redis used only for counters, not campaign storage
- Best suited for small to medium traffic volumes
- Custom modifications required for distributed deployments
Feature Gaps:
- No built-in user authentication or multi-user admin UI
- Limited OpenRTB support (partial compatibility)
- No video or audio ad formats
- No real-time bidding (RTB) integration beyond Prebid
Production Considerations:
- Single point of failure without custom HA setup
- Campaign data reload requires API call or restart
- ClickHouse retention policies need manual configuration
- GeoIP database updates require periodic refreshes
Need help scaling or adding features? Contact the author to discuss custom development.
Learn more: Limitations | Deployment Guide
Help and Support
Documentation:
- Browse this documentation site for comprehensive guides
- Check Limitations for known constraints
- Review Development Guide for troubleshooting
Community:
- GitHub Issues: Report bugs or request features
- GitHub Discussions: Ask questions and share use cases
- Email: patrick@openadserve.com for direct support
Commercial Support:
- Custom development and feature additions
- Scaling and distributed deployment assistance
- Training and consulting services
Next Steps
For Learners: Start with Project Overview to understand the architecture, then explore Ad Decisioning to see how ad selection works.
For Integrators: Follow the Quick Start Guide to get running, then review Integration Guide for SDK setup and Trafficking Guide for campaign creation.
For Developers: Read the Development Guide for setup and testing, then explore Ad Decisioning to understand the selector interface and filter architecture.
For Evaluators: Review Project Overview for capabilities, Limitations for constraints, and Inventory Forecasting for advanced features.
Ready to get started? Head to the Quick Start Guide now.