# Ad-Preflight - full documentation > Validate, fix, and package HTML5 ad creatives before uploading to ad platforms. This file contains every guide from https://ad-preflight.com/docs, inlined for machine reading. A short summary lives at https://ad-preflight.com/llms.txt. Install: `npx @ad-preflight/cli` - works with a local install, a global install, or none. Plans, pricing, machine limits and trial terms are on https://ad-preflight.com and change; do not quote figures from this file. --- # CLI guide Validate, fix, and package HTML5 ad creatives from the terminal - catch issues before they cause rejections on any platform. **Supported platforms:** Google Ads · DV360 · Doubleclick · Sizmek · Adform · any IAB-standard HTML5 ad platform **See also:** [Deep Audit (Pro)](https://ad-preflight.com/docs/deep-audit) for runtime checks in a real browser · [CI/CD guide](https://ad-preflight.com/docs/ci-cd) for pipelines · [MCP setup](https://ad-preflight.com/docs/mcp) for Cursor and AI agents --- ## Installation **Global (recommended):** ```bash npm install -g @ad-preflight/cli ad-preflight --help ``` **Project dependency:** ```bash npm install --save-dev @ad-preflight/cli npx @ad-preflight/cli package ./ad ``` All examples below use `npx @ad-preflight/cli` - it works with either install (and even with none: npx fetches the package). With a global install, plain `ad-preflight` works too. --- ## Commands | Command | What it does | |---------|-------------| | `npx @ad-preflight/cli package ` | Validate and package an ad creative into an upload-ready ZIP | | `npx @ad-preflight/cli preview ` | Open the ad in a local publisher-style page (test layout, z-index, click-through) | | `npx @ad-preflight/cli init-rules` | Add agent instructions (`AGENTS.md`, Cursor rules) so AI agents know to validate ads with ad-preflight | | `npx @ad-preflight/cli buy` | Show how to buy the Pro Deep Audit plugin | | `npx @ad-preflight/cli trial ` | Start the free Deep Audit trial (get the token at https://ad-preflight.com) | | `npx @ad-preflight/cli plugin-install ` | Install the Deep Audit plugin with your purchase token - see [Deep Audit](https://ad-preflight.com/docs/deep-audit) | | `npx @ad-preflight/cli plugin-uninstall` | Remove the plugin and release this machine's seat | | `npx @ad-preflight/cli license` | Show the license installed on this machine (`--refresh` to renew) | | `npx @ad-preflight/cli recover-license ` | Email your purchase token to the address you bought with | | `npx @ad-preflight/cli mcp` | Start the MCP server (stdio) for Cursor and other MCP clients | --- ## Package command ```bash npx @ad-preflight/cli package [options] ``` This is the core command. It validates the ad creative, reports issues, and produces a platform-ready ZIP. ### Options | Flag | Description | |------|-------------| | `--fix` | Auto-fix issues (click handler, HTTPS, ad.size meta). Backs up originals to `{folder}_original.zip` | | `--type ` | Ad type: `standard` (default), `amp`, `app` | | `--strict-dimensions` | Fail on non-IAB dimensions (default: warn only) | | `--deep` | Run the ad in a headless browser: JS errors, CPU, network, visual, animation and behavior checks (Pro - see [Deep Audit](https://ad-preflight.com/docs/deep-audit)) | | `--report [file]` | With `--deep`: write a self-contained PDF report you can share with adops (default name: `ad-preflight-.pdf`) | | `--out ` | Where the `.zip` files go. Defaults to the folder containing the creative - for a multi-size campaign, that means one archive per size, next to the campaign | | `--nopreview` | Skip opening the browser after packaging | | `--json [format]` | Machine-readable JSON output. Use `--json=pretty` for formatted output. See [CI/CD guide](https://ad-preflight.com/docs/ci-cd) | | `-h, --help` | Show help | ### How `--fix` works 1. Zips the folder as-is to `{folder}_original.zip` (your backup) 2. Applies fixes on disk (injects click handler, ad.size meta, converts HTTP to HTTPS) 3. Zips the fixed result as `compliance_{folder}.zip` (upload-ready) You keep the backup. The compliance ZIP is what you upload. --- ## Examples | Goal | Command | |------|---------| | Validate only | `npx @ad-preflight/cli package ./my-ad` | | Validate and auto-fix | `npx @ad-preflight/cli package ./my-ad --fix` | | AMP ad | `npx @ad-preflight/cli package ./amp-ad --type amp --fix` | | App campaign | `npx @ad-preflight/cli package ./app-ad --type app` | | Strict IAB dimensions | `npx @ad-preflight/cli package ./my-ad --strict-dimensions` | | Deep validation (Pro) | `npx @ad-preflight/cli package ./my-ad --deep` | | Deep validation + PDF report | `npx @ad-preflight/cli package ./my-ad --deep --report` | | JSON output for scripts | `npx @ad-preflight/cli package ./my-ad --json` | | Skip browser preview | `npx @ad-preflight/cli package ./my-ad --fix --nopreview` | --- ## Local preview Test your ad in a publisher-style page before uploading - check layout, z-index stacking, and click-through behavior: ```bash npx @ad-preflight/cli preview ./my-ad npx @ad-preflight/cli preview ./my-ad --port 8080 # custom port (default: 3750) ``` Opens a local browser page that mimics how the ad will appear on a publisher site. Multi-size campaigns are detected automatically - every size gets an entry in the preview. --- ## Pro features The Deep Audit runs your ad in a real headless browser and reports what the standard audit can't catch: runtime JavaScript errors, CPU on pace for Google's Heavy Ad Intervention, network problems, blank renders, slot overflow, animation-limit violations, and auto-redirects. Multi-size packs get one rolled-up report, and `--report` produces a shareable PDF scorecard. ```bash npx @ad-preflight/cli package ./my-ad --deep # Requires the Pro plugin ``` **Try it free:** get a trial token at https://ad-preflight.com, then: ```bash npx @ad-preflight/cli trial ``` **License management:** ```bash npx @ad-preflight/cli buy # How to buy npx @ad-preflight/cli plugin-install # Install the plugin on this machine npx @ad-preflight/cli license # Check status (--refresh to renew) npx @ad-preflight/cli recover-license # Lost your token? Get it emailed npx @ad-preflight/cli plugin-uninstall # Remove and free this machine's seat ``` Plans, pricing and machine limits: https://ad-preflight.com. Core features remain free forever. **Full guide: [Deep Audit (Pro)](https://ad-preflight.com/docs/deep-audit)** - what it checks, where to buy, installation, and troubleshooting. --- # Deep Audit (Pro) Run your creative in a real browser before adops uploads it - and catch the rejections the standard audit can't see: runtime errors, heavy CPU, oversized loads, blank renders, and policy violations like endless animations or missing borders. **Your creative never leaves your machine.** The audit runs in a local headless browser - nothing about the creative is uploaded anywhere. **See also:** [CLI guide](https://ad-preflight.com/docs/cli) for the free checks · [CI/CD guide](https://ad-preflight.com/docs/ci-cd) for pipelines --- ## What it checks The Deep Audit loads your ad in a headless Chrome, watches it like a real device would, and grades every size against platform rules (Google display rules by default): | Check | What you find out | |---|---| | **JavaScript errors** | Uncaught errors and console errors, with the exact `file.js:line` - the #1 cause of ads that render blank after upload | | **CPU usage** | Whether your ad is on pace for **Google Heavy Ad Intervention** (Chrome silently unloads heavy ads). Measured at 4x CPU throttle, so results reflect low-end devices, not your dev machine | | **Long tasks** | Main-thread blocking over 50ms - the jank that publishers complain about | | **Network behavior** | Full request waterfall: insecure `http://` calls, broken assets (404s), failed requests, and your **initial load vs subload** split against the 150 KB budget | | **Visual render** | A screenshot of every size, plus automatic detection of **blank renders**, content **overflowing the ad slot**, and **missing borders** on white backgrounds (a Google requirement) | | **Animation limits** | Animations that loop forever or run past Google's **30-second limit** | | **Behavior** | Auto-redirects and popups fired without a user click - instant rejection (and advertiser blocklisting) on every major platform | Every issue comes with a **suggested fix**, written for creative developers. ### Multi-size packs Point it at one folder containing your size variants and get a single report: ``` my-campaign/ ├── 300x250/index.html ├── 728x90/index.html └── 160x600/index.html ``` Each size is audited separately and rolled up into one pass/fail summary. --- ## Try it free Get a **trial token** at **[ad-preflight.com](https://ad-preflight.com)** - it arrives by email. Then activate it on this machine: ```bash npx @ad-preflight/cli trial ``` Trial audits produce a watermarked report and cover one creative size per run. The current limits and terms are on the site. --- ## Where to buy 1. Go to **[ad-preflight.com](https://ad-preflight.com)** and choose a plan - plans, pricing and machine limits are listed there. 2. After checkout you receive a **purchase token** on the confirmation page. **Save it** - it's your proof of purchase, and you'll reuse it to install on a new machine or after a Node upgrade. Lost it? `npx @ad-preflight/cli recover-license ` emails it back. --- ## How to install **Requirements:** Node.js 22 or 24, and an internet connection for the one-time install (the plugin downloads a dedicated headless Chrome, ~300 MB - allow a few minutes). ```bash npx @ad-preflight/cli plugin-install ``` The installer activates your license for this machine, downloads the plugin and browser, and self-tests the setup. When you see **"Plugin installed and verified"** you're done. **Good to know:** - Reinstalling on the same machine doesn't use an extra activation, and `plugin-uninstall` hands the slot back so you can move it to another machine. - If you upgrade Node to a different major version (e.g. 22 → 24), just run `plugin-install` again with the same token. - `npx @ad-preflight/cli license` shows what's installed on this machine at any time. --- ## How to use ### Validate a creative ```bash npx @ad-preflight/cli package ./my-ad --deep ``` The standard audit runs first (same as the free checks), then the deep audit loads every size in the browser. You get a per-size scorecard: ``` PASS 300x250 (300x250) ✓ JavaScript errors no runtime errors ✓ Long tasks main thread never blocked >50ms ✓ CPU usage avg 5.9% · peak 32.2% @4x throttle ✓ Network 1 request(s) · 0.7 KB · first paint 124ms ✓ Visual renders correctly in slot ✓ Animation static or completed within window ✓ Behavior no auto-redirects or popups ``` When something is wrong, the finding tells you what, where, and how to fix it: ``` FAIL 300x250 (300x250) ✗ [js-errors] Uncaught error - renderCampaign is not defined (script.js:13:1) ↳ Fix: Define or load the referenced symbol before it runs (check script order/timing) or guard the call. Uncaught errors typically make the ad render blank on the platform. ``` ### Shareable PDF report ```bash npx @ad-preflight/cli package ./my-ad --deep --report ``` Writes `ad-preflight-my-ad.pdf` (named after the creative folder) - a single self-contained file with the overall verdict, every size's scorecard, screenshots, and all findings with fixes. Send it to adops or attach it to the campaign ticket; it opens anywhere, no tools required. (Use `--report my-report.pdf` to pick the filename.) ### CI/CD ```bash npx @ad-preflight/cli package ./my-ad --deep --json ``` Outputs the full result as JSON and sets the exit code from the audit: **0** when everything passes (warnings allowed), **1** when any size has a blocking issue - so your pipeline fails before a broken creative reaches trafficking. Exit **1** also covers a licence that refuses to run the audit, and exit **2** means the plugin isn't installed on the runner. See the [CI/CD guide](https://ad-preflight.com/docs/ci-cd). ### Ad types By default creatives are audited against **Google display** rules. Use `--type amp` or `--type app` for AMPHTML ads and App campaign assets - size budgets adjust accordingly. --- ## Reading the results | Status | Meaning | |---|---| | **PASS** | Ready for upload - all checks green for this size | | **WARN** | Uploadable, but review the warnings - they're the things reviewers and publishers notice | | **FAIL** | Fix before upload - at least one issue that causes rejection or breakage in the wild | The pack summary rolls all sizes together: one FAIL anywhere fails the run. --- ## Troubleshooting | Message | What to do | |---|---| | `Deep Audit requires the Pro plugin (not installed)` | Run `npx @ad-preflight/cli plugin-install ` - get a trial or purchase token at [ad-preflight.com](https://ad-preflight.com) | | `Unsupported Node major` | Switch to a supported Node version (`nvm use 22` or `nvm use 24`) and re-run `plugin-install` | | Plugin built for a different Node major | You upgraded Node - re-run `plugin-install` with your token to get the matching build | | The headless browser did not finish downloading | The ~300 MB Chromium download was interrupted; the message prints the exact `npx playwright install chromium` command to finish it, then re-run `plugin-install` | | `MACHINE_LIMIT` during install | Your plan's activations are used up - free one with `plugin-uninstall` on a machine you no longer use, or move up a plan | | `active - needs to reconnect` on `license` | Connect this machine to the internet and run `npx @ad-preflight/cli license --refresh` | | Deep audit skipped - standard audit failed | Fix the listed issues first (or run with `--fix`), then re-run `--deep` | | The licensing server is unavailable | A temporary server problem - your installed licence keeps working; try the command again later | --- ## FAQ **Does my creative get uploaded for validation?** No. The audit runs entirely on your machine in a local headless browser. Nothing about your creative leaves your computer. **Why do the CPU numbers look higher than my machine's task manager?** The audit deliberately runs at 4x CPU throttle to emulate the low-end devices where Google's Heavy Ad Intervention actually triggers. An ad that looks fine on a dev machine can still be unloaded on a budget phone - this is the number that matters. **Do I need to be online to validate?** The audit itself runs on your machine. (If your creative references external assets, those are fetched during the audit like a real impression would.) Trial audits need a connection every run. **How long does an audit take?** Roughly 5–10 seconds per size, since each size gets a full load, settle, and measurement window in the browser. --- # CI/CD guide Catch broken ad creatives in your pipeline - before they reach any ad platform. ad-preflight validates against IAB standards and platform requirements (Google Ads, DV360, Sizmek, Adform, and more), outputs machine-readable JSON, and uses standard exit codes. **See also:** [CLI guide](https://ad-preflight.com/docs/cli) for full command reference · [Deep Audit (Pro)](https://ad-preflight.com/docs/deep-audit) for `--deep` in pipelines · [MCP setup](https://ad-preflight.com/docs/mcp) for Cursor and AI agents --- ## Install in CI **As a dev dependency (recommended - locked version):** ```bash npm install --save-dev @ad-preflight/cli ``` **Or run with npx (no install needed):** ```bash npx -y @ad-preflight/cli package ./ad --json ``` --- ## Machine mode In machine mode, ad-preflight writes **exactly one JSON object** to stdout - no banners, no progress bars, no tips. Use the exit code for pass/fail. Machine mode activates automatically when: - You pass `--json` or `--json=pretty` - stdout is not a TTY (pipes, CI runners, headless environments) --- ## Exit codes | Code | Meaning | Action | |------|---------|--------| | **0** | Validation passed, ZIP created | Continue pipeline | | **1** | Validation failed, Deep Audit failed, or runtime error | Fail the build | | **2** | Invalid arguments or setup problem (e.g. `--deep` without the plugin installed, unsupported Node major) | Fix the command / finish setup | | **3** | Licensing: system not supported, trial already used, or license no longer active | Needs a human - see the message | Code **3** comes from the setup commands (`plugin-install`, `trial`). `package` itself only ever exits 0, 1 or 2 - a licence that refuses the Deep Audit fails the run as exit **1**. > **Multi-size campaigns:** a size that fails validation is skipped, but the run still exits > **0** if the other sizes packaged. Check `packagesSkipped` in the JSON (and fail the build > yourself if it isn't empty) so a dropped size can't slip through unnoticed. --- ## Non-interactive shells No command hangs waiting for input when there is no terminal: - `package`, `preview` - never prompt. - `plugin-install ` - refuses to **replace** an existing license in a non-interactive shell; pass `--force` when that is intended. - `recover-license ` - the email must be passed as an argument (exits 2 otherwise). - `trial ` - the token is required; request it at https://ad-preflight.com first. --- ## JSON output **Success** (exit 0): ```json { "success": true, "outputPath": "compliance_my-ad.zip", "size": 12345, "type": "standard", "warnings": [], "fixLogs": [], "staticChecks": [ { "id": "clicktag", "label": "Click handler", "status": "pass" } ], "staticChecksBySize": { "...": [] }, "packages": [ { "name": "my-ad", "outputPath": "compliance_my-ad.zip", "size": 12345 } ] } ``` Notes for parsers: - **Collect artifacts from `packages`, not from `outputPath`.** For a multi-size campaign there is one entry per size; top-level `outputPath`/`size` describe only the first ZIP. Sizes that failed validation appear in `packagesSkipped` instead. - `originalZipPath` is present only when `--fix` ran (path of the pre-fix backup ZIP). - `deep` is present only when `--deep` ran (the Deep Audit report object). - `staticChecks` / `staticChecksBySize` feed the human report checklist - safe to ignore in CI. **Failure** (exit 1): ```json { "success": false, "issues": ["Missing var clickTag", "HTTP resource detected"], "warnings": [], "error": "Validation failed: 2 issues found" } ``` Check `result.success === true` and exit code `0` to confirm a pass. --- ## Pipeline examples ### Simple - fail on non-zero exit ```bash npx -y @ad-preflight/cli package ./ad --json # Exit code 0 = pass. That's it. ``` ### Shell script - capture output ```bash #!/bin/sh set -e npx -y @ad-preflight/cli package ./ad --json > result.json echo "Ad validation passed" ``` ### GitHub Actions ```yaml - name: Validate ad creative run: npx -y @ad-preflight/cli package ./ad --json > result.json - name: Check result run: | if [ "$(jq -r .success result.json)" != "true" ]; then echo "::error::Ad validation failed" jq . result.json exit 1 fi ``` ### GitLab CI ```yaml validate-ad: script: - npx -y @ad-preflight/cli package ./ad --json > result.json artifacts: paths: - result.json when: always ``` ### With auto-fix in CI ```bash npx -y @ad-preflight/cli package ./ad --fix --json > result.json # Produces compliance_ad.zip (fixed) and ad_original.zip (backup) # Upload compliance_ad.zip as your build artifact ``` --- ## Options reference All [CLI options](https://ad-preflight.com/docs/cli) work in machine mode. Common CI flags: | Flag | Use in CI | |------|-----------| | `--json` | Machine-readable output (default: compact) | | `--json=pretty` | Pretty-printed JSON (easier to read in logs) | | `--fix` | Auto-fix issues and produce upload-ready ZIP | | `--type amp` | Validate as AMP ad (600KB limit) | | `--strict-dimensions` | Fail on non-IAB dimensions instead of warning | | `--deep` | Headless browser validation (Pro license required) | --- # MCP setup Let AI agents validate and fix HTML5 ad creatives without leaving the editor. ad-preflight runs as an MCP server in Cursor (or any MCP-compatible client), validating against IAB standards and platform requirements for Google Ads, DV360, Sizmek, Adform, and more. **See also:** [CLI guide](https://ad-preflight.com/docs/cli) for full command reference · [CI/CD guide](https://ad-preflight.com/docs/ci-cd) for pipelines · [Deep Audit (Pro)](https://ad-preflight.com/docs/deep-audit) for runtime checks --- ## How it works - Exposes one tool: **`validate_ad_creative`** - validates and optionally auto-fixes an HTML5 ad creative - Also registers two prompts (`analyze_ad`, `fix_ad`) and three reference resources (platform specifications, file size limits, allowed file types) - your MCP client lists them alongside the tool - Runs over stdio - Cursor starts it on demand, no separate server process - Same validation rules as the CLI: click handlers (clickTag, Enabler API, Exit API), ad.size meta, HTTPS, file types, size limits, IAB dimensions --- ## Configuration Add ad-preflight to your MCP config: `.cursor/mcp.json` (project-level) or `~/.cursor/mcp.json` (global). ### Recommended (npx) Works whether the package is installed locally or not: ```json { "mcpServers": { "ad-preflight": { "command": "npx", "args": ["-y", "@ad-preflight/cli", "mcp"] } } } ``` ### Alternative (explicit path) Use when you prefer a fixed install path or want to avoid npx: ```json { "mcpServers": { "ad-preflight": { "command": "node", "args": ["node_modules/@ad-preflight/cli/dist/mcp-server.js"] } } } ``` **Restart Cursor after changing the config.** --- ## Tool: `validate_ad_creative` Validates and packages an HTML5 ad creative according to platform specs. | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | `folderPath` | string | yes | - | Absolute path to the creative folder - a single creative, or a campaign folder with one subfolder per size | | `type` | string | no | `"standard"` | Ad type: `standard`, `amp`, or `app` | | `fix` | boolean | no | `false` | Auto-fix issues (inject ClickTag, HTTPS, ad.size). Rewrites the creative in place and backs the original up to `_original.zip` | | `strictDimensions` | boolean | no | `false` | Fail when the ad size is not an IAB standard dimension (default: warn only) | ### What the agent sees The tool returns a structured result the agent can act on: | Field | Meaning | |---|---| | `success` | `false` means the creative must not be uploaded | | `issues` | Blocking problems that made validation fail | | `warnings` | Non-blocking problems worth reviewing | | `fixLogs` | What was changed when `fix` was `true` | | `packages` | Every ZIP produced - one entry per size for a multi-size campaign | | `packagesSkipped` | Sizes that failed validation and produced no ZIP | | `originalZipPath` | Backup of the pre-fix creative (only when `fix` was `true`) | | `logs` | Progress messages from the run | A creative that fails validation is a normal answer, not a tool error: the agent gets `success: false` plus the findings. Tool errors are reserved for runs that can't produce a verdict at all (for example, the folder doesn't exist). --- ## Example prompts Once MCP is configured, ask the agent naturally: | Prompt | What happens | |--------|-------------| | "Validate this ad creative" | Runs validation only (`fix: false`) | | "Check and fix issues in this ad" | Validates and auto-fixes (`fix: true`) | | "Validate this AMP ad" | Validates with `type: "amp"` | | "Validate every size in this campaign" | Validates each size subfolder and reports which ones passed | | "Is this ad ready for Google Ads?" | Validates against platform requirements | The agent calls `validate_ad_creative` with the appropriate parameters based on your prompt. --- ## Agent suggestions (optional) Write agent instructions into your project so agents recognise HTML5 ad creatives and know to validate them: ```bash npx @ad-preflight/cli init-rules ``` It writes three files, because no single format is read everywhere: | File | Read by | |---|---| | `AGENTS.md` | the cross-tool convention most agent CLIs and IDEs look for | | `.cursor/rules/ad-preflight.mdc` | current Cursor | | `.cursorrules` | older Cursor versions (legacy) | Existing files are left alone; pass `--force` to overwrite. This adds project-level instructions only - you still need the MCP config above for the tool itself to work. --- ## Troubleshooting | Problem | Solution | |---------|----------| | Tool not appearing in Cursor | Restart Cursor after editing `.cursor/mcp.json` | | Wrong path error (node variant) | Verify the path to `mcp-server.js` is correct from your project root. Use the npx config to avoid path issues | | Want CLI fallback instead | Run `npx @ad-preflight/cli package ./ad --json` and parse the output. See [CI/CD guide](https://ad-preflight.com/docs/ci-cd) |