Docs menuHooks and filters

Hooks and filters

The actions and filters Vireo Analytics and Vireo Pro offer site owners and developers, with their arguments and defaults.

On this page

Add these in your theme’s functions.php or a small plugin. Hooks used only to wire the free plugin and Pro together are left out.

The fast endpoint and filters

Vireo records each view through a small endpoint that loads WordPress without your plugins or theme, so it’s fast. Code you add can’t run there. If you use any of these filters, Vireo notices and records views through the standard admin-ajax.php route instead, which is slower but sees your code:

vireo_trust_proxy_headers, vireo_beacon_rate_limit_per_minute, vireo_beacon_rate_limit_shard_keys, vireo_honor_opt_out, vireo_bot_ua_pattern, vireo_bot_signatures, vireo_geo_country_headers, vireo_buffer_dir_max_bytes, vireo_headless_allowed_origins.

Before Vireo Analytics 0.12.5, vireo_beacon_rate_limit_shard_keys, vireo_buffer_dir_max_bytes and vireo_bot_signatures were missing from that check, so setting one of them left views on the fast endpoint, where it had no effect. From 0.12.5 they switch the route like the others.

Hook Type Arguments What it does
vireo_force_direct_endpoint filter bool|null $force (default null) false records every view through admin-ajax.php. true uses the fast endpoint without testing it first, for hosts that block a site’s requests to itself. It can’t override the filters above, or an endpoint address on another host.
vireo_endpoint_url filter string $url The address the tracker sends views to. Defaults to the plugin’s endpoint.php. If it points at another host, for example because a CDN rewrote it, Vireo uses admin-ajax.php instead.

Vireo checks the endpoint when it’s activated and then once an hour, so a change to either filter takes effect at the next check.

Tracking

Hook Type Arguments What it does
vireo_load_tracking_script filter bool $load (default true) Return false to keep the tracker off the current page.
vireo_print_tracking_script action none Call it with do_action() before </body> in a template that has no wp_footer(). It prints the tracker once.
vireo_honor_opt_out filter bool $honor (default true) Return false to count visitors who send Do Not Track or Global Privacy Control.
vireo_require_consent filter bool $require (default false) Return true to wait for statistics consent from a WP Consent API plugin.
vireo_collect_web_vitals filter bool $collect (default true) Return false to stop collecting Core Web Vitals.
vireo_auto_event_download_exts filter string $exts, extensions joined by | The file types the File downloads auto-event records. Default pdf|zip|rar|7z|doc|docx|xls|xlsx|ppt|pptx|csv|mp3|mp4|mov|wav|dmg|pkg|exe|apk.
vireo_track_wpra filter bool $track (default true) Return false to stop counting clicks on WP RSS Aggregator items.
vireo_track_spotlight filter bool $track (default true) Return false to stop counting Spotlight feed clicks.
vireo_show_admin_bar filter bool $show, int $user_id Whether the toolbar shows today’s pageviews for this user. Starts from the Toolbar setting.
// Keep the tracker off a landing page used for ad tests.
add_filter( 'vireo_load_tracking_script', function ( $load ) {
	return is_page( 'ad-test' ) ? false : $load;
} );

Bots and counting

Hook Type Arguments What it does
vireo_bot_ua_pattern filter string $pattern, a regular expression without delimiters Replace the whole bot pattern. Matches are reported as Other bots.
vireo_bot_signatures filter array $signatures, category to combined regex The extended bot list, generated from Matomo Device Detector. Return an empty array to skip it and keep only Vireo’s own list.
vireo_visitor_path_cap filter int $cap (default 5) Most views of one page a visitor can add in a day.
vireo_visitor_daily_cap filter int $cap (default 50) Most views a visitor can add in a day.
vireo_beacon_rate_limit_per_minute filter int $limit (default 60) Pageviews accepted per minute from one address. 0 or less turns the limit off.
vireo_beacon_rate_limit_shard_keys filter int $keys (default 2000) How many addresses each rate-limit file remembers before the oldest are dropped. 0 or less keeps them all. See the fast endpoint.
vireo_ai_sources filter array $map, label to host regex The AI assistants recognised as referrers.
// Recognise another assistant as an AI referrer.
add_filter( 'vireo_ai_sources', function ( $map ) {
	$map['Example AI'] = '(^|\.)example-ai\.com$';
	return $map;
} );

Proxies and addresses

Hook Type Arguments What it does
vireo_trust_proxy_headers filter bool $trust (default false) Return true to read the visitor’s address from CF-Connecting-IP, X-Forwarded-For or X-Real-IP when the request comes from a trusted proxy.
vireo_trusted_proxies filter array $cidrs Networks whose forwarding headers are believed. Defaults to loopback, private ranges and Cloudflare.
vireo_geo_country_headers filter array $headers $_SERVER keys read for a country code from your host or CDN, such as HTTP_CF_IPCOUNTRY.
add_filter( 'vireo_trust_proxy_headers', '__return_true' );
add_filter( 'vireo_trusted_proxies', function ( $cidrs ) {
	$cidrs[] = '203.0.113.0/24'; // Your load balancer.
	return $cidrs;
} );

Headless and connected sites

Hook Type Arguments What it does
vireo_headless_post_id filter int $post_id, string $path, string $site, int $claimed Map a front-end path to a post when matching by path can’t. $site is the front end’s origin and $claimed the ID the page declared.
vireo_headless_allowed_origins filter array $origins Origins allowed to send pageviews with the headless tag. Starts with the “Front-end site address” setting.
vireo_connected_sites_limit filter int $limit (default 1) How many connected sites this install allows, capped at 100.
vireo_mainwp_enabled filter bool $enabled (default true) Return false to stop a MainWP dashboard reading this site’s numbers.
vireo_mainwp_proxied_abilities filter string[] $names The reports a MainWP dashboard may run on this site. Starts with Vireo’s own read-only abilities, and Pro adds its reports. Only read-only abilities run, whatever the list says, and get-sites and get-sites-overview never do.
// Front end serves posts under /blog/ while WordPress has them at the root.
add_filter( 'vireo_headless_post_id', function ( $post_id, $path ) {
	if ( $post_id || 0 !== strpos( $path, '/blog/' ) ) {
		return $post_id;
	}
	return url_to_postid( home_url( substr( $path, 5 ) ) );
}, 10, 2 );

REST API, abilities and MCP

Hook Type Arguments What it does
vireo_rest_permission_callback filter bool $allowed, WP_REST_Request $request Add a condition to the REST API. Runs only after the capability check passes, so it can narrow access, never widen it.
vireo_abilities_permission_callback filter bool $allowed, array $input The same for abilities and MCP tools.
vireo_mcp_tools filter array $tools, ability names The abilities offered as tools on the MCP server. Pro adds its own through this filter.
vireo_mcp_server_description filter string $description The description the MCP server gives AI assistants when they connect.

Dashboard and data

Hook Type Arguments What it does
vireo_annotation_capability filter string $cap (default edit_others_posts) The capability needed to add notes.
vireo_drivers_limit filter int $limit How many movers What changed lists each way: 3 in free, 10 with Pro.
vireo_overview_card_tab filter string $tab, callable $cb Which Overview tab an add-on card hooked to vireo_overview_after_core appears on: content, campaigns, speed or issues.
vireo_overview_tab_{tab} action string $start, string $end, bool $compare Print a card on one Overview tab: vireo_overview_tab_content, _campaigns, _speed or _issues.
vireo_email_brand filter array $brand with logo_url (string, default empty), accent (hex colour like #0f172a, the default; anything else falls back to it) and show_vireo (bool, default true) How the email digest looks: a logo above the heading, the colour of the “View full dashboard” button, and whether the footer names Vireo Analytics. Vireo Pro’s white-label settings use it.
vireo_hour_stats_retention_days filter int $days (default 7, 1 to 90) How long hourly traffic is kept for the Hour chart.
vireo_plausible_max_bytes filter int $bytes (default 1 GB) The most a Plausible export may unpack to.
vireo_after_flush action none Fires after each batch of new views reaches the database, about once a minute.
vireo_goal_completed action int $goal_id, string $visitor_hash, int $ts, float $value, string $date Fires for each goal completion as it’s recorded, with the visitor’s salted hash (empty when there isn’t one), the Unix time, the goal’s value and the site-local date. It’s the only point where a completion still carries its visitor, so listen here for sequences. The hash changes every day and identifies no one.
vireo_allowed_query_vars filter string[] $keys (default page_id, p, tag, cat, product, attachment_id) Query parameters kept in a page’s path. Every other parameter is dropped, so /pricing/?ref=mail counts as /pricing/.
vireo_404_max_new_rows_per_day filter int $max (default 500) How many new Broken links entries are recorded in a day, each a missing address and where it was linked from. Hits on entries already recorded that day still count. 0 or less removes the limit.
vireo_buffer_dir_max_bytes filter int $bytes (default 250 MB) The most Vireo’s data folder may hold while views wait to be saved, across this site and its connected sites. Past it, new views are dropped until saving catches up. It’s reached only when saving has stopped, which Site Health reports. See the fast endpoint.
vireo_network_activation_limit filter int $limit (default 200, 1 to 10000) How many sites network activation sets up straight away. The rest set themselves up the first time one of their pages loads.

Functions

vireo_track_event( string $name, string $value = '' ): bool

Records a custom event from PHP. The name keeps only a-z, 0-9, _ and -, and name and value are cut to 100 characters. Returns false if the name is empty after cleaning. See Events and broken links.

Pro

Hook Type Arguments What it does
vireo_tracked_taxonomies filter string[] $taxonomies (default category, post_tag) The taxonomies in Top categories and tags.
vireo_download_extensions filter string[] $extensions, lowercase, no dot File types Pro counts as downloads.
vireo_page_vitals_retention_days filter int $days (default 180, 30 to 3650) How long per-page speed is kept.
vireo_transitions_retention_days filter int $days (default 90, 1 to 730) How long page-to-page paths are kept.
vireo_funnel_retention_days filter int $days (default 30, 1 to 365) How long funnel step records are kept.
vireo_transitions_max_new_pairs_per_day filter int $max (default 2000) How many new page-to-page pairs Where people go next records in a day. Pairs already recorded still count. 0 or less removes the limit.
vireo_ai_report_content filter string $html, array $data The AI-written part of the Pro email report, before it goes into the email.
vireo_ai_model_preference filter string[] $models The models the Pro email report and Ask Vireo ask your AI provider for, in order of preference.
vireo_ask_tools filter string[] $tools The abilities Ask Vireo may use. Only names starting with vireo-analytics/get- are kept.
vireo_ask_system_prompt filter string $prompt, string[] $tools The instruction Ask Vireo starts each question with.
vireo_pro_site_abilities filter string[] $tools The abilities that take a site argument for connected sites. Add one only if every table it reads follows the site being asked about, or it answers with this site’s numbers.
vireo_mainwp_timeout filter int $seconds (default 10) How long a MainWP child gets to answer an AI assistant’s question.

Updated 13 October 2026. Something wrong or missing? Tell us.