Pages

Tuesday, June 16, 2026

Publisher Onboarding as Manifests: How I Automate Ad Server, ads.txt, and Intranet Setup with YAML

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.txt and sellers.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 approachManifest 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 errorsNew publisher = new YAML
Monitoring is an afterthoughtChecks 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:

AreaManifest expressesAutomation level
GAM inventoryAd unit names, sizes, tiersApply where API is safe
AdExchange demandLine item names + targeted unitsPartial — creative activation may be UI-only
Placement membershipUnion into shared placementApply with idempotent sync
UPR floorsExpected floor levels vs wrapperCheck against daily export
MCM child / seller IDNetwork codes + seller idRead-only verify
Revenue dashboardReport IDs + sheet templatesSeed + management rows
ads.txt / sellers.jsonExact lines expected per domainHTTP fetch + match
Intranet objectsCompany, network, sites, wrappersDB read checks + controlled writes
Publisher commsTag email EN/ES artifactsGenerated 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.txt contains 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.txt edits (we verify, they publish)

Trying to hide those behind --apply=all would create false confidence.

Reusable decision rules

  1. If it is read-only, automate the check first. Production mutation comes later.
  2. If two systems must agree (intranet DB vs UI), verify both. One path lies sometimes.
  3. If a step is EXTERNAL, say so in `--plan`. Do not mark WRONG when waiting on the publisher.
  4. 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.