I was searching in documentation and online but it never mensioned anywhere. I want to add custom activity scope.

For example here are: All members, My friends, My groups, My favorites, Mensions.

http://s020.radikal.ru/i720/1402/03/bfc6b5c9a3ba.png Like here, on profile I see "personal, Mensions, Favorite". this is a place where I want my new menu (sorting) to appear

Now I want to add 'Whats hot'. So this won't be just a object to filter, but instead it should use some smart processing to generate output.

The output will be activity sorting based on activity_meta and activity date

So I have setup my component for buddypress but can find anything.

Do you have anything to show me some starting point? Maybe some tutorial? or code to read inside core? anything should go and in the end I'll post everything back

  • What does "What's hot" show? What kind of content? Popular groups? Popular posts? – gdaniel Feb 14 '14 at 22:04
  • popular activity based on activity_meta and activity_date – CBeTJlu4ok Feb 15 '14 at 9:06

What you want is something like the below class, provided in a gist by @boone-gorges. The code is for extending the groups stream with some tabs matching groupmeta.


* This is a quick and dirty class to work around the fact that bp_has_groups() does not have a
* meta_query parameter (or even an 'in' parameter). Usage:
* 1) Just before you fire up your bp_has_groups() loop, instantiate the NG_BP_Groups_Meta_Filter
*    class, with parameters $key and $value
* 2) Do your groups loop as normal
* 3) When you've closed the bp_has_groups() loop (endif;), call the method remove_filters() just
*    to be safe.
* Here's how you would run a bp_has_groups() loop that would only show groups that had the meta
* key/value: 'favorite_gum' => 'Juicy Fruit'
*   $meta_filter = new NG_BP_Groups_Meta_Filter( 'favorite_gum', 'Juicy Fruit' );
*   // Note that you can pass whatever arguments you want to bp_has_groups(), as usual
*   if ( bp_has_groups() ) :
*       while ( bp_groups() ) :
*           bp_the_group();
*           // Do your template stuff here
*       endwhile;
*   endif;
*   // Make sure that other loops on the page are clean
*   $meta_filter->remove_filters();
class BP_Groups_Meta_Filter {
    protected $key;
    protected $value;
    protected $group_ids = array();

    function __construct( $key, $value ) {
        $this->key = $key;
        $this->value = $value;
        add_filter( 'bp_groups_get_paged_groups_sql', array( &$this, 'filter_sql' ) );
        add_filter( 'bp_groups_get_total_groups_sql', array( &$this, 'filter_sql' ) );

    function setup_group_ids() {
        global $wpdb, $bp;
        $sql = $wpdb->prepare( "SELECT group_id FROM {$bp->groups->table_name_groupmeta} WHERE meta_key = %s AND meta_value = %s", $this->key, $this->value );
        $this->group_ids = wp_parse_id_list( $wpdb->get_col( $sql ) );

    function get_group_ids() {
        return $this->group_ids; 

    function filter_sql( $sql ) {
        $group_ids = $this->get_group_ids();
        if ( empty( $group_ids ) ) {
            return $sql;
        $sql_a = explode( 'WHERE', $sql );
        $new_sql = $sql_a[0] . 'WHERE g.id IN (' . implode( ',', $group_ids ) . ') AND ' . $sql_a[1];
        return $new_sql;

    function remove_filters() {
        remove_filter( 'bp_groups_get_paged_groups_sql', array( &$this, 'filter_sql' ) );
        remove_filter( 'bp_groups_get_total_groups_sql', array( &$this, 'filter_sql' ) );

Source: Limit a bp_has_groups() loop to groups matching a groupmeta key/value pair

This works very well, I have used it on several occasions now. To make it work you have to take care of creating the additional tabs and make sure you have a routine to take care of the filtering. A bit more insight can be found at the linked gist source for the class, take a closer look at the comments.

Additionally I provide you an example on how I used it in the past. Below code is an example on how to make use of that in combination with the group meta data provided by the plugin BuddyPress Group Tags. Used for the filter are the categories not the tags and of course this works only if the plugin is in use.


// create the tabs
add_action( 'bp_groups_directory_group_types', 'bp_ng_cat_grp_tabs_out' );
function bp_ng_cat_grp_tabs_out() {
    $gtags_categories = get_option( 'gtags_category' );
    $gtags_cat_keys = array_keys( $gtags_categories );

    foreach ( $gtags_cat_keys as $g_cat_k ) {
            <li class="selected" id="groups-<?php echo $g_cat_k; ?>">
                <a href="<?php bp_root_domain() ?>">
                    <?php $grp_count = count(gtags_get_group_ids( $g_cat_k )); printf( __( '%s <span>%s</span>', 'buddypress' ), $g_cat_k, $grp_count ) ?>

// take care of filtering
add_action( 'bp_before_groups_loop', 'bp_ng_cat_grp_tabs_filter' );
function bp_ng_cat_grp_tabs_filter() {
    $grp_querys = bp_ajax_querystring( 'groups' );
    $grp_querys_split = explode( '&' , $grp_querys);
    $grp_scope = preg_grep( '#scope=#' , $grp_querys_split);

    if ( $grp_scope != '' ) {
        $grp_scope = explode( '=' , implode( $grp_scope) );
        $grp_scope = $grp_scope[1];

    $gtags_categories = get_option( 'gtags_category' );
    $gtags_cat_keys = array_keys( $gtags_categories );

    if ( ! empty( $grp_scope ) && in_array( $grp_scope, $gtags_cat_keys ) ) :
        $meta_filter = new BP_Groups_Meta_Filter( 'gtags_group_cat', $grp_scope );

Ok, this should give you sufficient enough information on how this works. Of course this doesn't regard the activity stream, but like I said you need something like this and I'm certain it's possible. I just never had to do it, so I can't provide you with a complete example.

As you can see, key is to adapt the SQL to your needs, this can be done via the available filters. You can find those and pretty much all the other information you need to build your class for extending the activity stream in bp-activity-classes.php file. You definitely want to take a look at the
filter, but there are others to consider, depending on what your actual setup will be. Below code gives you an basic example on how to use the filters to alter the activity stream/loop. As it is it replaces the activity view and shows activities with the meta key favorite_count and sorts the results according to the meta value. Keep in mind, this isn't a solution, I just wrote this on the fly to give you more insight and a better starting point. So take it as it is intended, purely for testing, learning and understanding purposes.


    add_filter( 'bp_activity_get_where_conditions', 'wpse132109_alter_bp_activity_where_conditions', 12, 5 );
    function wpse132109_alter_bp_activity_where_conditions( $where_conditions, $r, $select_sql, $from_sql, $join_sql ) {
        global $bp;

        $meta_array = array(
            'relation' => 'AND',
                'key' => 'favorite_count',
                'compare' => 'EXISTS'
        $bp_activity_get_meta_query_sql = BP_Activity_Activity::get_meta_query_sql( $meta_array );
        if ( ! empty( $bp_activity_get_meta_query_sql['where'] ) ) {
            $where_conditions[] = $bp_activity_get_meta_query_sql['where'];

        return $where_conditions;

    add_filter( 'bp_activity_get_user_join_filter', 'wpse132109_alter_bp_activity_activties_sql', 12, 6 );
    function wpse132109_alter_bp_activity_activties_sql( $sql , $select_sql , $from_sql , $where_sql , $sort , $pag_sql = '' ) {
        global $bp;

        $meta_array = array(
            'relation' => 'AND',
                'key' => 'favorite_count',
                'compare' => 'EXISTS'
        $bp_activity_get_meta_query_sql = BP_Activity_Activity::get_meta_query_sql( $meta_array );
        if ( ! empty( $bp_activity_get_meta_query_sql['join'] ) ) {
            $join_sql .= $bp_activity_get_meta_query_sql['join'];

        $sql = "{$select_sql} {$from_sql} {$join_sql} {$where_sql} ORDER BY sti_bp_activity_meta.meta_value {$sort}";
        return $sql;

Note: neither for productive use nor in anyway optimized

Ok, that's a lot now, but this definitely should get you started. Just a short summary:

  1. Create a class for your activity filter
    • it will be somewhat similar to the above shown;
    • use the filters available to alter the SQL to your needs;
  2. Take care of
    • the output of your new tab(s);
    • the filtering options, so they are recognized and used;
  • yeap, thats just more then starting point. thanks a lot – CBeTJlu4ok Feb 16 '14 at 10:28
// Set up Cutsom BP navigation
function my_setup_nav() {
      global $bp;

      //Add new Menu Item in "Activity", "Profile" List.

bp_core_new_nav_item( array( 
    'name' => __( 'New Menu', 'buddypress' ), 
    'slug' => 'new-item', 
    'position' => 50,
    'screen_function' => 'my_new_item_page',
    'default_subnav_slug' => 'item-one'
) );

      //Add new sub-menu Item in "Profile" menu

bp_core_new_subnav_item( array(
   'name' => 'My Profile Page',
   'slug' => 'my-profile-page',
   'parent_url' => $bp->loggedin_user->domain . $bp->profile->slug . '/',
   'parent_slug' => $bp->profile->slug,
   'screen_function' => 'my_groups_page_function_to_show_screen',
   'position' => 40 ) );


add_action( 'bp_setup_nav', 'my_setup_nav' );

function my_new_item_page() {

      bp_core_load_template( apply_filters( 'bp_core_template_plugin', 'members/single/plugins' ) );
      add_action( 'bp_template_content', 'wdm_item_one_content');

function wdm_item_one_content()
    echo "New menu content";

function my_groups_page_function_to_show_screen() {

    //add title and content here
    add_action( 'bp_template_title', 'my_groups_page_function_to_show_screen_title' );
    add_action( 'bp_template_content', 'my_groups_page_function_to_show_screen_content' );
    bp_core_load_template( apply_filters( 'bp_core_template_plugin', 'members/single/plugins' ) );

 function my_groups_page_function_to_show_screen_title() {
     echo 'My Page Title';
 function my_groups_page_function_to_show_screen_content() { 

     // page content goes here

    echo "My Page content";
  • Sorry not even close. My question is about adding activity scope. – CBeTJlu4ok Feb 15 '14 at 12:48

Not the answer you're looking for? Browse other questions tagged or ask your own question.