Get Started with Aeion Ads

Set up your ad monetization in 5 steps. Create zones, connect 10 ad networks, build waterfall, run direct campaigns with pacing, and monitor real-time revenue—all in under 20 minutes.

1

Enable Ads Module & Create Your First Zone

FormatNameSizeResponsive
`300x250`Medium Rectangle300×250No
`728x90`Leaderboard728×90No
`160x600`Skyscraper160×600No
`300x600`Wide Skyscraper300×600No
`320x50`Mobile Leaderboard320×50Yes
`300x50`Mobile Banner300×50Yes
`native`NativeFluidYes
2

Connect Ad Networks

Go to Ads → Networks → Add Network.

Available Networks: Google AdSense, Meta Audience Network, Amazon Associates, Taboola, Outbrain, Media.net, PropellerAds, Ezoic, Infolinks, BuySellAds

Connect Google AdSense (API):

bash POST /ads/networks { "name": "Google AdSense", "adapter": "adsense", "status": "active", "priority": 1, "floorEcpm": 0.50, "timeoutMs": 2000, "credentials": { "publisherId": "pub-1234567890123456", "slotId": "1234567890" } }

Network Configuration (API):

bash POST /ads/networks { "name": "Amazon Publisher Services", "adapter": "amazon", "status": "active", "priority": 2, "floorEcpm": 0.30, "timeoutMs": 3000, "credentials": { "apiKey": "amzn-xxxx", "adSlotId": "aps-slot-xxx" } }

Set Network Waterfall Order (API):

bash PATCH /ads/zones/{zoneId} { "waterfall": [ { "networkId": "network-xxx", "weight": 1.0 }, { "networkId": "network-yyy", "weight": 0.8, "minEcpm": 0.50 }, { "networkId": "network-zzz", "weight": 0.5 } ] }

Response:

typescript { "id": "zone-xxx", "waterfall": [ { "networkId": "network-xxx", "weight": 1.0, "order": 1 }, { "networkId": "network-yyy", "weight": 0.8, "minEcpm": 0.50, "order": 2 }, { "networkId": "network-zzz", "weight": 0.5, "order": 3 } ] }

Network Health (API):

bash GET /ads/adapters/health

Response:

typescript { "networks": [ { "id": "network-xxx", "name": "Google AdSense", "status": "healthy", "fillRate": 92, "avgEcpm": 2.45, "lastChecked": "2026-05-11T09:00:00Z" }, { "id": "network-yyy", "name": "Amazon APS", "status": "healthy", "fillRate": 78, "avgEcpm": 1.23, "lastChecked": "2026-05-11T09:00:00Z" } ] }

ads.txt Auto-Generation (API):

bash GET /ads/ads-txt

Response:

google.com, pub-1234567890123456, DIRECT, f08c47fec1f5a0 amazon.com, pub-1234567890123456, RESELLER, amzn-ssp-advertising

SPA/SSR Support: For Single Page Apps, add <meta name="google-adsense-account" content="pub-1234567890"> to <head>. For SSR, serve from /ads.txt endpoint.

3

Create a Direct-Sold Campaign

ModelRate UnitDescription
`cpm`$/1,000 impressionsCost per thousand impressions
`cpc`$/clickCost per click
`cpa`$/conversionCost per conversion action
`flat`$/day or $/monthFlat-rate guaranteed delivery
4

Approve & Launch

Approve Creative (API):

bash POST /ads/creatives/{creativeId}/approve { "reviewNotes": "Looks good" // optional }

Approve Campaign (API):

bash POST /ads/campaigns/{campaignId}/approve

Response:

typescript { "id": "campaign-xxx", "status": "active", "startDate": "2026-05-15", "endDate": "2026-06-15", "pacing": "even" }

Manage Campaign Status (API):

```bash # Pause a running campaign POST /ads/campaigns/{campaignId}/pause

# Resume a paused campaign POST /ads/campaigns/{campaignId}/resume

# Complete a campaign manually POST /ads/campaigns/{campaignId}/complete

# Cancel a campaign (no dedicated action route — update status directly) PATCH /ads/campaigns/{campaignId} { "status": "cancelled" } ```

Status Lifecycle:

draft → scheduled → active → paused → completed ↓ cancelled

Update Campaign Budget (API):

bash PATCH /ads/campaigns/{campaignId} { "budget": 15000, "dailyBudget": 500 }

Update Line Item Targeting (API):

bash PATCH /ads/line-items/{lineItemId} { "targeting": { "countries": ["US", "CA", "GB", "AU"], "devices": ["desktop", "tablet", "mobile"] }, "frequencyCap": 5 }

5

Monitor & Optimize

Go to Ads → Analytics.

Get Dashboard Metrics (API):

bash GET /ads/analytics/dashboard?dateRange=last_30_days

Response:

typescript { "totalImpressions": 1245000, "totalClicks": 18675, "totalRevenue": 3456.78, // dollars "ctr": 1.50, "ecpm": 2.78, "viewabilityRate": 68.5, "totalViewable": 852825 }

Get Zone Metrics (API):

bash GET /ads/analytics/zones?dateRange=last_30_days

Response:

typescript { "zones": [ { "zone": "header-leaderboard", "impressions": 450000, "clicks": 7200, "revenue": 1425.00, "ecpm": 3.17, "ctr": 1.60 }, { "zone": "tech-blog-sidebar", "impressions": 320000, "clicks": 4800, "revenue": 896.00, "ecpm": 2.80, "ctr": 1.50 } ] }

Get Network Metrics (API):

bash GET /ads/analytics/networks?dateRange=last_30_days

Response:

typescript { "networks": [ { "network": "Google AdSense", "impressions": 890000, "clicks": 13400, "revenue": 2345.00, "ecpm": 2.63, "fillRate": 92 }, { "network": "Amazon APS", "impressions": 210000, "clicks": 3150, "revenue": 462.00, "ecpm": 2.20, "fillRate": 78 } ] }

Get Campaign Delivery Report (API):

bash GET /ads/campaigns/{campaignId}/delivery

Response:

typescript { "impressions": 45000, "clicks": 675, "conversions": 23, "ctr": 1.50, "cvr": 3.41, "spend": 382.50, "remainingBudget": 9617.50, "lineItemBreakdown": [ { "lineItemId": "li-xxx", "name": "Tech Blog - Sidebar", "impressions": 45000, "clicks": 675, "spend": 382.50 } ], "dailyDelivery": [ { "date": "2026-05-15", "impressions": 3200, "clicks": 48, "spend": 27.20 }, { "date": "2026-05-16", "impressions": 4100, "clicks": 62, "spend": 34.85 } ] }

Get Pacing Analysis (API):

bash GET /ads/campaigns/{campaignId}/pacing

Response:

typescript { "daysElapsed": 5, "daysRemaining": 25, "totalDays": 30, "expectedDelivery": 16.67, // % of budget expected spent "actualDelivery": 14.80, // % of budget actually spent "paceStatus": "under_delivering", "adjustmentNeeded": 187.00 // Need to spend $187 more to get on track }

Run Waterfall Optimization (AI) (API):

bash POST /ads/analytics/optimize/waterfall/{zoneId}

Response:

typescript { "previousOrder": ["google", "amazon", "taboola"], "newOrder": ["amazon", "google", "taboola"], "estimatedRevenueIncrease": 12.5 // % increase from reordering }

Run A/B Test for Creatives (API):

bash POST /ads/analytics/optimize/ab-test/{lineItemId}

Response:

typescript { "status": "testing", "creatives": [ { "creativeId": "creative-xxx", "impressions": 15000, "clicks": 300, "ctr": 2.00, "confidence": 91 }, { "creativeId": "creative-yyy", "impressions": 14800, "clicks": 222, "ctr": 1.50, "confidence": 88 } ], "winner": { "creativeId": "creative-xxx", "ctr": 2.00, "improvementPct": 33.3 // 33.3% better CTR than loser } }

Auto-pause low-CTR creatives + smart pacing run automatically as part of daily optimization — there's no standalone per-creative or per-campaign endpoint for them. Trigger the full daily pass on demand (it also reorders every active zone's waterfall):

bash POST /ads/analytics/optimize/run-daily

Response:

typescript { "waterfallsOptimized": 4, "creativesPaused": 2, // low-CTR creatives auto-paused this run "campaignsPaced": 6 // active campaigns re-evaluated for pacing }

Auto-pause reasoning (e.g. "CTR 0.08% below 0.1% threshold after 5000 impressions") and per-campaign pacing detail (current vs. target pace, recommended adjustment) show up in the admin's optimization log — Admin → Ads → Optimization.

Quick Reference

Zone API:

```bash # Create zone POST /ads/zones

# List zones GET /ads/zones

# Update waterfall PATCH /ads/zones/{zoneId}

# Network health GET /ads/adapters/health

# ads.txt GET /ads/ads-txt ```

Campaign API:

```bash # Create campaign POST /ads/campaigns

# Approve campaign POST /ads/campaigns/{campaignId}/approve

# Pause/resume/complete POST /ads/campaigns/{campaignId}/pause POST /ads/campaigns/{campaignId}/resume POST /ads/campaigns/{campaignId}/complete

# Update budget, or cancel via status PATCH /ads/campaigns/{campaignId}

# Get delivery report GET /ads/campaigns/{campaignId}/delivery

# Get pacing analysis GET /ads/campaigns/{campaignId}/pacing ```

Line Item API:

```bash # Create line item POST /ads/campaigns/{campaignId}/line-items

# Update targeting PATCH /ads/line-items/{lineItemId} ```

Creative API:

```bash # Upload creative POST /ads/creatives

# Approve/reject POST /ads/creatives/{creativeId}/approve POST /ads/creatives/{creativeId}/reject

# Preview rendered creative GET /ads/creatives/{creativeId}/preview ```

Network API:

```bash # Connect network POST /ads/networks

# List networks GET /ads/networks

# Update config PATCH /ads/networks/{networkId} ```

Analytics API:

```bash # Dashboard metrics GET /ads/analytics/dashboard?dateRange=last_30_days

# Zone metrics GET /ads/analytics/zones

# Network metrics GET /ads/analytics/networks

# Hourly breakdown GET /ads/analytics/hourly?dateRange=today

# Daily trend GET /ads/analytics/daily-trend?dateRange=last_7_days ```

Optimization API:

```bash # Waterfall optimization POST /ads/analytics/optimize/waterfall/{zoneId}

# A/B test POST /ads/analytics/optimize/ab-test/{lineItemId}

# Daily orchestration (waterfall reorder + auto-pause + smart pacing) POST /ads/analytics/optimize/run-daily ```

Advertiser API:

```bash # Create advertiser POST /ads/advertisers

# List advertisers GET /ads/advertisers

# Billing / statement GET /ads/advertisers/{advertiserId}/billing ```

FAQ

Every request checks sources in order: (1) direct-sold campaigns → (2) your connected network waterfall (ranked by real yield) → (3) house ads → (4) fallback HTML. Impression recording happens in the background so it never slows down the ad itself.

Aeion runs a statistically rigorous chi-square significance test on your creatives automatically. A difference is called out once it's statistically significant — no manual math, no exported spreadsheets. Minimum 1,000 impressions before evaluation.

Networks are ranked by real earning potential, not just headline eCPM. A network with a high eCPM but near-zero fill gets penalized, while a network with a lower eCPM but strong fill rate ranks higher — e.g., a $2 eCPM network at 80% fill outranks a $5 eCPM network at 2% fill.

Every impression is scored across multiple signals — VPN/proxy traffic, bot user agents, missing referrers, suspicious click patterns — and blocked automatically before it's ever billed if it crosses a safe risk threshold.

Per-user impression limit over a configurable window. e.g., a cap of 5 with a 24-hour window means a given visitor sees at most 5 impressions of that ad per day. Applies per line item.

Aeion continuously compares how much of your budget you've spent to how much of the flight has elapsed. If you're falling meaningfully behind pace, it recommends a budget increase; if you're running meaningfully ahead, it recommends dialing back.

`300x250`, `728x90`, `160x600`, `300x600`, `320x50`, `300x50`, `native`, custom. Image, video, HTML, and native creative types.

Multiple creatives per line item → weighted random. Higher weight = higher probability of selection. e.g., weights [60, 40] → 60% chance of first creative.

CPM (cost per 1,000 impressions), CPC (cost per click), CPA (cost per conversion), flat (per day/month). Revenue is calculated automatically based on whichever model you choose.

Aeion won't let you launch a new campaign for an advertiser account that's been suspended or closed — checked automatically at campaign creation.

Total impressions, clicks, and revenue, plus CTR, eCPM, and viewability rate — broken down by zone, network, campaign, page, and time (hourly/daily buckets).

Aeion reads your connected network credentials and keeps your ads.txt file automatically up to date in the standard format ad networks expect. SPA via meta tag, SSR via `/ads.txt` endpoint.

Aeion checks the visitor's consent status before serving personalized ads. Consent states: Personalized, Contextual, Limited. Right to erasure anonymizes impression records. Configurable data retention period.

Every impression and conversion is recorded to an append-only history — nothing is edited or deleted after the fact, so your reporting and any advertiser audit trail stay trustworthy.

Open the Ads Dashboard