Skip to content

Hooks and filters

The plugin exposes an extension surface focused on the capture pipeline, the notification flow, the bot filter, and the admin panel structure.

Fired immediately after a view row is inserted into {prefix}bp_profile_views.

do_action( 'bp_profile_views_after_insert', $insert_id, $user_id, $viewer_id );
Param Type Description
$insert_id int The $wpdb->insert_id of the new row.
$user_id int Profile owner (the person whose profile was viewed).
$viewer_id int Visitor. 0 for logged-out visitors.

The plugin’s own bp_profile_views_notification() callback is hooked here at priority 10. Add your own listener to forward view events to an analytics endpoint, queue a job, or trigger custom logic:

add_action(
'bp_profile_views_after_insert',
function ( $row_id, $user_id, $viewer_id ) {
// Example: push to an external stats service.
my_stats_track( 'profile_view', $user_id, $viewer_id );
},
20,
3
);

Controls the dedupe window for the “notify on view” feature. The plugin passes a MySQL INTERVAL expression string and interpolates it directly into a NOW() - INTERVAL {value} clause. Return a valid MySQL interval unit string.

$notify_day = apply_filters( 'bpv_notification_views_interval_day', $notify_day );
Param Type Default Description
$notify_day string '1 DAY' MySQL interval expression passed to NOW() - INTERVAL.

This filter only runs when allow_user_notification is 'yes' in General settings. If notifications are disabled, this filter is never called.

// One notification per week per viewer/profile pair.
add_filter( 'bpv_notification_views_interval_day', function () {
return '7 DAY';
} );
// Once per month.
add_filter( 'bpv_notification_views_interval_day', function () {
return '1 MONTH';
} );
// Conditional: longer window on a quieter site.
add_filter( 'bpv_notification_views_interval_day', function ( $interval ) {
return get_option( 'site_low_activity' ) === 'yes' ? '14 DAY' : $interval;
} );

Short-circuits the built-in user-agent bot detector. Return true to treat the current request as a bot (skip recording the view), false to force-count it regardless of UA, or null to fall through to the built-in UA pattern matching.

$override = apply_filters( 'bp_profile_views_is_bot', null );
Param Type Default Description
$override bool|null null true = bot, false = human, null = use UA patterns.
// Plug in a third-party bot-detection service.
add_filter( 'bp_profile_views_is_bot', function ( $override ) {
if ( is_bool( $override ) ) {
return $override; // Already decided.
}
return my_bot_detection_service()->is_bot();
} );
// Force-count a known monitoring UA that the built-in list would block.
add_filter( 'bp_profile_views_is_bot', function ( $override ) {
$ua = isset( $_SERVER['HTTP_USER_AGENT'] ) ? (string) $_SERVER['HTTP_USER_AGENT'] : '';
if ( false !== strpos( $ua, 'MyStatusCheckBot/1.0' ) ) {
return false;
}
return $override;
} );

Filters the list of lowercase UA substrings used by the built-in bot detector. Incoming user-agent strings are matched against each pattern with strpos(). Any match marks the request as a bot and prevents a view from being recorded.

$patterns = apply_filters( 'bp_profile_views_bot_user_agents', $patterns );
Param Type Description
$patterns string[] Lowercase substrings. Default list includes 'bot', 'crawler', 'spider', 'ahrefs', 'semrushbot', 'curl', and ~20 others.
// Add an in-house crawler to the blocklist.
add_filter( 'bp_profile_views_bot_user_agents', function ( $patterns ) {
$patterns[] = 'mycrawler';
return $patterns;
} );
// Remove a pattern that causes false positives on your stack.
add_filter( 'bp_profile_views_bot_user_agents', function ( $patterns ) {
return array_values( array_filter( $patterns, fn( $p ) => $p !== 'monitoring' ) );
} );

Sets the default chart period when no filter_by query-string parameter is present on the Views sub-tab. Applied in both the Legacy and Nouveau template partials.

$filter_by = apply_filters( 'bp_profile_views_filter_by', 'all' );
Param Type Default Description
$filter_by string 'all' Chart period. Accepted values: 'all', '7', '30', '365'. The numeric values represent a day count; 'all' shows the complete history.

The template renders four <select> options whose value attributes are exactly these strings. The PHP query uses strtotime('-' . ($filter_by - 1) . ' days'), so any non-numeric value other than 'all' will produce garbled arithmetic and return no rows.

// Default to the last 30 days instead of all-time.
add_filter( 'bp_profile_views_filter_by', function () {
return '30';
} );
// Default to the last 7 days.
add_filter( 'bp_profile_views_filter_by', function () {
return '7';
} );

Filters the admin sidebar tab array before rendering. Use this to add, remove, or reorder tabs in the plugin settings panel (1.5.0 and later).

$tabs = apply_filters( 'bpv_admin_tabs', $tabs );
Param Type Description
$tabs array Keyed by tab slug. Each entry is ['label' => string, 'icon' => string, 'group' => string]. Groups: 'main', 'settings', 'account', 'resources'.

Default tabs by group:

Slug Label Group
overview Overview main
members Members Views main
discover Discover main
general General settings
display Display settings
license License account
help Help & Docs account

The sidebar also renders a Resources group containing an outbound Documentation link. That is not a tab and is not in this array — see bpv_admin_help_links below.

// Add a custom tab.
add_filter( 'bpv_admin_tabs', function ( $tabs ) {
$tabs['my-custom-tab'] = array(
'label' => __( 'My Settings', 'my-plugin' ),
'icon' => 'dashicons-admin-tools',
'group' => 'settings',
);
return $tabs;
} );
// Remove the License tab for managed/agency installs.
add_filter( 'bpv_admin_tabs', function ( $tabs ) {
unset( $tabs['license'] );
return $tabs;
} );

Filters the URLs used on the Help & Docs admin tab and the sidebar Resources → Documentation link (1.5.3 and later). Both read the same map via Bpv_Admin::get_help_links(), so one filter re-points every documentation link at once. Re-point them for white-label installs or an internal help desk without forking.

$bpv_help_links = apply_filters( 'bpv_admin_help_links', $bpv_help_links );
Key Default
docs Documentation home
getting Getting-started guide
product Product page
support Support / ticket URL
contact Contact URL
add_filter( 'bpv_admin_help_links', function ( $links ) {
$links['support'] = 'https://help.example.com/';
return $links;
} );

Filters the product list shown on the Discover admin tab (1.5.3 and later). Each entry is an array with name, logo (a filename in assets/images/ecosystem/), desc, and url. Return an empty array to blank the tab on white-label installs, or unset discover via bpv_admin_tabs to drop the tab entirely.

$bpv_ecosystem = apply_filters( 'bpv_discover_products', $bpv_ecosystem );
add_filter( 'bpv_discover_products', function ( $products ) {
return array_values( array_filter( $products, function ( $product ) {
return 'Jetonomy' !== $product['name'];
} ) );
} );

Filters the one-click install catalog behind the Discover tab (1.5.3 and later). Keyed by plugin slug; each entry carries label, item_id (EDD product id), key (free distribution licence), basename, detect (callable), store_url, and optionally license_option.

Only slugs present in this catalog can be installed - the AJAX handler resolves the requested slug against it and returns 404 for anything else, so a request can never name its own package URL.

$catalog = apply_filters( 'bpv_install_catalog', $catalog );
add_filter( 'bpv_install_catalog', function ( $catalog ) {
unset( $catalog['wb-gamification'] );
return $catalog;
} );

The plugin registers its own component for the BP Notifications system. Useful if you query the wp_bp_notifications table directly or build custom notification handlers:

Field Value
Component name bp_profile_view_notifications
Component action bp_profile_view_notifications_action
Format text "{display_name} viewed your profile."
Notification link Visitor’s profile URL, nonce-signed for mark-as-read

The mark-as-read nonce is mark-as-read-notification-{current_user_id}-{viewer_id}. When a profile owner clicks a notification and lands on the viewer’s profile page, the plugin verifies this nonce and marks all matching notifications for that pair as read.

Dedupe is enforced in PHP before any notification is created: the plugin queries wp_bp_notifications for any existing row matching (user_id, secondary_item_id, component_name) within the configured interval. If one is found, no new notification is created.

If the BuddyPress Notifications component is not active, views are still recorded but the notification flow is silently inert.

To opt a user out of being tracked from code, set the visitor_setting user meta to 'no':

update_user_meta( $user_id, 'visitor_setting', 'no' );

The next time that user visits a profile their visit is not recorded. Existing rows are unaffected. To re-enable tracking set the meta back to 'yes'.