# Ads Serving Service

> High-performance microservice for real-time bidding (RTB) and ad delivery with < 100ms latency.

## Overview

Ads Serving Service is the heart of the advertising system, handling millions of requests per second:

- **Real-Time Bidding (RTB)** - Real-time ad auction
- **Ad Selection** - Select the most relevant ad
- **Pacing Algorithm** - Budget smoothing
- **Frequency Capping** - Control ad frequency per user

## Requirements

| Requirement | Version |
|-------------|---------|
| .NET SDK | 10.0.101+ |
| Docker | 24.0+ |
| Redis | 7.0+ (required) |
| PostgreSQL | 15+ |

## Quick Start

```bash
cd services/ads-serving-service-net
docker-compose up -d
```

## Project Structure

```
ads-serving-service-net/
├── src/
│   ├── AdsServingService.API/
│   │   └── Controllers/
│   │       └── AdServeController.cs
│   │
│   ├── AdsServingService.Domain/
│   │   └── AggregatesModel/
│   │       ├── AdRequestAggregate/
│   │       ├── AuctionAggregate/
│   │       ├── PacingAggregate/
│   │       └── FrequencyAggregate/
│   │
│   └── AdsServingService.Infrastructure/
│
└── AdsServingService.slnx
```

## Ad Serving Flow (< 100ms)

```
Request → Gateway → Check Cache → Run Auction → Return Ad → Fire Events
            │            │              │              │
            ▼            ▼              ▼              ▼
        Traefik      Redis         eCPM Rank      RabbitMQ
                    (< 5ms)       (in-memory)      (async)
```

### eCPM Formula

```
eCPM = (Bid × Predicted CTR × 1000) + Quality Score
```

## API Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | `/api/v1/ads/serve` | Get ad for placement |
| `POST` | `/api/v1/ads/events/impression` | Track impression |
| `POST` | `/api/v1/ads/events/click` | Track click |

## Redis Caching

| Key Pattern | TTL | Purpose |
|-------------|-----|---------|
| `ads:active:{placement}` | 5 min | Active ads list |
| `freq:{userId}:{date}` | 24h | User frequency |
| `budget:{campaignId}:{date}` | 24h | Budget tracker |

## Integration

| Service | Integration |
|---------|-------------|
| **ads-manager-service** | Consume active ads |
| **ads-billing-service** | Publish charges |
| **ads-tracking-service** | Publish events |

## License

Proprietary - GoodGo Platform

## Admin Backoffice APIs

### Auction Management

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/v1/admin/auctions` | List auctions (paginated, with filters) |
| `GET` | `/api/v1/admin/auctions/statistics` | Auction statistics (win rate, eCPM, etc.) |

### Budget Management

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/v1/admin/budget/pacers` | List budget pacers |
| `GET` | `/api/v1/admin/budget/campaigns/{id}` | Get campaign budget status |
| `PUT` | `/api/v1/admin/budget/campaigns/{id}/reset` | Reset daily spend (manual) |
| `GET` | `/api/v1/admin/budget/statistics` | Overall budget statistics |

### Frequency Cap Management

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/v1/admin/frequency/caps` | List frequency caps |
| `GET` | `/api/v1/admin/frequency/caps/{id}` | Get frequency cap details |
| `POST` | `/api/v1/admin/frequency/caps` | Create frequency cap |
| `DELETE` | `/api/v1/admin/frequency/caps/{id}` | Delete frequency cap |

## Database Schema

```sql
-- Auctions table
CREATE TABLE auctions (
    id UUID PRIMARY KEY,
    user_id UUID NOT NULL,
    placement_type VARCHAR(50) NOT NULL,
    auction_time TIMESTAMP NOT NULL,
    bids JSONB,
    winning_ad_id UUID,
    winning_campaign_id UUID,
    final_price DECIMAL(18,4),
    winning_ecpm DECIMAL(18,4)
);

-- Budget Pacers table
CREATE TABLE budget_pacers (
    id UUID PRIMARY KEY,
    campaign_id UUID NOT NULL UNIQUE,
    daily_budget DECIMAL(18,4) NOT NULL,
    spent_today DECIMAL(18,4) NOT NULL,
    strategy VARCHAR(20) NOT NULL,
    last_updated TIMESTAMP NOT NULL
);

-- Frequency Caps table
CREATE TABLE frequency_caps (
    id UUID PRIMARY KEY,
    ad_id UUID NOT NULL,
    max_impressions_per_user INT NOT NULL,
    window VARCHAR(20) NOT NULL
);
```

## Migrations

```bash
# Create migration
dotnet ef migrations add MigrationName --project src/AdsServingService.Infrastructure --startup-project src/AdsServingService.API

# Apply migrations
dotnet ef database update --project src/AdsServingService.Infrastructure --startup-project src/AdsServingService.API
```

