007AJ AdPlacer

Documentation for version 1.0.3. Lightweight ad manager with placements, rotation, conditions, accessible popups, local statistics and ads.txt.

Installation

  1. Plugins > Add New > Upload Plugin, choose adplacer-1.0.3.zip, Install, Activate. Requires WordPress 6.3+ and PHP 7.4+.
  2. AdPlacer > Ads: create an ad.
  3. AdPlacer > Slots & Popups: create a slot, choose a placement and tick the ads it shows. Or skip slots and place a single ad with its shortcode, block or widget.

Ads

TypeUse
ImageImage with link, alt text, rel (sponsored / nofollow / noopener / noreferrer) and new-tab option.
CodeHTML/JavaScript for AdSense and other networks. Only users allowed to post unfiltered HTML can save scripts; others are filtered to safe HTML.
Rich textText and HTML from the classic editor.

Each ad's list row shows its shortcode, e.g. [adplacer id="12"], and its viewable impressions / clicks for the last 30 days.

Slots and placements

A slot holds one or more ads and decides where they appear.

PlacementWhere
Manual onlyWherever you put the slot's shortcode, block, widget or theme code.
HeaderTop of the page (wp_body_open, with a footer fallback that moves it to the top for themes without that hook).
FooterBottom of the page.
Before / after post contentMain content of single posts and pages.
After paragraph NInside the main content.
Between postsBlog and archive lists every N posts (classic loops and block-theme Query Loop).
PopupSee Popups.

Rotation: random, weighted random or fixed order, with any number of ads shown at once. Options: label ("Advertisement" or your text), alignment and extra CSS class.

Shortcode, block, widget and theme code

All of these work with or without any slots configured, and always load the plugin stylesheet when they output an ad.

Ads inside ads (nesting limit)

A rich-text ad can contain AdPlacer shortcodes. Nesting works up to 3 levels below the top-level ad or slot (top-level ad → ad → ad → ad); deeper content is left out. An ad or slot that refers to itself, directly or through other ads (A contains B, B contains A), is shown once and the repeated reference is silently skipped. The same guard applies to slots, automatic placements, popups, the shortcode, block, widget, theme functions and JavaScript rendering.

MethodUsage
Shortcode[adplacer slot="slot-name"] or [adplacer id="12"]
Block"AdPlacer Ad" block (Widgets category); choose a slot or a single ad.
Widget"AdPlacer Ad" widget in Appearance > Widgets; optional title, then a slot or single ad.
Theme codeadplacer_show( 'slot-name' ), echo adplacer_get( 'slot-name' ), adplacer_has( 'slot-name' ), adplacer_ad( 12 ), do_action( 'adplacer_slot', 'slot-name' )

Display conditions

On ads and on slots: device (mobile/desktop), logged-in or logged-out, user roles, page types, post types, categories and tags, specific post IDs, excluded IDs and a start/end schedule in the site's time zone. Settings can also hide ads for chosen roles.

Device (mobile / desktop)

By default the browser decides the device (breakpoint 767px), so device rules also work with page caching. Mobile-only or desktop-only ads and slots get a CSS class that hides them on the other device, and a slot whose ads are all hidden on the current device is hidden as well. Device-restricted popups never open, take focus or lock page scrolling on the other device, and a popup whose ads are all hidden on the current device does not open. With JavaScript rendering, the device is sent with the uncached render request and decided on the server. The optional "Also detect mobile on the server" setting uses the visitor's user agent instead and should not be used with page caching.

Popups

Center modal, bottom bar or corner slide-in. Triggers: page-load delay, scroll percentage, exit intent (desktop only) or active time on page. Frequency: every view, once per session or once every N days. Close button, Escape and overlay click, focus trap, aria-modal and focus return.

How front-end files load

AdPlacer has one small stylesheet (assets/front.css) and one small script (assets/front.js, no libraries). They are registered on every request but enqueued only when an ad is actually output on the page:

Note: a page whose content contains an AdPlacer shortcode or block gets the stylesheet even if display conditions end up hiding that ad for the current visitor.

Statistics (viewable impressions)

AdPlacer > Statistics shows viewable impressions, clicks and CTR per ad for 7, 30, 90 or 365 days, with a per-day view for each ad.

Upgrading from 1.0.0: version 1.0.0 counted an impression whenever the ad was rendered with a visible size, including below the fold. On sites with existing statistics, the Statistics page shows the date viewable counting began; totals before that date are rendered-ad impressions and will be higher.

Turn statistics off, set retention (30-3650 days) and the per-visitor request limit in AdPlacer > Settings.

Page caching

With full-page caching, switch Settings > Rendering to JavaScript. Every slot, automatic placement, popup and single ad placed by ID (shortcode, block or widget) is then output as an empty placeholder and filled after the page loads by an uncached request. That request checks rotation, schedules (start/end), device and visitor rules (logged in/out, roles) at that moment, so a cached page shows the right ads without purging the cache. Ads nested inside a rendered ad are rendered in the same request. An AdPlacer widget whose content turns out empty is hidden.

ads.txt

Edit ads.txt under AdPlacer > Settings. It is served at /ads.txt when no physical file exists.

Developer reference

Functions

adplacer_show( $slot, $args ), adplacer_get( $slot, $args ), adplacer_has( $slot ), adplacer_ad( $id ), action adplacer_slot.

Filters

FilterPurpose
adplacer_capabilityCapability to manage ads (default manage_options).
adplacer_disableReturn true to output no ads on the current request.
adplacer_ad_visible / adplacer_conditions_passOverride ad visibility / condition results.
adplacer_slot_adsChange the ads chosen for a slot.
adplacer_ad_html / adplacer_slot_htmlFilter ad and slot markup.
adplacer_render_modeserver or js per slot.
adplacer_paragraph_fallback_appendWhether "after paragraph N" appends at the end when the post is shorter.
adplacer_tracking_enabledReturn false to stop recording statistics.

Privacy and data removal

Only daily viewable-impression and click totals per ad are stored (table wp_adplacer_stats, one row per ad per day, updated atomically), with no personal data. Abuse of the counting endpoint is limited by a 2-minute counter (stored in the wp_adplacer_rate table) keyed by a salted hash of the visitor IP (taken from REMOTE_ADDR); the IP is never stored. Popup frequency is kept in the visitor's browser storage. The plugin makes no outbound requests. Third-party ad code may set its own cookies.

Deleting the plugin removes nothing unless you tick "Delete all ads, slots, statistics and settings when the plugin is deleted" in Settings.

Changelog

1.0.3

1.0.2

1.0.1

1.0.0