WP Manifestindependent plugin directory
manifest / content / aggressive-ads

Aggressive Ads WP Registry grade A. No security issues foundWP RegistryNo security issues foundOpen the reportA

White-label WordPress advertising platform with campaign workflows, targeting, decision engine, reporting and first-party ad delivery

★ 1stars
17release downloads
v1.5.0latest · 1mo ago

Install

Download aggressive-ads-1.5.0.zip From the v1.5.0 release on GitHub, Aug 29, 2026

Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/theaggressive/aggressive-ads/releases/download/v1.5.0/aggressive-ads-1.5.0.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

Live means live. White-label advertising management for WordPress.

Advertisers build campaigns. Staff review them. Approval publishes. Native fill is the only publisher: there is no AdSanity, no downstream ads CPT, and no theme dependency. Display name and logo are settings; the code prefix is aggr_ forever.

Plugin Aggressive Ads 1.5.0
Slug / text domain aggressive-ads
Namespace Aggressive\Ads
REST aggr/v1
Default UI name Advertising (Brand settings may replace it)
Author The Aggressive, LLC
Repository TheAggressive/Aggressive-Ads

What it does

Advertiser portal at /advertiser/ — its own document, not a page with a block. Sign-in, signup, password setup and recovery are portal-owned; wp-login.php is untouched and is how staff reach wp-admin. Advertisers never enter wp-admin (Admin_Guard). Screens: dashboard, campaigns, six-step wizard, organization, account, help.

Staff admin under one Advertising menu: Review, Organizations, Placements, Packages, Settings. Distinct capabilities; aggr_access_staff is derived, never granted on a role. Placements is the slot catalogue (common IAB sizes or custom W×H). Packages are staff-written; campaigns keep snapshots.

Native delivery is always on, not a Modules checkbox. Editors place aggr/placement (or aggr_placement( 'header-728x90' ) / the shortcode). Cached HTML is a reserved slot. After paint: GET /aggr/v1/fill/{slot}, POST /aggr/v1/i beacon, first-party click hop /ads/c/{token}. Impressions and clicks follow the filled token.

The decision engine picks what fills a slot. An ordered pipeline of pure stages — eligibility, exact schedule and dayparts, targeting, frequency, pacing, priority, weighted selection — and every candidate leaves every stage with a reason, so "why is this ad here?" has an answer. POST /aggr/v1/decisions decides a whole page at once with competitive separation. GET /aggr/v1/placements/{id}/decision returns the decision and its full trace to staff only, replayable from a supplied clock and seed.

Reporting (when the Reporting module is on) reads aggr_rollups: dashboard tiles, a seven-day sparkline, campaign list/detail columns, REST impressions / clicks / ctr. House and other orgs are excluded in SQL. Spend stays absent until billing has a source.

White-label is Brand settings: product name, logo, tagline, contrast-gated --aggr-* tokens. A host theme may override tokens; the portal is fully functional without that.

Status

Built: campaign domain (eleven statuses, 22 legal edges), org-scoped ownership, private creative storage, portal and staff UI, notifications, campaign clock (approved → scheduled → live → complete), assignment-based native fill, the decision engine with targeting, frequency, pacing and priority stages plus staff-only traces, the request-to-conversion measurement model, CSV reporting export, i18n tooling and four locale catalogs, site-scoped tenancy, GitHub updater with SHA-256 verification, Playwright + axe.

Not built, even where docs/ describes the design: spend/billing. If a doc describes something you cannot find, it has not been built.

Requirements

PHP 8.4+
WordPress 6.7+ (tests run 7.1)
Node 24.x
pnpm 11.x (packageManager is 11.1.2)

No runtime Composer packages. vendor/ is dev tooling and never ships. The production autoloader is inc/class-autoloader.php. See build-and-release.md.

Getting started

composer install      # PHPCS, PHPStan, PHPUnit — vendor/ never ships
pnpm install          # frontend tools + staged-file Git hooks
pnpm build            # src/ → dist/
pnpm dev:seed         # an advertiser, an org, and five campaigns
pnpm qa:fast          # Docker-free code quality and unit gate
pnpm qa:local         # qa:fast + the WordPress suites + Studio browser workflows
pnpm qa               # exact containerized CI rehearsal
pnpm qa:fresh         # recreate the environment, then run the same rehearsal

qa:local discovers the Studio site whose wp-content/plugins/aggressive-ads resolves to this checkout, starts it, and runs Playwright against the URL Studio reports for it — never one assembled from a port, which would get the scheme wrong for a site with HTTPS enabled. Set AGGR_STUDIO_PATH=/path/to/site when two sites serve the checkout and the runner asks you to choose, and AGGR_STUDIO_URL when Studio reports no address or you need to override the one it gives.

That site has to opt in before anything runs, because the suite resets the admin and advertiser passwords to match its fixtures and seeds fixture campaigns — and nothing puts either back:

touch /path/to/studio/site/.aggr-e2e-site   # or: AGGR_STUDIO_E2E_ALLOW=1

Theme, permalink structure and the mail-capture mu-plugin are captured up front and restored on the way out, whether Playwright passes or fails.

home and siteurl are the exception: they are set from Studio and left that way. Studio assigns the port and can reassign it, so a URL captured before a run can be stale by the next one — restoring it would put the site back to an address nothing serves. Studio is the source of truth for where a Studio site lives; AGGR_STUDIO_URL overrides it.

Docker Compose remains the reproducible CI environment. It mounts this checkout into the pinned Docker Official WordPress image and starts a disposable MySQL database; local Studio uses SQLite, so MySQL integration, multisite, combined coverage, release-artifact, and forward-PHP checks remain authoritative in GitHub CI and available locally through pnpm qa.

Commands

pnpm lint:php                # PHPCS — WordPress + VIP-Go + PHPCompatibility
pnpm analyse:php             # PHPStan level 8, no baseline
pnpm test:php:unit           # no WordPress, no database
pnpm test:php:integration    # integration / security / rest / upgrade
pnpm test:php:multisite      # colliding-id tenancy
pnpm lint:js                 # ESLint on src/
pnpm typecheck               # tsc --noEmit
pnpm lint:css                # Stylelint on every authored CSS file under src/
pnpm test:js                 # Jest on Interactivity helpers
pnpm lint:files              # file length, boundaries, permission callbacks, client contract
pnpm ci:coverage             # combined unit + integration PCOV coverage
pnpm test:e2e:browsers       # install Chromium and WebKit
pnpm test:e2e:install        # the same, plus system libraries (needs sudo; what CI runs)
pnpm test:e2e                # Playwright + axe (after pnpm build and env:start)
pnpm test:php:native         # the WP suites natively; no Docker, no sudo
pnpm db:local                # start|stop|status|destroy the local test MySQL
pnpm test:e2e:studio         # Playwright + axe against the current Studio site
pnpm qa:fast                 # Docker-free pre-push code and unit checks
pnpm qa:local                # qa:fast + native WP suites + Studio browser workflows
pnpm qa                      # every CI lane, serially; requires a clean worktree
pnpm qa:fresh                # clean database/container rehearsal
pnpm env:stop                # remove the disposable containers and database

Each ci:* script maps 1:1 onto a GitHub Actions job. The local rehearsal derives its commands from that workflow so the two cannot drift.

pnpm install enables the repository's Git hooks. Pre-commit formats and re-stages only selected files, commit-msg enforces Conventional Commits, and pre-push runs pnpm qa:fast, which needs no Docker at all — ShellCheck comes from a checksum-pinned binary in .cache/ci/, the same way the i18n lane gets WP-CLI. Run pnpm qa:local when a change touches a browser workflow. The full pnpm qa rehearsal installs Playwright's browsers but not their system libraries, so it never asks for a password; CI installs those with --with-deps on a bare runner. See build-and-release.md for the CI graph, release artifact chain, and branch-protection contract.

Architecture

aggressive-ads.php                 header, constants, floor guard, hand-off
 └ inc/class-autoloader.php        Aggressive\Ads\X\Y_Z → inc/X/class-y-z.php
 └ inc/class-plugin.php            boot + ordered init_services()
 └ inc/class-service-registrar.php factories — instantiates nothing

Two boundaries fail the build when crossed:

  • inc/Repository/ is the only place data access appears. No WP_Query, get_posts(), get_post_meta(), $wpdb anywhere else in inc/.
  • inc/Domain/ calls no WordPress function. Campaign rules stay unit-testable without a bootstrap.

Start with docs/README.md. Short version:

Doc Covers
architecture.md Layers, native fill, Placements, no downstream ads CPT
domain-model.md Five entities, storage, invariants
campaign-workflow.md The state machine every status write goes through
roles-and-capabilities.md Who may do what
threat-model.md Attack surfaces and the test proving each
platform-p3-decision-engine.md The serving pipeline, its stages and trace contract
roadmap.md What shipped vs remaining product
suite-roadmap.md Suite build order

License

GPL-2.0-or-later.

Releases

9 releases. Each count is every asset in that release; expand a row for the breakdown.

Tag
Published
Assets
Downloads
v1.5.0 latest
Aug 29, 2026 1mo ago
aggressive-ads-1.5.0.zip +1 asset
4
aggressive-ads-1.5.0.zip3
aggressive-ads-1.5.0.zip.sha2561
Aug 23, 2026 2mo ago
aggressive-ads-1.4.0.zip.sha256 +1 asset
4
aggressive-ads-1.4.0.zip.sha2562
aggressive-ads-1.4.0.zip2
Aug 19, 2026 2mo ago
aggressive-ads-1.3.1.zip.sha256 +1 asset
2
aggressive-ads-1.3.1.zip.sha2561
aggressive-ads-1.3.1.zip1
Aug 18, 2026 2mo ago
aggressive-ads-1.3.0.zip.sha256 +1 asset
2
aggressive-ads-1.3.0.zip.sha2561
aggressive-ads-1.3.0.zip1
Aug 18, 2026 2mo ago
aggressive-ads-1.2.1.zip +1 asset
3
aggressive-ads-1.2.1.zip2
aggressive-ads-1.2.1.zip.sha2561
Aug 18, 2026 2mo ago
aggressive-ads-1.2.0.zip.sha256 +1 asset
4
aggressive-ads-1.2.0.zip.sha2562
aggressive-ads-1.2.0.zip2
Aug 17, 2026 2mo ago
aggressive-ads-1.1.1.zip.sha256 +1 asset
6
aggressive-ads-1.1.1.zip.sha2563
aggressive-ads-1.1.1.zip3
Aug 17, 2026 2mo ago
aggressive-ads-1.1.0.zip.sha256 +1 asset
8
aggressive-ads-1.1.0.zip.sha2567
aggressive-ads-1.1.0.zip1
Aug 15, 2026 2mo ago
aggressive-ads-1.0.0.zip.sha256 +1 asset
6
aggressive-ads-1.0.0.zip.sha2564
aggressive-ads-1.0.0.zip2
A grade

Security

Aggressive Ads 1.5.0 · audited by WP Registry

No security issues found.

Audited release
1.5.0
Findings
none
Worst severity
—
Content hash
f61e9f82265dc7e69e6f17fd…

WP Registry hashes the installable build and reports on that exact bytes-for-bytes copy. Embargoed findings are withheld until they are disclosed, so a clean verdict means nothing public is outstanding. WP Manifest does not audit code itself.