Documentation for version 1.0.3. Lightweight ad manager with placements, rotation, conditions, accessible popups, local statistics and ads.txt.
adplacer-1.0.3.zip, Install, Activate. Requires WordPress 6.3+ and PHP 7.4+.| Type | Use |
|---|---|
| Image | Image with link, alt text, rel (sponsored / nofollow / noopener / noreferrer) and new-tab option. |
| Code | HTML/JavaScript for AdSense and other networks. Only users allowed to post unfiltered HTML can save scripts; others are filtered to safe HTML. |
| Rich text | Text 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.
A slot holds one or more ads and decides where they appear.
| Placement | Where |
|---|---|
| Manual only | Wherever you put the slot's shortcode, block, widget or theme code. |
| Header | Top of the page (wp_body_open, with a footer fallback that moves it to the top for themes without that hook). |
| Footer | Bottom of the page. |
| Before / after post content | Main content of single posts and pages. |
| After paragraph N | Inside the main content. |
| Between posts | Blog and archive lists every N posts (classic loops and block-theme Query Loop). |
| Popup | See 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.
All of these work with or without any slots configured, and always load the plugin stylesheet when they output an ad.
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.
| Method | Usage |
|---|---|
| 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 code | adplacer_show( 'slot-name' ), echo adplacer_get( 'slot-name' ), adplacer_has( 'slot-name' ), adplacer_ad( 12 ), do_action( 'adplacer_slot', 'slot-name' ) |
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.
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.
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.
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:
[adplacer] shortcode or an AdPlacer block, the stylesheet is added in the <head>.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.
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.
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.
Edit ads.txt under AdPlacer > Settings. It is served at /ads.txt when no physical file exists.
adplacer_show( $slot, $args ), adplacer_get( $slot, $args ), adplacer_has( $slot ), adplacer_ad( $id ), action adplacer_slot.
| Filter | Purpose |
|---|---|
adplacer_capability | Capability to manage ads (default manage_options). |
adplacer_disable | Return true to output no ads on the current request. |
adplacer_ad_visible / adplacer_conditions_pass | Override ad visibility / condition results. |
adplacer_slot_ads | Change the ads chosen for a slot. |
adplacer_ad_html / adplacer_slot_html | Filter ad and slot markup. |
adplacer_render_mode | server or js per slot. |
adplacer_paragraph_fallback_append | Whether "after paragraph N" appends at the end when the post is shorter. |
adplacer_tracking_enabled | Return false to stop recording statistics. |
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.
INSERT ... ON DUPLICATE KEY UPDATE per event, so simultaneous requests for the same ad and day no longer cause "Duplicate entry" database errors. Every write is checked and the tracking endpoint returns an error status if a counter could not be saved.wp_adplacer_rate) instead of a read-then-write transient. Expired rows are purged automatically.