Skip to content
Back to Documentation

Server-Side Ad Insertion (SSAI)

Complete guide to integrating ApexMediation's SSAI system for seamless ad stitching across Live and VOD content.

What is Server-Side Ad Insertion?

Server-Side Ad Insertion (SSAI), also known as Dynamic Ad Insertion (DAI), stitches advertisements directly into the video stream at the server level before delivery to the viewer. This approach eliminates ad blocker effectiveness, ensures seamless playback, and provides broadcast-quality ad experiences across all devices.

Key Benefits

  • Ad blocker resistant: Ads are part of the content stream, indistinguishable from program content
  • Seamless experience: No buffering or player reinitialization between content and ads
  • Broad compatibility: Designed to work across modern HLS and DASH players. Exact compatibility depends on protocol, container, DRM policy, and player capabilities—see the Certified Playback Matrix and protocol pages.
  • Accurate measurement: Server-side tracking with exactly-once delivery guarantees

Architecture Overview

┌─────────────────────────────────────────────────────────────────────┐
│                        Video Player (SDK)                            │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                  │
│  │ HLS.js      │  │ Shaka       │  │ ExoPlayer   │                  │
│  │ AVPlayer    │  │ dash.js     │  │ Native      │                  │
│  └─────┬───────┘  └──────┬──────┘  └──────┬──────┘                  │
└────────┼─────────────────┼────────────────┼─────────────────────────┘
         │                 │                │
         └─────────────────┼────────────────┘
                           │
                    ┌──────▼──────┐
                    │  CDN Edge   │  ← Segments cached at edge
                    └──────┬──────┘
                           │
              ┌────────────▼────────────┐
              │   SSAI Manifest Service │
              │  ┌───────────────────┐  │
              │  │ Session Manager   │  │
              │  │ Pod Decisioning   │  │
              │  │ Manifest Stitcher │  │
              │  │ Tracking Engine   │  │
              │  └───────────────────┘  │
              └────────────┬────────────┘
                           │
         ┌─────────────────┼─────────────────┐
         │                 │                 │
   ┌─────▼─────┐    ┌──────▼──────┐   ┌──────▼──────┐
   │  Origin   │    │  Ad Server  │   │ Demand      │
   │  (CMS)    │    │  (VAST/VMAP)│   │ Partners    │
   └───────────┘    └─────────────┘   └─────────────┘

Request Flow

  1. Session Init: Player SDK requests a session manifest URL, providing device capabilities, consent signals, and targeting context.
  2. Manifest Fetch: Player fetches the personalized HLS/DASH manifest from the SSAI service (CDN may cache segments but not the manifest).
  3. Ad Break Detection: SSAI service detects ad break opportunities from SCTE-35, EXT-X-DATERANGE, or DASH EventStream signals.
  4. Pod Decisioning: Real-time auction selects ads matching format requirements, competitive separation rules, and frequency caps.
  5. Manifest Stitching: Ad segments are stitched into the manifest with proper discontinuity markers and timing information.
  6. Segment Delivery: Player fetches stitched segments from CDN edge (content and ads appear as unified stream).
  7. Tracking: Impressions, quartiles, and completion events fire server-side with deduplication for exactly-once delivery.

Integration

Session Initialization

POST /v1/session/init
{
  "tenant_id": "your-tenant-id",
  "asset": {
    "id": "content-12345",
    "type": "vod",           // "live" | "vod"
    "duration": 3600         // seconds (VOD only)
  },
  "device": {
    "type": "ctv",           // "web" | "mobile" | "ctv" 
    "os": "tvos",
    "model": "Apple TV 4K",
    "player": "avplayer"
  },
  "format": {
    "protocol": "hls",       // "hls" | "dash"
    "container": "cmaf",     // "ts" | "cmaf"
    "drm": null              // "widevine" | "fairplay" | null
  },
  "consent": {
    "gdpr": true,
    "ccpa": false,
    "us_privacy": "1YNN"
  }
}

Response

{
  "session_id": "sess_abc123xyz",
  "manifest_url": "https://ssai.apexmediation.ee/v1/session/sess_abc123xyz/master.m3u8",
  "expires_at": "2025-01-15T12:00:00Z",
  "tracking_url": "https://track.apexmediation.ee/v1/session/sess_abc123xyz"
}

Ad Decisioning & Timing

Pod Structure

Each ad break is organized as a "pod" containing one or more slots. The decisioning engine fills each slot based on format compatibility, competitive separation, and frequency caps.

Slot Types

Pre-roll

Before content playback begins

Mid-roll

During content at signaled break points

Post-roll

After content completion

SLA Guarantees

  • Decision Deadline: Pod decisions complete before break start (p99 < 200ms)
  • Fallback Behavior: If deadline approaches, slate (fallback content) is served rather than black screen
  • Safe Mode: During incidents, system reduces fanout and enforces strict deadlines

Content Correctness

The SSAI system enforces strict content correctness rules to ensure seamless playback:

Format Compatibility

Ads must match content codec, resolution tier, and container format. HLS/TS content receives HLS/TS ads; DASH/CMAF content receives DASH/CMAF ads.

Audio Continuity

Audio layout (stereo/5.1/Atmos) and loudness (EBU R128/ATSC A/85) are validated and normalized to prevent jarring transitions.

Timing Alignment

Segment durations are aligned to GOP boundaries. Discontinuity sequences are maintained consistently across renditions.

Caption Handling

CEA-608/708 captions are preserved through ad breaks. WebVTT timing is adjusted to account for ad insertion.

Observability & Forensics

Every ad decision is fully explainable for debugging and support:

Explain API

GET /v1/session/{session_id}/pod/{pod_id}/explain
{
  "pod_id": "pod_123",
  "break_type": "midroll",
  "slots_requested": 3,
  "slots_filled": 2,
  "decision_trace": [
    {"step": "partner_request", "partner": "partner_a", "duration_ms": 45},
    {"step": "format_filter", "rejected": 2, "reason": "codec_mismatch"},
    {"step": "competitive_separation", "rejected": 1, "reason": "same_category"},
    {"step": "frequency_cap", "rejected": 0},
    {"step": "final_selection", "selected": 2}
  ],
  "unfilled_reason": "no_compatible_inventory"
}

Metrics Exposed

  • Session counts by tenant/channel
  • Pod decision latency (p50/p95/p99)
  • Fill rate by break type
  • Format rejection reasons
  • Partner response times
  • Tracking event success rate

Security & Privacy

Signed Session Tokens

All session manifests are protected by cryptographically signed tokens with TTL expiration. Tokens are validated on every manifest request.

Anti-Tampering

Session parameters (targeting, consent) cannot be modified after session creation. Any tampering attempt results in session invalidation.

Rate Limiting

Per-tenant, per-session, and per-IP rate limits prevent abuse and protect against session storms during player retry loops.

Cache Isolation

Session manifests use private/no-store cache headers to prevent cross-user manifest poisoning at CDN edges.

Platform Coverage Matrix

Certified
Limited (player-specific config required)
Not supported by platform
PlatformHLS/TSHLS/CMAFDASH/TSDASH/CMAFLiveVOD
Web (hls.js)
Web (Shaka)
tvOS (AVPlayer)
Android TV (ExoPlayer)
Roku
Fire TV

DASH + TS containers: While technically supported by some players (Shaka, ExoPlayer), DASH with TS segments requires player-specific configuration and is not recommended for new deployments. Use DASH + CMAF for full compatibility. See Container Formats for details.

Next Steps