Your Ads Are Code. Your Pipeline Is Limitless. CI/CD, image generation, staging accounts, drift detection — all the infrastructure you already have, now for ads.
# .github/workflows/ads.yml
on:
pull_request:
paths: ['campaigns/**']
push:
branches: [main]
paths: ['campaigns/**']
jobs:
plan:
if: github.event_name == 'pull_request'
steps:
- run: ads plan --ci # posts diff as PR comment
apply:
if: github.event_name == 'push'
steps:
- run: ads apply # executes on merge to mainYour engineering team ships features through CI/CD — reviewed, tested, staged, then deployed.
Your ad campaigns are managed in a browser tab. Changes are manual, untracked, and invisible to the rest of your team.
There's no PR, no diff, no approval process. Anyone with access can change anything at any time.
When ads live in code, your entire pipeline — CI, staging, automation, monitoring — becomes available to your ad campaigns.
Add ads to your CI/CD pipeline. When a campaign file changes, `ads plan --ci` posts the diff as a PR comment. Merging to main runs `ads apply`. The same workflow you use to ship software, now for ads.
## Acme Ads — Planned Changes + campaign/q2-launch create + campaign/q2-launch/brand-kw create ~ campaign/retarget/budget $25 → $40/day - campaign/old-winter-promo delete 2 to create · 1 to update · 1 to delete These changes will apply when this PR is merged.
Generate ad creatives programmatically and wire them directly into your campaigns. A script calls an image generation API, saves the assets, and updates the campaign files — all before `ads apply` runs.
import { fal } from '@fal-ai/client'
const images = await fal.subscribe('fal-ai/flux/dev', {
input: { prompt: 'Acme SaaS UI, dark mode, product shot', num_images: 4 },
})
await updateCampaignCreatives('q2-launch', images.map(i => i.url))
await exec('ads plan && ads apply')Run `ads apply --account staging` to apply changes to a test account first. Validate that everything looks right before touching production.
$ ads apply --account staging Creating campaign/q2-launch... ✓ Creating campaign/q2-launch/brand-kw... ✓ Creating campaign/q2-launch/brand-kw/rsa... ✓ Applied 3 changes. Run `ads apply --account production` when ready.
Plan on pull request, apply on merge. The same git workflow you use for code, applied to ad campaigns.
Generate creatives programmatically — fal.ai, DALL-E, Midjourney — and wire them directly into campaign files before apply.
Apply to a test account first. Validate changes before they touch your production campaigns.
Schedule `ads pull` in CI to catch manual UI changes before they cause problems.
Write scripts that adjust budgets based on performance data, season, or business events — then commit and apply.
Hook `ads plan` output into Slack, PagerDuty, or any webhook to get notified when campaigns drift.