By Vicente Arteaga Gomez
MisLinux
This is part of my Kubernetes-on-Hetzner-and-operations series on MisLinux. It comes from building a real publisher-onboarding pipeline in production, not from a vendor playbook.
Onboarding a new publisher used to mean a long checklist in someone's head:
- Create ad units in the ad server
- Wire demand and pricing floors
- Register the child network and seller ID
- Stand up a revenue dashboard spreadsheet
- Confirm
ads.txtandsellers.json - Create intranet publisher, sites, wrappers, and contracts
- Send tags to the publisher
Each step touched a different system. Each step had a different tool. And "done" meant different things to different people.
I fixed that by treating onboarding as declarative desired state.
The core idea
One YAML file describes what "fully onboarded" means for a publisher:
publisher: Example Media Co
gam:
parent_network: "12345678901"
child_network: "98765432"
seller_id: pub-example-001
sites:
- domain: example-news.com
display_use_domain: true
tags:
parent_network: "12345678901"
communication_language: en
stats:
expect_adunits:
- Example_news.com-320x50_Display
- Example_news.com-728x90_Display
- Example_news.com-PR1_Video
readiness:
wrappers:
- uuid: abc123def456-d
lineitems:
- name: AdExchange Example Video
Then one orchestrator command compares live state against that manifest:
php onboard.php --config=manifests/example-publisher.onboard.yaml --plan
php onboard.php --config=manifests/example-publisher.onboard.yaml --apply=pcontrol --confirm
php onboard.php --config=manifests/example-publisher.onboard.yaml --apply=all --confirm
--plan is read-only. It prints OK, MISSING, WRONG, or EXTERNAL for every step.
--apply mutates only the steps that are safe to automate. Everything else stays a explicit human gate.
That split is the whole safety model.
Why manifests beat ad-hoc scripts
| Ad-hoc approach | Manifest approach |
|---|---|
| "Run these twelve commands in order" | One file defines end state |
| Hard to see what is still missing | --plan is a live diff |
| Every new publisher copies paste errors | New publisher = new YAML |
| Monitoring is an afterthought | Checks reuse the same manifest |
The manifest is not magic. It is the contract that scripts, tests, and monitoring all read.
What one onboarding manifest covers
In my pipeline, a full publisher touches roughly nine areas:
| Area | Manifest expresses | Automation level |
|---|---|---|
| GAM inventory | Ad unit names, sizes, tiers | Apply where API is safe |
| AdExchange demand | Line item names + targeted units | Partial — creative activation may be UI-only |
| Placement membership | Union into shared placement | Apply with idempotent sync |
| UPR floors | Expected floor levels vs wrapper | Check against daily export |
| MCM child / seller ID | Network codes + seller id | Read-only verify |
| Revenue dashboard | Report IDs + sheet templates | Seed + management rows |
| ads.txt / sellers.json | Exact lines expected per domain | HTTP fetch + match |
| Intranet objects | Company, network, sites, wrappers | DB read checks + controlled writes |
| Publisher comms | Tag email EN/ES artifacts | Generated from manifest inputs |
Some steps are fully automated. Some are assisted (human in GAM UI, machine verifies after). The manifest makes that honest instead of pretending everything is one button.
Checks that can hook into monitoring
The same readiness config powers a daily cron:
php publisher-readiness-check.php --config=manifests/example-publisher.onboard.yaml --json
Gates include:
- Wrapper serves VAST with expected ad unit in the tag
- Line items are active and target the right inventory
- Control panel rows exist with correct metric flags
- Live
ads.txtcontains the expected DIRECT/RESELLER lines - GAM inventory count matches expectation
When a gate fails, Telegram gets an incident message. When everything is green, silence.
That is the monitoring story the operator asked for: detect activity and detect missing setup, not spam on success.
Detecting "onboarding is working" via traffic
Separate mode: day-by-day ad request stats per ad unit:
php onboard.php --config=manifests/example-publisher.onboard.yaml --stats=14
This answers: "We onboarded ten ad units — which ones are actually receiving requests?"
A roster unit with zero requests is not always failure (publisher has not deployed yet). But once wrapper traffic exists and GAM requests stay zero, the funnel check localizes the break:
php onboard.php --config=manifests/example-publisher.onboard.yaml --funnel --days=7
Wrapper requests → GAM ad unit requests → dashboard revenue. The hop where upstream is non-zero and downstream is zero names the broken layer.
AI's role: build the procedure, not wing the production click
I use AI agents to author and harden the onboarding tooling:
- Generate check libraries and PHPUnit tests
- Record CIR notes when GAM API quirks block automation
- Produce diff output (
--diff) that shows field-level expected vs actual
I do not use AI to "just click through GAM" on economically loaded pricing rules without guardrails.
The manifest makes AI useful because the desired state is explicit. The agent is not guessing what "done" means.
What I would not put in a manifest
Keep human gates visible:
- Creating UPR rules that set global floors (no public API — browser workflow with confirm tokens)
- First-time publisher legal review
- Publisher-side
ads.txtedits (we verify, they publish)
Trying to hide those behind --apply=all would create false confidence.
Reusable decision rules
- If it is read-only, automate the check first. Production mutation comes later.
- If two systems must agree (intranet DB vs UI), verify both. One path lies sometimes.
- If a step is EXTERNAL, say so in `--plan`. Do not mark WRONG when waiting on the publisher.
- Store proof artifacts next to the manifest run (
history/onboarding-emails/..., activation proof JSON).
Closing thought
Publisher onboarding is a business process disguised as nine technical chores.
YAML manifests do not remove the chores. They make desired state portable, testable, and monitorable — which is what lets AI help without turning production into a roulette wheel.
---
Scope note: Examples use fictional publisher, domain, and network identifiers. The pattern reflects MCM-style ad-ops workflows from my production environment; it is not a case study of any live customer.