Appearance
Developer Reference
Filters
Notifications
voxel_adrotate_sync/milestone_email
Replace the milestone email wholesale — recipient, subject, body, headers. Return the modified array.
php
add_filter( 'voxel_adrotate_sync/milestone_email', function ( $email, $post_id, $threshold, $type ) {
$email['subject'] = sprintf( 'Your ad just passed %d %s', $threshold, $type );
$email['headers'][] = 'Bcc: [email protected]';
return $email;
}, 10, 4 );Targeting
voxel_adrotate_sync/visitor_location (default null)
Override geo detection entirely. Return a location array, or a bare two-letter country string. Useful for testing, or for driving geo from a source of your own.
php
add_filter( 'voxel_adrotate_sync/visitor_location', fn() => [
'country' => 'US',
'region' => 'California',
'region_code' => 'CA',
'city' => 'Los Angeles',
] );voxel_adrotate_sync/geo_lookup
Used by the Custom geo provider. Receives the IP; return a location array.
voxel_adrotate_sync/geo_country_aliases
Extend the country name → ISO-2 map used by geo= rules.
php
add_filter( 'voxel_adrotate_sync/geo_country_aliases', function ( $map ) {
$map['HOLLAND'] = 'NL';
return $map;
} );voxel_adrotate_sync/has_consent
Override the GDPR consent decision — for integrating a consent-management platform server-side.
Assets
voxel_adrotate_sync_chartjs_src
Chart.js is bundled locally by default, so there's no third-party request. Filter the URL to point at a CDN or your own copy, or return false to skip it entirely if your theme already ships Chart.js.
php
add_filter( 'voxel_adrotate_sync_chartjs_src', '__return_false' );voxel_adrotate_sync/preload_ad_assets (default false)
By default the ad CSS and responsive script load only where an ad can appear. Enable this to force them everywhere — needed if you place ads through AdRotate's own sidebar widgets or post injection, which the plugin can't detect server-side.
voxel_adrotate_sync/preload_stats_css (default true)
The stats widget enqueues its own CSS where placed, but Voxel's My Listings cards are built outside Elementor's enqueue cycle, so the CSS is forced site-wide by default. Return false to stop that and save a few KB per page, if you don't show banner stats inside My Listings cards.
Maintenance
voxel_adrotate_sync/bulk_resync_batch_size
Tune the bulk re-sync chunk size. Accepts 50 to 1000; defaults to 200.
Helper functions
Available once the plugin is active. Each defaults to the current post.
php
get_adrotate_banner_stats( $post_id = null, $period = 'all' );
get_adrotate_banner_schedule( $post_id = null );
get_adrotate_daily_stats( $post_id = null, $days = 30 );
get_adrotate_banner_revenue( $post_id = null );$period accepts today, week, month, year or all.
php
$stats = get_adrotate_banner_stats( get_the_ID(), 'month' );
printf( '%d impressions, %d clicks', $stats['impressions'], $stats['clicks'] );Shortcodes
| Shortcode | Purpose |
|---|---|
[adrotate_banner_stats] | Renders stats for the current banner. |
[vas_ad] | Targeting and consent wrapper — see Targeting. |
Scheduled action
voxel_adrotate_sync/daily_expiry_scan runs daily. It demotes schedule-expired adverts to disabled and sends expiry warnings. Hook it to run your own daily work against banner data, or trigger it manually with WP-CLI:
bash
wp cron event run voxel_adrotate_sync/daily_expiry_scanNotes on internals
- Every database query uses
prepare()with placeholders, or binds only internally-cast integers. - Statistics and schedule reads are cached as transients, with the TTL configurable in settings. The cache is invalidated the moment AdRotate records an impression or click, so figures never lag.
- Dynamic-tag statistics are memoised per request: multiple tags on one card cost one stats query and one schedule query.
- Text domain is
voxel-adrotate-sync, with a.potin/languages/. This is unchanged from before the plugin was renamed to Voxel Ads — the domain keys existing translations and stored settings.

