diff --git src/bp-activity/bp-activity-actions.php src/bp-activity/bp-activity-actions.php
index 7d17133..8109ae7 100644
--- src/bp-activity/bp-activity-actions.php
+++ src/bp-activity/bp-activity-actions.php
@@ -831,3 +831,124 @@ function bp_activity_catch_transition_post_type_status( $new_status, $old_status
 	}
 }
 add_action( 'transition_post_status', 'bp_activity_catch_transition_post_type_status', 10, 3 );
+
+/**
+ * When a post type comment status transition occurs, update the relevant activity's status.
+ *
+ * @since 2.5.0
+ *
+ * @param string     $new_status New comment status.
+ * @param string     $old_status Previous comment status.
+ * @param WP_Comment $comment Comment data.
+ */
+function bp_activity_transition_post_type_comment_status( $new_status, $old_status, $comment ) {
+	$post_type = get_post_type( $comment->comment_post_ID );
+	if ( ! $post_type ) {
+		return;
+	}
+
+	// Get the post type tracking args.
+	$activity_post_object = bp_activity_get_post_type_tracking_args( $post_type );
+
+	// Bail if the activity type does not exist
+	if ( empty( $activity_post_object->comments_tracking->action_id ) ) {
+		return false;
+
+	// Set the $activity_comment_object
+	} else {
+		$activity_comment_object = $activity_post_object->comments_tracking;
+	}
+
+	// Init an empty activity ID
+	$activity_id = 0;
+
+	/**
+	 * Activity currently doesn't have any concept of a trash, or an unapproved/approved state.
+	 *
+	 * If a blog comment transitions to a "delete" or "hold" status, delete the activity item.
+	 * If a blog comment transitions to trashed, or spammed, mark the activity as spam.
+	 * If a blog comment transitions to approved (and the activity exists), mark the activity as ham.
+	 * If a blog comment transitions to unapproved (and the activity exists), mark the activity as spam.
+	 * Otherwise, record the comment into the activity stream.
+	 */
+
+	// This clause handles delete/hold.
+	if ( in_array( $new_status, array( 'delete', 'hold' ) ) ) {
+		return bp_activity_post_type_remove_comment( $comment->comment_ID, $activity_post_object );
+
+	// These clauses handle trash, spam, and un-spams.
+	} elseif ( in_array( $new_status, array( 'trash', 'spam', 'unapproved' ) ) ) {
+		$action = 'spam_activity';
+	} elseif ( 'approved' == $new_status ) {
+		$action = 'ham_activity';
+	}
+
+	// Get the activity
+	if ( bp_disable_blogforum_comments() ) {
+		$activity_id = bp_activity_get_activity_id( array(
+			'component'         => $activity_comment_object->component_id,
+			'item_id'           => get_current_blog_id(),
+			'secondary_item_id' => $comment->comment_ID,
+			'type'              => $activity_comment_object->action_id,
+		) );
+	} else {
+		$activity_id = get_comment_meta( $comment->comment_ID, 'bp_activity_comment_id', true );
+	}
+
+	/**
+	 * Leave a chance to plugins to manage activity comments differently.
+	 *
+	 * @since  2.5.0
+	 *
+	 * @param bool        $value       True to override BuddyPress management.
+	 * @param string      $post_type   The post type name.
+	 * @param int         $activity_id The post type activity (0 if not found).
+	 * @param string      $new_status  The new status of the post type comment.
+	 * @param string      $old_status  The old status of the post type comment.
+	 * @param WP_Comment  $comment Comment data.
+	 */
+	if ( true === apply_filters( 'bp_activity_pre_transition_post_type_comment_status', false, $post_type, $activity_id, $new_status, $old_status, $comment ) ) {
+		return false;
+	}
+
+	// Check activity item exists
+	if ( empty( $activity_id ) ) {
+		// If no activity exists, but the comment has been approved, record it into the activity table.
+		if ( 'approved' == $new_status ) {
+			return bp_activity_post_type_comment( $comment->comment_ID, true, $activity_post_object );
+		}
+
+		return;
+	}
+
+	// Create an activity object
+	$activity = new BP_Activity_Activity( $activity_id );
+	if ( empty( $activity->component ) ) {
+		return;
+	}
+
+	// Spam/ham the activity if it's not already in that state
+	if ( 'spam_activity' === $action && ! $activity->is_spam ) {
+		bp_activity_mark_as_spam( $activity );
+	} elseif ( 'ham_activity' == $action) {
+		bp_activity_mark_as_ham( $activity );
+	}
+
+	// Add "new_post_type_comment" to the whitelisted activity types, so that the activity's Akismet history is generated
+	$post_type_comment_action = $activity_comment_object->action_id;
+	$comment_akismet_history = create_function( '$t', '$t[] = $post_type_comment_action; return $t;' );
+	add_filter( 'bp_akismet_get_activity_types', $comment_akismet_history );
+
+	// Make sure the activity change won't edit the comment if sync is on
+	remove_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20 );
+
+	// Save the updated activity
+	$activity->save();
+
+	// Restore the action
+	add_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20 );
+
+	// Remove the "new_blog_comment" activity type whitelist so we don't break anything
+	remove_filter( 'bp_akismet_get_activity_types', $comment_akismet_history );
+}
+add_action( 'transition_comment_status', 'bp_activity_transition_post_type_comment_status', 10, 3 );
diff --git src/bp-activity/bp-activity-admin.php src/bp-activity/bp-activity-admin.php
index 49c9cad..9cf7e07 100644
--- src/bp-activity/bp-activity-admin.php
+++ src/bp-activity/bp-activity-admin.php
@@ -1110,6 +1110,7 @@ class BP_Activity_List_Table extends WP_List_Table {
 
 		// Option defaults.
 		$filter           = array();
+		$filter_query     = false;
 		$include_id       = false;
 		$search_terms     = false;
 		$sort             = 'DESC';
@@ -1136,9 +1137,27 @@ class BP_Activity_List_Table extends WP_List_Table {
 		}*/
 
 		// Filter.
-		if ( !empty( $_REQUEST['activity_type'] ) )
+		if ( ! empty( $_REQUEST['activity_type'] ) ) {
 			$filter = array( 'action' => $_REQUEST['activity_type'] );
 
+			/**
+			 * Filter here to override the filter with a filter query
+			 *
+			 * @since  2.5.0
+			 *
+			 * @param array $filter
+			 */
+			$has_filter_query = apply_filters( 'bp_activity_list_table_filter_activity_type_items', $filter );
+
+			if ( ! empty( $has_filter_query['filter_query'] ) ) {
+				// Reset the filter
+				$filter       = array();
+
+				// And use the filter query instead
+				$filter_query = $has_filter_query['filter_query'];
+			}
+		}
+
 		// Are we doing a search?
 		if ( !empty( $_REQUEST['s'] ) )
 			$search_terms = $_REQUEST['s'];
@@ -1165,6 +1184,7 @@ class BP_Activity_List_Table extends WP_List_Table {
 			'page'             => $page,
 			'per_page'         => $per_page,
 			'search_terms'     => $search_terms,
+			'filter_query'     => $filter_query,
 			'show_hidden'      => true,
 			// 'sort'             => $sort,
 			'spam'             => $spam,
@@ -1768,50 +1788,28 @@ class BP_Activity_List_Table extends WP_List_Table {
 	 * functions from working as intended.
 	 *
 	 * @since 2.0.0
+	 * @since 2.5.0 Include Post type activities types
 	 *
 	 * @param array $item An array version of the BP_Activity_Activity object.
 	 * @return bool $can_comment
 	 */
-	protected function can_comment( $item  ) {
-		$can_comment = true;
-
-		if ( $this->disable_blogforum_comments ) {
-			switch ( $item['type'] ) {
-				case 'new_blog_post' :
-				case 'new_blog_comment' :
-				case 'new_forum_topic' :
-				case 'new_forum_post' :
-					$can_comment = false;
-					break;
-			}
+	protected function can_comment( $item ) {
+		$can_comment = bp_activity_type_supports( $item['type'], 'comment-reply' );
 
-		// Activity comments supported.
-		} else {
-			// Activity comment.
-			if ( 'activity_comment' == $item['type'] ) {
-				// Blogs.
-				if ( bp_is_active( 'blogs' ) ) {
-					// Grab the parent activity entry.
-					$parent_activity = new BP_Activity_Activity( $item['item_id'] );
-
-					// Fetch blog post comment depth and if the blog post's comments are open.
-					bp_blogs_setup_activity_loop_globals( $parent_activity );
-
-					// Check if the activity item can be replied to.
-					if ( false === bp_blogs_can_comment_reply( true, $item ) ) {
-						$can_comment = false;
-					}
-				}
+		if ( ! $this->disable_blogforum_comments && bp_is_active( 'blogs' ) ) {
+			$parent_activity = false;
+
+			if ( bp_activity_type_supports( $item['type'], 'post-type-comment-tracking' ) ) {
+				$parent_activity = (object) $item;
+			} elseif ( 'activity_comment' === $item['type'] ) {
+				$parent_activity = new BP_Activity_Activity( $item['item_id'] );
+			}
 
-			// Blog post.
-			} elseif ( 'new_blog_post' == $item['type'] ) {
-				if ( bp_is_active( 'blogs' ) ) {
-					bp_blogs_setup_activity_loop_globals( (object) $item );
+			if ( isset( $parent_activity->type ) && bp_activity_post_type_get_tracking_arg( $parent_activity->type, 'post_type' ) ) {
+				// Fetch blog post comment depth and if the blog post's comments are open.
+				bp_blogs_setup_activity_loop_globals( $parent_activity );
 
-					if ( empty( buddypress()->blogs->allow_comments[$item['id']] ) ) {
-						$can_comment = false;
-					}
-				}
+				$can_comment = bp_blogs_can_comment_reply( true, $item );
 			}
 		}
 
@@ -1819,10 +1817,12 @@ class BP_Activity_List_Table extends WP_List_Table {
 		 * Filters if an activity item can be commented on or not.
 		 *
 		 * @since 2.0.0
+		 * @since 2.5.0 Add a second parameter to include the activity item into the filter.
 		 *
-		 * @param bool $can_comment Whether an activity item can be commented on or not.
+		 * @param bool   $can_comment Whether an activity item can be commented on or not.
+		 * @param array  $item        An array version of the BP_Activity_Activity object.
 		 */
-		return apply_filters( 'bp_activity_list_table_can_comment', $can_comment );
+		return apply_filters( 'bp_activity_list_table_can_comment', $can_comment, $item );
 	}
 
 	/**
diff --git src/bp-activity/bp-activity-functions.php src/bp-activity/bp-activity-functions.php
index b5e8a93..75464fb 100644
--- src/bp-activity/bp-activity-functions.php
+++ src/bp-activity/bp-activity-functions.php
@@ -428,8 +428,21 @@ function bp_activity_set_post_type_tracking_args( $post_type = '', $args = array
 		return false;
 	}
 
+	$activity_labels = array(
+		/* Post labels */
+		'bp_activity_admin_filter',
+		'bp_activity_front_filter',
+		'bp_activity_new_post',
+		'bp_activity_new_post_ms',
+		/* Comment labels */
+		'bp_activity_comments_admin_filter',
+		'bp_activity_comments_front_filter',
+		'bp_activity_new_comment',
+		'bp_activity_new_comment_ms'
+	);
+
 	// Labels are loaded into the post type object.
-	foreach ( array( 'bp_activity_admin_filter', 'bp_activity_front_filter', 'bp_activity_new_post', 'bp_activity_new_post_ms' ) as $label_type ) {
+	foreach ( $activity_labels as $label_type ) {
 		if ( ! empty( $args[ $label_type ] ) ) {
 			$wp_post_types[ $post_type ]->labels->{$label_type} = $args[ $label_type ];
 			unset( $args[ $label_type ] );
@@ -446,6 +459,7 @@ function bp_activity_set_post_type_tracking_args( $post_type = '', $args = array
  * Get tracking arguments for a specific post type.
  *
  * @since 2.2.0
+ * @since 2.5.0 Add post type comments tracking args
  *
  * @param  string $post_type Name of the post type.
  * @return object The tracking arguments of the post type.
@@ -455,17 +469,20 @@ function bp_activity_get_post_type_tracking_args( $post_type ) {
 		return false;
 	}
 
-	$post_type_object = get_post_type_object( $post_type );
+	$post_type_object           = get_post_type_object( $post_type );
+	$post_type_support_comments = post_type_supports( $post_type, 'comments' );
 
 	$post_type_activity = array(
-		'component_id'      => buddypress()->activity->id,
-		'action_id'         => 'new_' . $post_type,
-		'format_callback'   => 'bp_activity_format_activity_action_custom_post_type_post',
-		'front_filter'      => $post_type_object->labels->name,
-		'contexts'          => array( 'activity' ),
-		'position'          => 0,
-		'singular'          => strtolower( $post_type_object->labels->singular_name ),
-		'activity_comment' => ! post_type_supports( $post_type, 'comments' ),
+		'component_id'            => buddypress()->activity->id,
+		'action_id'               => 'new_' . $post_type,
+		'format_callback'         => 'bp_activity_format_activity_action_custom_post_type_post',
+		'front_filter'            => $post_type_object->labels->name,
+		'contexts'                => array( 'activity' ),
+		'position'                => 0,
+		'singular'                => strtolower( $post_type_object->labels->singular_name ),
+		'activity_comment'        => ! $post_type_support_comments,
+		'comment_action_id'       => false,
+		'comment_format_callback' => 'bp_activity_format_activity_action_custom_post_type_comment',
 	);
 
 	if ( ! empty( $post_type_object->bp_activity ) ) {
@@ -498,6 +515,52 @@ function bp_activity_get_post_type_tracking_args( $post_type ) {
 		$post_type_activity->new_post_type_action_ms = $post_type_object->labels->bp_activity_new_post_ms;
 	}
 
+	// If the post type supports comments and has a comment action id, build the comments tracking args
+	if ( $post_type_support_comments && ! empty( $post_type_activity->comment_action_id ) ) {
+		// Init a new container for the activity type for comments
+		$post_type_activity->comments_tracking = new stdClass();
+
+		// Build the activity type for comments
+		$post_type_activity->comments_tracking->component_id = $post_type_activity->component_id;
+		$post_type_activity->comments_tracking->action_id    = $post_type_activity->comment_action_id;
+
+		// Try to get the comments admin filter from the post type labels.
+		if ( ! empty( $post_type_object->labels->bp_activity_comments_admin_filter ) ) {
+			$post_type_activity->comments_tracking->admin_filter = $post_type_object->labels->bp_activity_comments_admin_filter;
+
+		// Fall back to a generic name.
+		} else {
+			$post_type_activity->comments_tracking->admin_filter = _x( 'New item comment posted', 'Post Type generic comments activity admin filter', 'buddypress' );
+		}
+
+		$post_type_activity->comments_tracking->format_callback = $post_type_activity->comment_format_callback;
+
+		// Check for the comments front filter in the post type labels.
+		if ( ! empty( $post_type_object->labels->bp_activity_comments_front_filter ) ) {
+			$post_type_activity->comments_tracking->front_filter = $post_type_object->labels->bp_activity_comments_front_filter;
+
+		// Fall back to a generic name.
+		} else {
+			$post_type_activity->comments_tracking->front_filter = sprintf( __( '%s comments', 'buddypress' ), $post_type_object->labels->singular_name );
+		}
+
+		$post_type_activity->comments_tracking->contexts = $post_type_activity->contexts;
+		$post_type_activity->comments_tracking->position = (int) $post_type_activity->position + 1;
+
+		// Try to get the action for new post type comment action on non-multisite installations.
+		if ( ! empty( $post_type_object->labels->bp_activity_new_comment ) ) {
+			$post_type_activity->comments_tracking->new_post_type_comment_action = $post_type_object->labels->bp_activity_new_comment;
+		}
+
+		// Try to get the action for new post type comment action on multisite installations.
+		if ( ! empty( $post_type_object->labels->bp_activity_new_comment_ms ) ) {
+			$post_type_activity->comments_tracking->new_post_type_comment_action_ms = $post_type_object->labels->bp_activity_new_comment_ms;
+		}
+	}
+
+	// Finally make sure we'll be able to find the post type this activity type is associated to.
+	$post_type_activity->post_type = $post_type;
+
 	/**
 	 * Filters tracking arguments for a specific post type.
 	 *
@@ -513,6 +576,7 @@ function bp_activity_get_post_type_tracking_args( $post_type ) {
  * Get tracking arguments for all post types.
  *
  * @since 2.2.0
+ * @since 2.5.0 Include post type comments tracking args if needed
  *
  * @return array List of post types with their tracking arguments.
  */
@@ -526,6 +590,20 @@ function bp_activity_get_post_types_tracking_args() {
 		$track_post_type = bp_activity_get_post_type_tracking_args( $post_type );
 
 		if ( ! empty( $track_post_type ) ) {
+			// Set the post type comments tracking args
+			if ( ! empty( $track_post_type->comments_tracking->action_id ) ) {
+				// Used to check support for comment tracking by activity type (new_post_type_comment)
+				$track_post_type->comments_tracking->comments_tracking = true;
+
+				// Used to be able to find the post type this activity type is associated to.
+				$track_post_type->comments_tracking->post_type = $post_type;
+
+				$post_types_tracking_args[ $track_post_type->comments_tracking->action_id ] = $track_post_type->comments_tracking;
+
+				// Used to check support for comment tracking by activity type (new_post_type)
+				$track_post_type->comments_tracking = true;
+			}
+
 			$post_types_tracking_args[ $track_post_type->action_id ] = $track_post_type;
 		}
 
@@ -543,6 +621,117 @@ function bp_activity_get_post_types_tracking_args() {
 }
 
 /**
+ * Check if the *Post Type* activity supports a specific feature.
+ *
+ * @since 2.5.0
+ *
+ * @param  string $activity_type The activity type to check.
+ * @param  string $feature       The feature to check. Currently supports:
+ *                               'post-type-comment-tracking', 'post-type-comment-reply' & 'comment-reply'.
+ *                               See inline doc for more info.
+ * @return bool
+ */
+function bp_activity_type_supports( $activity_type = '', $feature = '' ) {
+	$retval = false;
+
+	$bp = buddypress();
+
+	switch ( $feature ) {
+		/**
+		 * Does this activity type support comment tracking?
+		 *
+		 * eg. 'new_blog_post' and 'new_blog_comment' will both return true.
+		 */
+		case 'post-type-comment-tracking' :
+			// Set the activity track global if not set yet
+			if ( empty( $bp->activity->track ) ) {
+				$bp->activity->track = bp_activity_get_post_types_tracking_args();
+			}
+
+			if ( ! empty( $bp->activity->track[ $activity_type ]->comments_tracking ) ) {
+				$retval = true;
+			}
+			break;
+
+		/**
+		 * Is this a parent activity type that support post comments?
+		 *
+		 * eg. 'new_blog_post' will return true; 'new_blog_comment' will return false.
+		 */
+		case 'post-type-comment-reply' :
+			// Set the activity track global if not set yet.
+			if ( empty( $bp->activity->track ) ) {
+				$bp->activity->track = bp_activity_get_post_types_tracking_args();
+			}
+
+			if ( ! empty( $bp->activity->track[ $activity_type ]->comments_tracking ) && ! empty( $bp->activity->track[ $activity_type ]->comment_action_id ) ) {
+				$retval = true;
+			}
+			break;
+
+		/**
+		 * Does this activity type support comment & reply?
+		 */
+		case 'comment-reply' :
+			// Set the activity track global if not set yet.
+			if ( empty( $bp->activity->track ) ) {
+				$bp->activity->track = bp_activity_get_post_types_tracking_args();
+			}
+
+			// Post Type activities
+			if ( ! empty( $bp->activity->track[ $activity_type ] ) ) {
+				if ( isset( $bp->activity->track[ $activity_type ]->activity_comment ) ) {
+					$retval = $bp->activity->track[ $activity_type ]->activity_comment;
+				}
+
+				// Eventually override with comment synchronization feature.
+				if ( isset( $bp->activity->track[ $activity_type ]->comments_tracking ) ) {
+					$retval = $bp->activity->track[ $activity_type ]->comments_tracking && ! bp_disable_blogforum_comments();
+				}
+
+			// Retired Forums component
+			} elseif ( 'new_forum_topic' === $activity_type || 'new_forum_post' === $activity_type ) {
+				$retval = ! bp_disable_blogforum_comments();
+
+			// By Default, all other activity types are supporting comments.
+			} else {
+				$retval = true;
+			}
+			break;
+	}
+
+	return $retval;
+}
+
+/**
+ * Get a specific tracking argument for a given activity type
+ *
+ * @since 2.5.0
+ *
+ * @param  string       $activity_type the activity type.
+ * @param  string       $arg           the key of the tracking argument.
+ * @return mixed        the value of the tracking arg, false if not found.
+ */
+function bp_activity_post_type_get_tracking_arg( $activity_type, $arg = '' ) {
+	if ( empty( $activity_type ) || empty( $arg ) ) {
+		return false;
+	}
+
+	$bp = buddypress();
+
+	// Set the activity track global if not set yet
+	if ( empty( $bp->activity->track ) ) {
+		$bp->activity->track = bp_activity_get_post_types_tracking_args();
+	}
+
+	if ( isset( $bp->activity->track[ $activity_type ]->{$arg} ) ) {
+		return $bp->activity->track[ $activity_type ]->{$arg};
+	} else {
+		return false;
+	}
+}
+
+/**
  * Get all components' activity actions, sorted by their position attribute.
  *
  * @since 2.2.0
@@ -1405,6 +1594,57 @@ function bp_activity_format_activity_action_custom_post_type_post( $action, $act
 	return apply_filters( 'bp_activity_custom_post_type_post_action', $action, $activity );
 }
 
+/**
+ * Format activity action strings for custom post types comments.
+ *
+ * @since 2.5.0
+ *
+ * @param string $action   Static activity action.
+ * @param object $activity Activity data object.
+ *
+ * @return string
+ */
+function bp_activity_format_activity_action_custom_post_type_comment( $action, $activity ) {
+	$bp = buddypress();
+
+	// Fetch all the tracked post types once.
+	if ( empty( $bp->activity->track ) ) {
+		$bp->activity->track = bp_activity_get_post_types_tracking_args();
+	}
+
+	if ( empty( $activity->type ) || empty( $bp->activity->track[ $activity->type ] ) ) {
+		return $action;
+	}
+
+	$user_link = bp_core_get_userlink( $activity->user_id );
+
+	if ( is_multisite() ) {
+		$blog_link = '<a href="' . esc_url( get_home_url( $activity->item_id ) ) . '">' . get_blog_option( $activity->item_id, 'blogname' ) . '</a>';
+
+		if ( ! empty( $bp->activity->track[ $activity->type ]->new_post_type_comment_action_ms ) ) {
+			$action = sprintf( $bp->activity->track[ $activity->type ]->new_post_type_comment_action_ms, $user_link, $activity->primary_link, $blog_link );
+		} else {
+			$action = sprintf( _x( '%1$s commented on the <a href="%2$s">item</a>, on the site %3$s', 'Activity Custom Post Type comment action', 'buddypress' ), $user_link, $activity->primary_link, $blog_link );
+		}
+	} else {
+		if ( ! empty( $bp->activity->track[ $activity->type ]->new_post_type_comment_action ) ) {
+			$action = sprintf( $bp->activity->track[ $activity->type ]->new_post_type_comment_action, $user_link, $activity->primary_link );
+		} else {
+			$action = sprintf( _x( '%1$s commented on the <a href="%2$s">item</a>', 'Activity Custom Post Type post comment action', 'buddypress' ), $user_link, $activity->primary_link );
+		}
+	}
+
+	/**
+	 * Filters the formatted custom post type activity comment action string.
+	 *
+	 * @since 2.5.0
+	 *
+	 * @param string               $action   Activity action string value.
+	 * @param BP_Activity_Activity $activity Activity item object.
+	 */
+	return apply_filters( 'bp_activity_custom_post_type_comment_action', $action, $activity );
+}
+
 /*
  * Business functions are where all the magic happens in BuddyPress. They will
  * handle the actual saving or manipulation of information. Usually they will
@@ -1993,11 +2233,13 @@ function bp_activity_post_type_update( $post = null ) {
 	 * Fires after the updating of an activity item for a custom post type entry.
 	 *
 	 * @since 2.2.0
+	 * @since 2.5.0 Add the post type tracking args parameter
 	 *
-	 * @param WP_Post              $post     Post object.
-	 * @param BP_Activity_Activity $activity Activity object.
+	 * @param WP_Post              $post                 Post object.
+	 * @param BP_Activity_Activity $activity             Activity object.
+	 * @param object               $activity_post_object The post type tracking args object.
 	 */
-	do_action( 'bp_activity_post_type_updated', $post, $activity );
+	do_action( 'bp_activity_post_type_updated', $post, $activity, $activity_post_object );
 
 	return $updated;
 }
@@ -2053,9 +2295,270 @@ function bp_activity_post_type_unpublish( $post_id = 0, $post = null ) {
 }
 
 /**
+ * Create an activity item for a newly posted post type comment.
+ *
+ * @since 2.5.0
+ *
+ * @param  int  $comment_id  ID of the comment.
+ * @param  bool $is_approved Whether the comment is approved or not.
+ * @param  object $activity_post_object the post type tracking args object.
+ *
+ * @return int|bool The ID of the activity on success. False on error.
+ */
+function bp_activity_post_type_comment( $comment_id = 0, $is_approved = true, $activity_post_object = null ) {
+	// Get the users comment
+	$post_type_comment = get_comment( $comment_id );
+
+	// Don't record activity if the comment hasn't been approved
+	if ( empty( $is_approved ) ) {
+		return false;
+	}
+
+	// Don't record activity if no email address has been included
+	if ( empty( $post_type_comment->comment_author_email ) ) {
+		return false;
+	}
+
+	// Don't record activity if the comment has already been marked as spam
+	if ( 'spam' === $is_approved ) {
+		return false;
+	}
+
+	// Get the user by the comment author email.
+	$user = get_user_by( 'email', $post_type_comment->comment_author_email );
+
+	// If user isn't registered, don't record activity
+	if ( empty( $user ) ) {
+		return false;
+	}
+
+	// Get the user_id
+	$user_id = (int) $user->ID;
+
+	// Get blog and post data
+	$blog_id = get_current_blog_id();
+
+	// Get the post
+	$post_type_comment->post = get_post( $post_type_comment->comment_post_ID );
+
+	if ( ! is_a( $post_type_comment->post, 'WP_Post' ) ) {
+		return false;
+	}
+
+	/**
+	 * Filters whether to publish activities about the comment regarding the post status
+	 *
+	 * @since 2.5.0
+	 *
+	 * @param bool true to bail, false otherwise.
+	 */
+	$is_post_status_not_allowed = (bool) apply_filters( 'bp_activity_post_type_is_post_status_allowed', 'publish' !== $post_type_comment->post->post_status || ! empty( $post_type_comment->post->post_password ) );
+
+	// If this is a password protected post, or not a public post don't record the comment
+	if ( $is_post_status_not_allowed ) {
+		return false;
+	}
+
+	// Set post type
+	$post_type = $post_type_comment->post->post_type;
+
+	if ( empty( $activity_post_object ) ) {
+		// Get the post type tracking args.
+		$activity_post_object = bp_activity_get_post_type_tracking_args( $post_type );
+
+		// Bail if the activity type does not exist
+		if ( empty( $activity_post_object->comments_tracking->action_id ) ) {
+			return false;
+		}
+	}
+
+	// Set the $activity_comment_object
+	$activity_comment_object = $activity_post_object->comments_tracking;
+
+	/**
+	 * Filters whether or not to post the activity about the comment.
+	 *
+	 * This is a variable filter, dependent on the post type,
+	 * that lets components or plugins bail early if needed.
+	 *
+	 * @since 2.5.0
+	 *
+	 * @param bool $value      Whether or not to continue.
+	 * @param int  $blog_id    ID of the current site.
+	 * @param int  $post_id    ID of the current post being commented.
+	 * @param int  $user_id    ID of the current user.
+	 * @param int  $comment_id ID of the current comment being posted.
+	 */
+	if ( false === apply_filters( "bp_activity_{$post_type}_pre_comment", true, $blog_id, $post_type_comment->post->ID, $user_id, $comment_id ) ) {
+		return false;
+	}
+
+	// Is this an update ?
+	$activity_id = bp_activity_get_activity_id( array(
+		'user_id'           => $user_id,
+		'component'         => $activity_comment_object->component_id,
+		'type'              => $activity_comment_object->action_id,
+		'item_id'           => $blog_id,
+		'secondary_item_id' => $comment_id,
+	) );
+
+	// Record this in activity streams.
+	$comment_link = get_comment_link( $post_type_comment->comment_ID );
+
+	// Backward compatibility filters for the 'blogs' component.
+	if ( 'blogs' == $activity_comment_object->component_id )  {
+		$activity_content      = apply_filters_ref_array( 'bp_blogs_activity_new_comment_content',      array( $post_type_comment->comment_content, &$post_type_comment, $comment_link ) );
+		$activity_primary_link = apply_filters_ref_array( 'bp_blogs_activity_new_comment_primary_link', array( $comment_link, &$post_type_comment ) );
+	} else {
+		$activity_content      = $post_type_comment->comment_content;
+		$activity_primary_link = $comment_link;
+	}
+
+	$activity_args = array(
+		'id'            => $activity_id,
+		'user_id'       => $user_id,
+		'content'       => $activity_content,
+		'primary_link'  => $activity_primary_link,
+		'component'     => $activity_comment_object->component_id,
+		'recorded_time' => $post_type_comment->comment_date_gmt,
+	);
+
+	if ( bp_disable_blogforum_comments() ) {
+		$blog_url = get_home_url( $blog_id );
+		$post_url = add_query_arg(
+			'p',
+			$post_type_comment->post->ID,
+			trailingslashit( $blog_url )
+		);
+
+		$activity_args['type']              = $activity_comment_object->action_id;
+		$activity_args['item_id']           = $blog_id;
+		$activity_args['secondary_item_id'] = $post_type_comment->comment_ID;
+
+		if ( ! empty( $activity_args['content'] ) ) {
+			// Create the excerpt.
+			$activity_summary = bp_activity_create_summary( $activity_args['content'], $activity_args );
+
+			// Backward compatibility filter for blog comments.
+			if ( 'blogs' == $activity_post_object->component_id )  {
+				$activity_args['content'] = apply_filters( 'bp_blogs_record_activity_content', $activity_summary, $activity_args['content'], $activity_args, $post_type );
+			} else {
+				$activity_args['content'] = $activity_summary;
+			}
+		}
+
+		// Set up the action by using the format functions.
+		$action_args = array_merge( $activity_args, array(
+			'post_title' => $post_type_comment->post->post_title,
+			'post_url'   => $post_url,
+			'blog_url'   => $blog_url,
+			'blog_name'  => get_blog_option( $blog_id, 'blogname' ),
+		) );
+
+		$activity_args['action'] = call_user_func_array( $activity_comment_object->format_callback, array( '', (object) $action_args ) );
+
+		// Make sure the action is set.
+		if ( empty( $activity_args['action'] ) ) {
+			return;
+		} else {
+			// Backward compatibility filter for the blogs component.
+			if ( 'blogs' === $activity_post_object->component_id )  {
+				$activity_args['action'] = apply_filters( 'bp_blogs_record_activity_action', $activity_args['action'] );
+			}
+		}
+
+		$activity_id = bp_activity_add( $activity_args );
+	}
+
+	/**
+	 * Fires after the publishing of an activity item for a newly published post type post.
+	 *
+	 * @since 2.5.0
+	 *
+	 * @param int        $activity_id          ID of the newly published activity item.
+	 * @param WP_Comment $post_type_comment    Comment object.
+	 * @param array      $activity_args        Array of activity arguments.
+	 * @param object     $activity_post_object the post type tracking args object.
+	 */
+	do_action_ref_array( 'bp_activity_post_type_comment', array( &$activity_id, $post_type_comment, $activity_args, $activity_post_object ) );
+
+	return $activity_id;
+}
+add_action( 'comment_post', 'bp_activity_post_type_comment', 10, 2 );
+add_action( 'edit_comment', 'bp_activity_post_type_comment', 10    );
+
+/**
+ * Remove an activity item when a comment about a post type is deleted.
+ *
+ * @since 2.5.0
+ *
+ * @param  int    $comment_id           ID of the comment.
+ * @param  object $activity_post_object The post type tracking args object.
+ *
+ * @return bool True on success. False on error.
+ */
+function bp_activity_post_type_remove_comment( $comment_id = 0, $activity_post_object = null ) {
+	if ( empty( $activity_post_object ) ) {
+		$comment = get_comment( $comment_id );
+		if ( ! $comment ) {
+			return;
+		}
+
+		$post_type = get_post_type( $comment->comment_post_ID );
+		if ( ! $post_type ) {
+			return;
+		}
+
+		// Get the post type tracking args.
+		$activity_post_object = bp_activity_get_post_type_tracking_args( $post_type );
+
+		// Bail if the activity type does not exist
+		if ( empty( $activity_post_object->comments_tracking->action_id ) ) {
+			return false;
+		}
+	}
+
+	// Set the $activity_comment_object
+	$activity_comment_object = $activity_post_object->comments_tracking;
+
+	if ( empty( $activity_comment_object->action_id ) ) {
+		return false;
+	}
+
+	$deleted = false;
+
+	if ( bp_disable_blogforum_comments() ) {
+		$deleted = bp_activity_delete_by_item_id( array(
+			'item_id'           => get_current_blog_id(),
+			'secondary_item_id' => $comment_id,
+			'component'         => $activity_comment_object->component_id,
+			'type'              => $activity_comment_object->action_id,
+			'user_id'           => false,
+		) );
+	}
+
+	/**
+	 * Fires after the custom post type comment activity was removed.
+	 *
+	 * @since 2.5.0
+	 *
+	 * @param bool       $deleted              True if the activity was deleted false otherwise
+	 * @param WP_Comment $comment              Comment object.
+	 * @param object     $activity_post_object The post type tracking args object.
+	 * @param string     $value                The post type comment activity type.
+	 */
+	do_action( 'bp_activity_post_type_remove_comment', $deleted, $comment_id, $activity_post_object, $activity_comment_object->action_id );
+
+	return $deleted;
+}
+add_action( 'delete_comment', 'bp_activity_post_type_remove_comment', 10, 1 );
+
+/**
  * Add an activity comment.
  *
  * @since 1.2.0
+ * @since 2.5.0 Add a new possible parameter $skip_notification for the array of arguments.
+ *              Add the $primary_link parameter for the array of arguments.
  *
  * @uses wp_parse_args()
  * @uses bp_activity_add()
@@ -2065,15 +2568,19 @@ function bp_activity_post_type_unpublish( $post_id = 0, $post = null ) {
  * @uses do_action() To call the 'bp_activity_comment_posted' hook.
  *
  * @param array|string $args {
- *     @type int    $id          Optional. Pass an ID to update an existing comment.
- *     @type string $content     The content of the comment.
- *     @type int    $user_id     Optional. The ID of the user making the comment.
- *                               Defaults to the ID of the logged-in user.
- *     @type int    $activity_id The ID of the "root" activity item, ie the oldest
- *                               ancestor of the comment.
- *     @type int    $parent_id   Optional. The ID of the parent activity item, ie the item to
- *                               which the comment is an immediate reply. If not provided,
- *                               this value defaults to the $activity_id.
+ *     @type int    $id                Optional. Pass an ID to update an existing comment.
+ *     @type string $content           The content of the comment.
+ *     @type int    $user_id           Optional. The ID of the user making the comment.
+ *                                     Defaults to the ID of the logged-in user.
+ *     @type int    $activity_id       The ID of the "root" activity item, ie the oldest
+ *                                     ancestor of the comment.
+ *     @type int    $parent_id         Optional. The ID of the parent activity item, ie the item to
+ *                                     which the comment is an immediate reply. If not provided,
+ *                                     this value defaults to the $activity_id.
+ *     @type string $primary_link      Optional. the primary link for the comment.
+ *                                     Defaults to an empty string.
+ *     @type bool   $skip_notification Optional. false to send a comment notification, false otherwise.
+ *                                     Defaults to false.
  * }
  * @return int|bool The ID of the comment on success, otherwise false.
  */
@@ -2087,11 +2594,13 @@ function bp_activity_new_comment( $args = '' ) {
 	}
 
 	$r = wp_parse_args( $args, array(
-		'id'          => false,
-		'content'     => false,
-		'user_id'     => bp_loggedin_user_id(),
-		'activity_id' => false, // ID of the root activity item.
-		'parent_id'   => false  // ID of a parent comment (optional).
+		'id'                => false,
+		'content'           => false,
+		'user_id'           => bp_loggedin_user_id(),
+		'activity_id'       => false, // ID of the root activity item.
+		'parent_id'         => false, // ID of a parent comment (optional).
+		'primary_link'      => '',
+		'skip_notification' => false,
 	) );
 
 	// Bail if missing necessary data.
@@ -2138,6 +2647,7 @@ function bp_activity_new_comment( $args = '' ) {
 		'content'           => $comment_content,
 		'component'         => buddypress()->activity->id,
 		'type'              => 'activity_comment',
+		'primary_link'      => $r['primary_link'],
 		'user_id'           => $r['user_id'],
 		'item_id'           => $activity_id,
 		'secondary_item_id' => $r['parent_id'],
@@ -2156,16 +2666,31 @@ function bp_activity_new_comment( $args = '' ) {
 	}
 	wp_cache_delete( $activity_id, 'bp_activity' );
 
-	/**
-	 * Fires near the end of an activity comment posting, before the returning of the comment ID.
-	 *
-	 * @since 1.2.0
-	 *
-	 * @param int                  $comment_id ID of the newly posted activity comment.
-	 * @param array                $r          Array of parsed comment arguments.
-	 * @param BP_Activity_Activity $activity   Activity item being commented on.
-	 */
-	do_action( 'bp_activity_comment_posted', $comment_id, $r, $activity );
+	if ( empty( $r[ 'skip_notification' ] ) ) {
+		/**
+		 * Fires near the end of an activity comment posting, before the returning of the comment ID.
+		 * Sends a notification to the user @see bp_activity_new_comment_notification_helper().
+		 *
+		 * @since 1.2.0
+		 *
+		 * @param int   $comment_id ID of the newly posted activity comment.
+		 * @param array $r          Array of parsed comment arguments.
+		 * @param int   $activity   ID of the activity item being commented on.
+		 */
+		do_action( 'bp_activity_comment_posted', $comment_id, $r, $activity );
+	} else {
+		/**
+		 * Fires near the end of an activity comment posting, before the returning of the comment ID.
+		 * without sending a notification to the user
+		 *
+		 * @since 2.5.0
+		 *
+		 * @param int   $comment_id ID of the newly posted activity comment.
+		 * @param array $r          Array of parsed comment arguments.
+		 * @param int   $activity   ID of the activity item being commented on.
+		 */
+		do_action( 'bp_activity_comment_posted_notification_skipped', $comment_id, $r, $activity );
+	}
 
 	if ( empty( $comment_id ) ) {
 		$errors->add( 'comment_failed', $feedback );
@@ -2434,6 +2959,7 @@ function bp_activity_delete( $args = '' ) {
  * @return bool True on success, false on failure.
  */
 function bp_activity_delete_comment( $activity_id, $comment_id ) {
+	$deleted = false;
 
 	/**
 	 * Filters whether BuddyPress should delete an activity comment or not.
@@ -2442,13 +2968,14 @@ function bp_activity_delete_comment( $activity_id, $comment_id ) {
 	 * handle the deletion of child comments differently. Make sure you return false.
 	 *
 	 * @since 1.2.0
+	 * @since 2.5.0 Add the deleted parameter (passed by reference)
 	 *
 	 * @param bool $value       Whether BuddyPress should continue or not.
 	 * @param int  $activity_id ID of the root activity item being deleted.
 	 * @param int  $comment_id  ID of the comment being deleted.
 	 */
-	if ( ! apply_filters( 'bp_activity_delete_comment_pre', true, $activity_id, $comment_id ) ) {
-		return false;
+	if ( ! apply_filters_ref_array( 'bp_activity_delete_comment_pre', array( true, $activity_id, $comment_id, &$deleted ) ) ) {
+		return $deleted;
 	}
 
 	// Delete any children of this comment.
@@ -2457,6 +2984,8 @@ function bp_activity_delete_comment( $activity_id, $comment_id ) {
 	// Delete the actual comment.
 	if ( ! bp_activity_delete( array( 'id' => $comment_id, 'type' => 'activity_comment' ) ) ) {
 		return false;
+	} else {
+		$deleted = true;
 	}
 
 	// Purge comment cache for the root activity update.
@@ -2475,7 +3004,7 @@ function bp_activity_delete_comment( $activity_id, $comment_id ) {
 	 */
 	do_action( 'bp_activity_delete_comment', $activity_id, $comment_id );
 
-	return true;
+	return $deleted;
 }
 
 	/**
diff --git src/bp-activity/bp-activity-template.php src/bp-activity/bp-activity-template.php
index 113d480..f3ab841 100644
--- src/bp-activity/bp-activity-template.php
+++ src/bp-activity/bp-activity-template.php
@@ -3425,48 +3425,27 @@ function bp_activity_can_comment() {
 	global $activities_template;
 	$bp = buddypress();
 
-	// Assume activity can be commented on.
-	$can_comment = true;
-
-	// Determine ability to comment based on activity action name.
-	$activity_action = bp_get_activity_action_name();
-
-	$turn_off = 0;
-	if ( ! empty( $activities_template->disable_blogforum_replies ) ) {
-		$turn_off = 1;
-	}
+	// Determine ability to comment based on activity type name.
+	$activity_type = bp_get_activity_type();
 
-	$maybe_turn_off = array_fill_keys( array(
-		'new_blog_post',
-		'new_blog_comment',
-		'new_forum_topic',
-		'new_forum_post',
-	), $turn_off );
+	// Get the 'comment-reply' support for the current activity type.
+	$can_comment = bp_activity_type_supports( $activity_type, 'comment-reply' );
 
-	$maybe_turn_off['activity_comment'] = 1;
-
-	// Fetch all the tracked post types once.
-	if ( empty( $bp->activity->track ) ) {
-		$bp->activity->track = bp_activity_get_post_types_tracking_args();
+	// Neutralize activity_comment.
+	if ( 'activity_comment' === $activity_type ) {
+		$can_comment = false;
 	}
 
-	foreach ( $bp->activity->track as $action => $tracking_args ) {
-		if ( empty( $tracking_args->activity_comment ) ) {
-			$maybe_turn_off[ $action ] = $turn_off;
-		}
-	}
-
-	$can_comment = empty( $maybe_turn_off[ $activity_action ] );
-
 	/**
 	 * Filters whether a comment can be made on an activity item.
 	 *
 	 * @since 1.5.0
+	 * @since 2.5.0 Use $activity_type instead of $activity_name for the second parameter.
 	 *
 	 * @param bool   $can_comment     Status on if activity can be commented on.
-	 * @param string $activity_action Current activity action being checked on.
+	 * @param string $activity_type   Current activity type being checked on.
 	 */
-	return apply_filters( 'bp_activity_can_comment', $can_comment, $activity_action );
+	return apply_filters( 'bp_activity_can_comment', $can_comment, $activity_type );
 }
 
 /**
diff --git src/bp-blogs/bp-blogs-activity.php src/bp-blogs/bp-blogs-activity.php
index af93731..b822f50 100644
--- src/bp-blogs/bp-blogs-activity.php
+++ src/bp-blogs/bp-blogs-activity.php
@@ -18,16 +18,9 @@ defined( 'ABSPATH' ) || exit;
  * @return bool|null Returns false if activity component is not active.
  */
 function bp_blogs_register_activity_actions() {
-	$bp = buddypress();
-
-	// Bail if activity is not active.
-	if ( ! bp_is_active( 'activity' ) ) {
-		return false;
-	}
-
 	if ( is_multisite() ) {
 		bp_activity_set_action(
-			$bp->blogs->id,
+			buddypress()->blogs->id,
 			'new_blog',
 			__( 'New site created', 'buddypress' ),
 			'bp_blogs_format_activity_action_new_blog',
@@ -37,19 +30,6 @@ function bp_blogs_register_activity_actions() {
 		);
 	}
 
-	// Only add the comment type if the 'post' post type is trackable.
-	if ( post_type_supports( 'post', 'buddypress-activity' ) ) {
-		bp_activity_set_action(
-			$bp->blogs->id,
-			'new_blog_comment',
-			__( 'New post comment posted', 'buddypress' ),
-			'bp_blogs_format_activity_action_new_blog_comment',
-			__( 'Comments', 'buddypress' ),
-			array( 'activity', 'member' ),
-			10
-		);
-	}
-
 	/**
 	 * Fires after the registry of the default blog component activity actions.
 	 *
@@ -60,6 +40,81 @@ function bp_blogs_register_activity_actions() {
 add_action( 'bp_register_activity_actions', 'bp_blogs_register_activity_actions' );
 
 /**
+ * Set up the tracking arguments for the 'post' post type.
+ *
+ * @since 2.5.0 This was moved out of the BP_Blogs_Component class.
+ *
+ * @see bp_activity_get_post_type_tracking_args() for information on parameters.
+ *
+ * @param object|null $params    Tracking arguments.
+ * @param string|int  $post_type Post type to track.
+ * @return object
+ */
+function bp_blogs_register_post_tracking_args( $params = null, $post_type = 0 ) {
+
+	/**
+	 * Filters the post types to track for the Blogs component.
+	 *
+	 * @since 1.5.0
+	 * @deprecated 2.3.0
+	 *
+	 * Make sure plugins still using 'bp_blogs_record_post_post_types'
+	 * to track their post types will generate new_blog_post activities
+	 * See https://buddypress.trac.wordpress.org/ticket/6306
+	 *
+	 * @param array $value Array of post types to track.
+	 */
+	$post_types = apply_filters( 'bp_blogs_record_post_post_types', array( 'post' ) );
+	$post_types_array = array_flip( $post_types );
+
+	if ( ! isset( $post_types_array[ $post_type ] ) ) {
+		return $params;
+	}
+
+	// Set specific params for the 'post' post type.
+	$params->component_id    = buddypress()->blogs->id;
+	$params->action_id       = 'new_blog_post';
+	$params->admin_filter    = __( 'New post published', 'buddypress' );
+	$params->format_callback = 'bp_blogs_format_activity_action_new_blog_post';
+	$params->front_filter    = __( 'Posts', 'buddypress' );
+	$params->contexts        = array( 'activity', 'member' );
+	$params->position        = 5;
+
+	if ( post_type_supports( $post_type, 'comments' ) ) {
+		$params->comment_action_id = 'new_blog_comment';
+
+		/**
+		 * Filters the post types to track for the Blogs component.
+		 *
+		 * @since 1.5.0
+		 * @deprecated 2.5.0
+		 *
+		 * Make sure plugins still using 'bp_blogs_record_comment_post_types'
+		 * to track comment about their post types will generate new_blog_comment activities
+		 * See https://buddypress.trac.wordpress.org/ticket/6306
+		 *
+		 * @param array $value Array of post types to track.
+		 */
+		$comment_post_types = apply_filters( 'bp_blogs_record_comment_post_types', array( 'post' ) );
+		$comment_post_types_array = array_flip( $comment_post_types );
+
+		if ( isset( $comment_post_types_array[ $post_type ] ) ) {
+			$params->comments_tracking = new stdClass();
+			$params->comments_tracking->component_id    = buddypress()->blogs->id;
+			$params->comments_tracking->action_id       = 'new_blog_comment';
+			$params->comments_tracking->admin_filter    = __( 'New post comment posted', 'buddypress' );
+			$params->comments_tracking->format_callback = 'bp_blogs_format_activity_action_new_blog_comment';
+			$params->comments_tracking->front_filter    = __( 'Comments', 'buddypress' );
+			$params->comments_tracking->contexts        = array( 'activity', 'member' );
+			$params->comments_tracking->position        = 10;
+		}
+	}
+
+	return $params;
+}
+add_filter( 'bp_activity_get_post_type_tracking_args', 'bp_blogs_register_post_tracking_args', 10, 2 );
+
+/**
  * Format 'new_blog' activity actions.
  *
  * @since 2.0.0
@@ -218,8 +273,35 @@ function bp_blogs_format_activity_action_new_blog_post( $action, $activity ) {
  * @return string Constructed activity action.
  */
 function bp_blogs_format_activity_action_new_blog_comment( $action, $activity ) {
-	$blog_url  = bp_blogs_get_blogmeta( $activity->item_id, 'url' );
-	$blog_name = bp_blogs_get_blogmeta( $activity->item_id, 'name' );
+	/**
+	 * When the comment is published we are faking an activity object
+	 * to which we add 4 properties :
+	 * - the post url
+	 * - the post title
+	 * - the blog url
+	 * - the blog name
+	 * This is done to build the 'post link' part of the activity
+	 * action string.
+	 * NB: in this case the activity has not yet been created.
+	 */
+
+	$blog_url = false;
+
+	// Try to get the blog url from the activity object
+	if ( isset( $activity->blog_url ) ) {
+		$blog_url = $activity->blog_url;
+	} else {
+		$blog_url = bp_blogs_get_blogmeta( $activity->item_id, 'url' );
+	}
+
+	$blog_name = false;
+
+	// Try to get the blog name from the activity object
+	if ( isset( $activity->blog_name ) ) {
+		$blog_name = $activity->blog_name;
+	} else {
+		$blog_name = bp_blogs_get_blogmeta( $activity->item_id, 'name' );
+	}
 
 	if ( empty( $blog_url ) || empty( $blog_name ) ) {
 		$blog_url  = get_home_url( $activity->item_id );
@@ -229,8 +311,31 @@ function bp_blogs_format_activity_action_new_blog_comment( $action, $activity )
 		bp_blogs_update_blogmeta( $activity->item_id, 'name', $blog_name );
 	}
 
-	$post_url   = bp_activity_get_meta( $activity->id, 'post_url' );
-	$post_title = bp_activity_get_meta( $activity->id, 'post_title' );
+	$post_url = false;
+
+	// Try to get the post url from the activity object
+	if ( isset( $activity->post_url ) ) {
+		$post_url = $activity->post_url;
+
+	/**
+	 * The post_url property is not set, we need to build the url
+	 * thanks to the post id which is also saved as the secondary
+	 * item id property of the activity object.
+	 */
+	} elseif ( ! empty( $activity->id ) ) {
+		$post_url = bp_activity_get_meta( $activity->id, 'post_url' );
+	}
+
+	$post_title = false;
+
+	// Should be the case when the comment has just been published
+	if ( isset( $activity->post_title ) ) {
+		$post_title = $activity->post_title;
+
+	// If activity already exists try to get the post title from activity meta
+	} elseif ( ! empty( $activity->id ) ) {
+		$post_title = bp_activity_get_meta( $activity->id, 'post_title' );
+	}
 
 	// Should only be empty at the time of post creation.
 	if ( empty( $post_url ) || empty( $post_title ) ) {
@@ -333,20 +438,12 @@ add_filter( 'bp_activity_prefetch_object_data', 'bp_blogs_prefetch_activity_obje
  * @return int|bool On success, returns the activity ID. False on failure.
  */
 function bp_blogs_record_activity( $args = '' ) {
-
-	// Bail if activity is not active.
-	if ( ! bp_is_active( 'activity' ) ) {
-		return false;
-	}
-
-	$bp = buddypress();
-
 	$defaults = array(
 		'user_id'           => bp_loggedin_user_id(),
 		'action'            => '',
 		'content'           => '',
 		'primary_link'      => '',
-		'component'         => $bp->blogs->id,
+		'component'         => buddypress()->blogs->id,
 		'type'              => false,
 		'item_id'           => false,
 		'secondary_item_id' => false,
@@ -410,12 +507,6 @@ function bp_blogs_record_activity( $args = '' ) {
  * @return bool True on success, false on failure.
  */
 function bp_blogs_delete_activity( $args = '' ) {
-
-	// Bail if activity is not active.
-	if ( ! bp_is_active( 'activity' ) ) {
-		return false;
-	}
-
 	$r = bp_parse_args( $args, array(
 		'item_id'           => false,
 		'component'         => buddypress()->blogs->id,
@@ -522,17 +613,18 @@ function bp_blogs_comments_open( $activity ) {
  *
  * Note: This is only a one-way sync - activity comments -> blog comment.
  *
- * For blog post -> activity comment, see {@link bp_blogs_record_comment()}.
+ * For blog post -> activity comment, see {@link bp_activity_post_type_comment()}.
  *
  * @since 2.0.0
+ * @since 2.5.0 Allow custom post types to sync their comments with activity ones
  *
  * @param int    $comment_id      The activity ID for the posted activity comment.
  * @param array  $params          Parameters for the activity comment.
  * @param object $parent_activity Parameters of the parent activity item (in this case, the blog post).
  */
 function bp_blogs_sync_add_from_activity_comment( $comment_id, $params, $parent_activity ) {
-	// If parent activity isn't a blog post, stop now!
-	if ( $parent_activity->type != 'new_blog_post' ) {
+	// if parent activity isn't a post type having the buddypress-activity support, stop now!
+	if ( ! bp_activity_type_supports( $parent_activity->type, 'post-type-comment-tracking' ) ) {
 		return;
 	}
 
@@ -548,11 +640,13 @@ function bp_blogs_sync_add_from_activity_comment( $comment_id, $params, $parent_
 		$user = bp_core_get_core_userdata( $params['user_id'] );
 	}
 
+	// Get associated post type and set default comment parent
+	$post_type      = bp_activity_post_type_get_tracking_arg( $parent_activity->type, 'post_type' );
+	$comment_parent = 0;
+
 	// See if a parent WP comment ID exists.
-	if ( ! empty( $params['parent_id'] ) ) {
-		$comment_parent = bp_activity_get_meta( $params['parent_id'], 'bp_blogs_post_comment_id' );
-	} else {
-		$comment_parent = 0;
+	if ( ! empty( $params['parent_id'] ) && ! empty( $post_type ) ) {
+		$comment_parent = bp_activity_get_meta( $params['parent_id'], "bp_blogs_{$post_type}_comment_id" );
 	}
 
 	// Comment args.
@@ -565,15 +659,11 @@ function bp_blogs_sync_add_from_activity_comment( $comment_id, $params, $parent_
 		'comment_type'         => '', // Could be interesting to add 'buddypress' here...
 		'comment_parent'       => (int) $comment_parent,
 		'user_id'              => $params['user_id'],
-
-		// Commenting these out for now
-		// 'comment_author_IP'    => '127.0.0.1',
-		// 'comment_agent'        => '', .
 		'comment_approved'     => 1
 	);
 
 	// Prevent separate activity entry being made.
-	remove_action( 'comment_post', 'bp_blogs_record_comment', 10, 2 );
+	remove_action( 'comment_post', 'bp_activity_post_type_comment', 10, 2 );
 
 	// Handle multisite.
 	switch_to_blog( $parent_activity->item_id );
@@ -589,7 +679,9 @@ function bp_blogs_sync_add_from_activity_comment( $comment_id, $params, $parent_
 	add_comment_meta( $post_comment_id, 'bp_activity_comment_id', $comment_id );
 
 	// Add meta to activity comment.
-	bp_activity_update_meta( $comment_id, 'bp_blogs_post_comment_id', $post_comment_id );
+	if ( ! empty( $post_type ) ) {
+		bp_activity_update_meta( $comment_id, "bp_blogs_{$post_type}_comment_id", $post_comment_id );
+	}
 
 	// Resave activity comment with WP comment permalink.
 	//
@@ -616,7 +708,7 @@ function bp_blogs_sync_add_from_activity_comment( $comment_id, $params, $parent_
 	restore_current_blog();
 
 	// Add the comment hook back.
-	add_action( 'comment_post', 'bp_blogs_record_comment', 10, 2 );
+	add_action( 'comment_post', 'bp_activity_post_type_comment', 10, 2 );
 
 	/**
 	 * Fires after activity comments have been synced and posted as blog comments.
@@ -640,16 +732,20 @@ add_action( 'bp_activity_comment_posted', 'bp_blogs_sync_add_from_activity_comme
  * activity comment children before they are deleted.
  *
  * @since 2.0.0
+ * @since 2.5.0 Add the $delected parameter
  *
  * @param bool $retval             Whether BuddyPress should continue or not.
  * @param int  $parent_activity_id The parent activity ID for the activity comment.
  * @param int  $activity_id        The activity ID for the pending deleted activity comment.
+ * @param bool $deleted            Whether the comment was deleted or not.
  * @return bool
  */
-function bp_blogs_sync_delete_from_activity_comment( $retval, $parent_activity_id, $activity_id ) {
+function bp_blogs_sync_delete_from_activity_comment( $retval, $parent_activity_id, $activity_id, &$deleted ) {
 	// Check if parent activity is a blog post.
 	$parent_activity = new BP_Activity_Activity( $parent_activity_id );
-	if ( 'new_blog_post' != $parent_activity->type ) {
+
+	// if parent activity isn't a post type having the buddypress-activity support, stop now!
+	if ( ! bp_activity_type_supports( $parent_activity->type, 'post-type-comment-tracking' ) ) {
 		return $retval;
 	}
 
@@ -657,6 +753,7 @@ function bp_blogs_sync_delete_from_activity_comment( $retval, $parent_activity_i
 	$activity = bp_activity_get( array(
 		'in'               => $activity_id,
 		'display_comments' => 'stream',
+		'spam'             => 'all',
 	) );
 
 	// Get all activity comment IDs for the pending deleted item.
@@ -677,11 +774,14 @@ function bp_blogs_sync_delete_from_activity_comment( $retval, $parent_activity_i
 	// emulate bp_activity_delete_comment().
 	BP_Activity_Activity::rebuild_activity_comment_tree( $parent_activity_id );
 
+	// Avoid the error message although the comments were successfully deleted
+	$deleted = true;
+
 	// We're overriding the default bp_activity_delete_comment() functionality
 	// so we need to return false.
 	return false;
 }
-add_filter( 'bp_activity_delete_comment_pre', 'bp_blogs_sync_delete_from_activity_comment', 10, 3 );
+add_filter( 'bp_activity_delete_comment_pre', 'bp_blogs_sync_delete_from_activity_comment', 10, 4 );
 
 /**
  * Updates the blog comment when the associated activity comment is edited.
@@ -691,43 +791,64 @@ add_filter( 'bp_activity_delete_comment_pre', 'bp_blogs_sync_delete_from_activit
  * @param BP_Activity_Activity $activity The activity object.
  */
 function bp_blogs_sync_activity_edit_to_post_comment( BP_Activity_Activity $activity ) {
-	// Not an activity comment? stop now!
-	if ( 'activity_comment' !== $activity->type ) {
-		return;
-	}
-
 	// This is a new entry, so stop!
 	// We only want edits!
-	if ( empty( $activity->id ) ) {
+	if ( empty( $activity->id ) || bp_disable_blogforum_comments() ) {
 		return;
 	}
 
-	// Prevent recursion.
-	remove_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20 );
+	// fetch parent activity item
+	$parent_activity = new BP_Activity_Activity( $activity->item_id );
 
-	// Try to see if a corresponding blog comment exists.
-	$post_comment_id = bp_activity_get_meta( $activity->id, 'bp_blogs_post_comment_id' );
+	// if parent activity isn't a post type having the buddypress-activity support for comments, stop now!
+	if ( ! bp_activity_type_supports( $parent_activity->type, 'post-type-comment-tracking' ) ) {
+		return;
+	}
 
-	if ( empty( $post_comment_id ) ) {
+	$post_type = bp_activity_post_type_get_tracking_arg( $parent_activity->type, 'post_type' );
+
+	// No associated post type for this activity comment, stop.
+	if ( ! $post_type ) {
 		return;
 	}
 
-	// Fetch parent activity item.
-	$parent_activity = new BP_Activity_Activity( $activity->item_id );
+	// Try to see if a corresponding blog comment exists.
+	$post_comment_id = bp_activity_get_meta( $activity->id, "bp_blogs_{$post_type}_comment_id" );
 
-	// Sanity check.
-	if ( 'new_blog_post' !== $parent_activity->type ) {
+	if ( empty( $post_comment_id ) ) {
 		return;
 	}
 
 	// Handle multisite.
 	switch_to_blog( $parent_activity->item_id );
 
-	// Update the blog post comment.
-	wp_update_comment( array(
-		'comment_ID'      => $post_comment_id,
-		'comment_content' => $activity->content
-	) );
+	// Get the comment status
+	$post_comment_status = wp_get_comment_status( $post_comment_id );
+	$old_comment_status  = $post_comment_status;
+
+	// No need to edit the activity, as it's the activity who's updating the comment
+	remove_action( 'transition_comment_status',     'bp_activity_transition_post_type_comment_status', 10, 3 );
+	remove_action( 'bp_activity_post_type_comment', 'bp_blogs_comment_sync_activity_comment',          10, 4 );
+
+	if ( 1 === (int) $activity->is_spam && 'spam' !== $post_comment_status ) {
+		wp_spam_comment( $post_comment_id );
+	} elseif ( ! $activity->is_spam ) {
+		if ( 'spam' === $post_comment_status  ) {
+			wp_unspam_comment( $post_comment_id );
+		} elseif ( 'trash' === $post_comment_status ) {
+			wp_untrash_comment( $post_comment_id );
+		} else {
+			// Update the blog post comment.
+			wp_update_comment( array(
+				'comment_ID'       => $post_comment_id,
+				'comment_content'  => $activity->content,
+			) );
+		}
+	}
+
+	// Restore actions
+	add_action( 'transition_comment_status',     'bp_activity_transition_post_type_comment_status', 10, 3 );
+	add_action( 'bp_activity_post_type_comment', 'bp_blogs_comment_sync_activity_comment',          10, 4 );
 
 	restore_current_blog();
 }
@@ -769,12 +890,8 @@ add_action( 'trashed_post_comments', 'bp_blogs_remove_activity_meta_for_trashed_
  * powers the 'Comments' filter in the activity directory dropdown) includes
  * both old-style and new-style activity comments.
  *
- * This implementation involves filtering the activity queries directly, and
- * should be considered a stopgap. The proper solution would involve enabling
- * multiple query condition clauses, connected by an OR, in the bp_has_activities()
- * API.
- *
  * @since 2.1.0
+ * @since 2.5.0 Used for any synced Post type comments, in wp-admin or front-end contexts.
  *
  * @param array $args Arguments passed from bp_parse_args() in bp_has_activities().
  * @return array $args
@@ -783,13 +900,26 @@ function bp_blogs_new_blog_comment_query_backpat( $args ) {
 	global $wpdb;
 	$bp = buddypress();
 
-	// Bail if this is not a 'new_blog_comment' query.
-	if ( 'new_blog_comment' !== $args['action'] ) {
+	// If activity comments are disabled for blog posts, stop now!
+	if ( bp_disable_blogforum_comments() ) {
+		return $args;
+	}
+
+	// Get the associated post type
+	$post_type = bp_activity_post_type_get_tracking_arg( $args['action'], 'post_type' );
+
+	// Bail if this is not an activity associated with a post type
+	if ( empty( $post_type ) ) {
+		return $args;
+	}
+
+	// Bail if this is an activity about posts and not comments
+	if ( bp_activity_post_type_get_tracking_arg( $args['action'], 'comment_action_id' ) ) {
 		return $args;
 	}
 
 	// Comment synced ?
-	$activity_ids = $wpdb->get_col( $wpdb->prepare( "SELECT activity_id FROM {$bp->activity->table_name_meta} WHERE meta_key = %s", 'bp_blogs_post_comment_id' ) );
+	$activity_ids = $wpdb->get_col( $wpdb->prepare( "SELECT activity_id FROM {$bp->activity->table_name_meta} WHERE meta_key = %s", "bp_blogs_{$post_type}_comment_id" ) );
 
 	if ( empty( $activity_ids ) ) {
 		return $args;
@@ -798,7 +928,7 @@ function bp_blogs_new_blog_comment_query_backpat( $args ) {
 	// Init the filter query.
 	$filter_query = array();
 
-	if ( 'null' === $args['scope'] ) {
+	if ( ! isset( $args['scope'] ) || 'null' === $args['scope'] ) {
 		$args['scope'] = '';
 	} elseif ( 'just-me' === $args['scope'] ) {
 		$filter_query = array(
@@ -831,11 +961,13 @@ function bp_blogs_new_blog_comment_query_backpat( $args ) {
 
 	// Finally reset the action.
 	$args['action'] = '';
+	$args['type']   = '';
 
 	// Return the original arguments.
 	return $args;
 }
-add_filter( 'bp_after_has_activities_parse_args', 'bp_blogs_new_blog_comment_query_backpat' );
+add_filter( 'bp_after_has_activities_parse_args',                'bp_blogs_new_blog_comment_query_backpat' );
+add_filter( 'bp_activity_list_table_filter_activity_type_items', 'bp_blogs_new_blog_comment_query_backpat' );
 
 /**
  * Utility function to set up some variables for use in the activity loop.
@@ -857,8 +989,8 @@ function bp_blogs_setup_activity_loop_globals( $activity ) {
 		return;
 	}
 
-	// Parent not a blog post? stop now!
-	if ( 'new_blog_post' !== $activity->type ) {
+	// The activity type does not support comments or replies ? stop now!
+	if ( ! bp_activity_type_supports( $activity->type, 'post-type-comment-reply' ) ) {
 		return;
 	}
 
@@ -935,36 +1067,31 @@ add_action( 'bp_before_activity_comment', 'bp_blogs_setup_comment_loop_globals_o
  * @return bool
  */
 function bp_blogs_disable_activity_commenting( $retval ) {
+	global $activities_template;
+
 	// If activity commenting is disabled, return current value.
-	if ( bp_disable_blogforum_comments() ) {
+	if ( bp_disable_blogforum_comments() || ! isset( $activities_template->in_the_loop ) ) {
 		return $retval;
 	}
 
-	// Activity commenting is enabled for blog posts.
-	switch ( bp_get_activity_action_name() ) {
-
-		// We still have to disable activity commenting for 'new_blog_comment' items
-		// commenting should only be done on the parent 'new_blog_post' item.
-		case 'new_blog_comment' :
-			$retval = false;
-
-			break;
-
-		// Check if commenting is disabled for the WP blog post
-		// we should extrapolate this and automate this for plugins... or not.
-		case 'new_blog_post' :
-			global $activities_template;
+	$type = bp_get_activity_type();
 
+	// It's a post type supporting comment tracking.
+	if ( bp_activity_type_supports( $type, 'post-type-comment-tracking' ) ) {
+		// The activity type is supporting comments or replies
+		if ( bp_activity_type_supports( $type, 'post-type-comment-reply' ) ) {
 			// Setup some globals we'll need to reference later.
 			bp_blogs_setup_activity_loop_globals( $activities_template->activity );
 
 			// If comments are closed for the WP blog post, we should disable
 			// activity comments for this activity entry.
-			if ( empty( buddypress()->blogs->allow_comments[bp_get_activity_id()] ) ) {
+			if ( empty( buddypress()->blogs->allow_comments[ bp_get_activity_id() ] ) ) {
 				$retval = false;
 			}
-
-			break;
+		// The activity type does not support comments or replies
+		} else {
+			$retval = false;
+		}
 	}
 
 	return $retval;
@@ -972,6 +1099,42 @@ function bp_blogs_disable_activity_commenting( $retval ) {
 add_filter( 'bp_activity_can_comment', 'bp_blogs_disable_activity_commenting' );
 
 /**
+ * Limit the display of post type synced comments.
+ *
+ * @since  2.5.0
+ *
+ * When viewing the synced comments in stream mode, this prevents comments to
+ * be displayed twice, and avoids a Javascript error as the form to add replies
+ * is not available.
+ *
+ * @param  int $retval  The comment count for the activity.
+ * @return int          The comment count, or 0 to hide activity comment replies.
+ */
+function bp_blogs_post_type_comments_avoid_duplicates( $retval ) {
+	/**
+	 * Only limit the display when Post type comments are synced with
+	 * activity comments.
+	 */
+	if ( bp_disable_blogforum_comments() ) {
+		return $retval;
+	}
+
+	if ( 'activity_comment' !== bp_get_activity_type() ) {
+		return $retval;
+	}
+
+	// Check the parent activity
+	$parent_activity = new BP_Activity_Activity( bp_get_activity_item_id() );
+
+	if ( isset( $parent_activity->type ) && bp_activity_post_type_get_tracking_arg( $parent_activity->type, 'post_type' ) ) {
+		$retval = 0;
+	}
+
+	return $retval;
+}
+add_filter( 'bp_activity_get_comment_count', 'bp_blogs_post_type_comments_avoid_duplicates' );
+
+/**
  * Check if an activity comment associated with a blog post can be replied to.
  *
  * By default, disables replying to activity comments if the corresponding WP
@@ -1057,9 +1220,13 @@ function bp_blogs_activity_comment_single_permalink( $retval, $activity ) {
 		return $retval;
 	}
 
-	$blog_comment_id = bp_activity_get_meta( $activity->id, 'bp_blogs_post_comment_id' );
+	if ( bp_disable_blogforum_comments() ) {
+		return $retval;
+	}
+
+	$parent_activity = new BP_Activity_Activity( $activity->item_id );
 
-	if ( ! empty( $blog_comment_id ) ) {
+	if ( isset( $parent_activity->type ) && bp_activity_post_type_get_tracking_arg( $parent_activity->type, 'post_type' ) ) {
 		$retval = $activity->primary_link;
 	}
 
@@ -1083,23 +1250,52 @@ function bp_blogs_activity_comment_single_action( $retval, $activity ) {
 		return $retval;
 	}
 
-	$blog_comment_id = bp_activity_get_meta( $activity->id, 'bp_blogs_post_comment_id' );
+	if ( bp_disable_blogforum_comments() ) {
+		return $retval;
+	}
+
+	$parent_activity = new BP_Activity_Activity( $activity->item_id );
+
+	if ( ! isset( $parent_activity->type ) ) {
+		return $retval;
+	}
+
+	$post_type = bp_activity_post_type_get_tracking_arg( $parent_activity->type, 'post_type' );
+
+	if ( ! $post_type ) {
+		return $retval;
+	}
+
+	$blog_comment_id = bp_activity_get_meta( $activity->id, "bp_blogs_{$post_type}_comment_id" );
 
 	if ( ! empty( $blog_comment_id ) ) {
-		// Fetch the parent blog post activity item.
-		$parent_blog_post_activity = new BP_Activity_Activity( $activity->item_id );
+		$bp = buddypress();
 
-		// Fake a 'new_blog_comment' activity object.
-		$object = $activity;
+		// Check if a comment action id is set for the parent activity
+		$comment_action_id = bp_activity_post_type_get_tracking_arg( $parent_activity->type, 'comment_action_id' );
 
-		// Override 'item_id' to use blog ID.
-		$object->item_id = $parent_blog_post_activity->item_id;
+		// Use the action string callback for the activity type
+		if ( ! empty( $comment_action_id ) ) {
+			// Fake a 'new_{post_type}_comment' by cloning the activity object.
+			$object = clone $activity;
 
-		// Override 'secondary_item_id' to use comment ID.
-		$object->secondary_item_id = $blog_comment_id;
+			// Set the type of the activity to be a comment about a post type
+			$object->type = $comment_action_id;
 
-		// Now format the activity action using the 'new_blog_comment' action callback.
-		$retval = bp_blogs_format_activity_action_new_blog_comment( '', $object );
+			// Use the blog ID as the item_id.
+			$object->item_id = $parent_activity->item_id;
+
+			// Use comment ID as the secondary_item_id.
+			$object->secondary_item_id = $blog_comment_id;
+
+			// Get the format callback for this activity comment
+			$format_callback = bp_activity_post_type_get_tracking_arg( $comment_action_id, 'format_callback' );
+
+			// now format the activity action using the 'new_{post_type}_comment' action callback
+			if ( is_callable( $format_callback ) ) {
+				$retval = call_user_func_array( $format_callback, array( '', $object ) );
+			}
+		}
 	}
 
 	return $retval;
diff --git src/bp-blogs/bp-blogs-filters.php src/bp-blogs/bp-blogs-filters.php
index 5cb6a2f..bfd96f0 100644
--- src/bp-blogs/bp-blogs-filters.php
+++ src/bp-blogs/bp-blogs-filters.php
@@ -61,7 +61,7 @@ function bp_blogs_comments_clauses_select_by_id( $retval ) {
 }
 
 /**
- * Check whether the current post can be published.
+ * Check whether the current activity about a post or a comment can be published.
  *
  * Abstracted from the deprecated `bp_blogs_record_post()`.
  *
@@ -121,3 +121,4 @@ function bp_blogs_post_pre_publish( $return = true, $blog_id = 0, $post_id = 0,
 	return $return;
 }
 add_filter( 'bp_activity_post_pre_publish', 'bp_blogs_post_pre_publish', 10, 4 );
+add_filter( 'bp_activity_post_pre_comment', 'bp_blogs_post_pre_publish', 10, 4 );
diff --git src/bp-blogs/bp-blogs-functions.php src/bp-blogs/bp-blogs-functions.php
index 02e3477..a608107 100644
--- src/bp-blogs/bp-blogs-functions.php
+++ src/bp-blogs/bp-blogs-functions.php
@@ -477,12 +477,14 @@ add_action( 'bp_activity_post_type_published', 'bp_blogs_publish_post_activity_m
  * Updates a blog post's activity meta entry during a post edit.
  *
  * @since 2.2.0
+ * @since 2.5.0 Add the post type tracking args object parameter
  *
- * @param WP_Post              $post     Post object.
- * @param BP_Activity_Activity $activity Activity object.
+ * @param WP_Post              $post                 Post object.
+ * @param BP_Activity_Activity $activity             Activity object.
+ * @param object               $activity_post_object The post type tracking args object.
  */
-function bp_blogs_update_post_activity_meta( $post, $activity ) {
-	if ( empty( $activity->id ) || 'post' != $post->post_type ) {
+function bp_blogs_update_post_activity_meta( $post, $activity, $activity_post_object ) {
+	if ( empty( $activity->id ) || empty( $activity_post_object->action_id ) ) {
 		return;
 	}
 
@@ -491,57 +493,59 @@ function bp_blogs_update_post_activity_meta( $post, $activity ) {
 	if ( $post->post_title !== $existing_title ) {
 		bp_activity_update_meta( $activity->id, 'post_title', $post->post_title );
 
-		// Now update activity meta for post comments... sigh.
-		add_filter( 'comments_clauses', 'bp_blogs_comments_clauses_select_by_id' );
-		$comments = get_comments( array( 'post_id' => $post->ID ) );
-		remove_filter( 'comments_clauses', 'bp_blogs_comments_clauses_select_by_id' );
-
-		if ( ! empty( $comments ) ) {
-			$activity_ids = array();
-			$comment_ids  = wp_list_pluck( $comments, 'comment_ID' );
-
-			// Set up activity args.
-			$args = array(
-				'update_meta_cache' => false,
-				'show_hidden'       => true,
-				'per_page'          => 99999,
-			);
-
-			// Query for old-style "new_blog_comment" activity items.
-			$args['filter'] = array(
-				'object'       => buddypress()->blogs->id,
-				'action'       => 'new_blog_comment',
-				'secondary_id' => implode( ',', $comment_ids ),
-			);
-
-			$activities = bp_activity_get( $args );
-			if ( ! empty( $activities['activities'] ) ) {
-				$activity_ids = (array) wp_list_pluck( $activities['activities'], 'id' );
-			}
-
-			// Query for activity comments connected to a blog post.
-			unset( $args['filter'] );
-			$args['meta_query'] = array( array(
-				'key'     => 'bp_blogs_post_comment_id',
-				'value'   => $comment_ids,
-				'compare' => 'IN',
-			) );
-			$args['type'] = 'activity_comment';
-			$args['display_comments'] = 'stream';
+		if ( ! empty( $activity_post_object->comments_tracking->action_id ) ) {
+			// Now update activity meta for post comments... sigh.
+			add_filter( 'comments_clauses', 'bp_blogs_comments_clauses_select_by_id' );
+			$comments = get_comments( array( 'post_id' => $post->ID ) );
+			remove_filter( 'comments_clauses', 'bp_blogs_comments_clauses_select_by_id' );
+
+			if ( ! empty( $comments ) ) {
+				$activity_ids = array();
+				$comment_ids  = wp_list_pluck( $comments, 'comment_ID' );
+
+				// Set up activity args.
+				$args = array(
+					'update_meta_cache' => false,
+					'show_hidden'       => true,
+					'per_page'          => 99999,
+				);
+
+				// Query for old-style "new_blog_comment" activity items.
+				$args['filter'] = array(
+					'object'       => $activity_post_object->comments_tracking->component_id,
+					'action'       => $activity_post_object->comments_tracking->action_id,
+					'secondary_id' => implode( ',', $comment_ids ),
+				);
+
+				$activities = bp_activity_get( $args );
+				if ( ! empty( $activities['activities'] ) ) {
+					$activity_ids = (array) wp_list_pluck( $activities['activities'], 'id' );
+				}
 
-			$activities = bp_activity_get( $args );
-			if ( ! empty( $activities['activities'] ) ) {
-				$activity_ids = array_merge( $activity_ids, (array) wp_list_pluck( $activities['activities'], 'id' ) );
-			}
+				// Query for activity comments connected to a blog post.
+				unset( $args['filter'] );
+				$args['meta_query'] = array( array(
+					'key'     => 'bp_blogs_' . $post->post_type . '_comment_id',
+					'value'   => $comment_ids,
+					'compare' => 'IN',
+				) );
+				$args['type'] = 'activity_comment';
+				$args['display_comments'] = 'stream';
+
+				$activities = bp_activity_get( $args );
+				if ( ! empty( $activities['activities'] ) ) {
+					$activity_ids = array_merge( $activity_ids, (array) wp_list_pluck( $activities['activities'], 'id' ) );
+				}
 
-			// Update activity meta for all found activity items.
-			if ( ! empty( $activity_ids ) ) {
-				foreach ( $activity_ids as $aid ) {
-					bp_activity_update_meta( $aid, 'post_title', $post->post_title );
+				// Update activity meta for all found activity items.
+				if ( ! empty( $activity_ids ) ) {
+					foreach ( $activity_ids as $aid ) {
+						bp_activity_update_meta( $aid, 'post_title', $post->post_title );
+					}
 				}
-			}
 
-			unset( $activities, $activity_ids, $comment_ids, $comments );
+				unset( $activities, $activity_ids, $comment_ids, $comments );
+			}
 		}
 	}
 
@@ -552,186 +556,130 @@ function bp_blogs_update_post_activity_meta( $post, $activity ) {
 		bp_activity_delete_meta( $activity->id, 'post_comment_status' );
 	}
 }
-add_action( 'bp_activity_post_type_updated', 'bp_blogs_update_post_activity_meta', 10, 2 );
+add_action( 'bp_activity_post_type_updated', 'bp_blogs_update_post_activity_meta', 10, 3 );
 
 /**
- * Record a new blog comment in the BuddyPress activity stream.
+ * Update Activity and blogs meta and eventually sync comment with activity comment
  *
- * Only posts the item if blog is public and post is not password-protected.
+ * @since  2.5.0
  *
- * @param int         $comment_id  ID of the comment being recorded.
- * @param bool|string $is_approved Optional. The $is_approved value passed to
- *                                 the 'comment_post' action. Default: true.
- * @return bool|object Returns false on failure, the comment object on success.
+ * @param  int|bool   $activity_id          ID of recorded activity, or false if sync is active.
+ * @param  WP_Comment $comment              The comment object.
+ * @param  array      $activity_args        Array of activity arguments.
+ * @param  object     $activity_post_object The post type tracking args object.
+ * @return int|bool   Returns false if no activity, the activity id otherwise.
  */
-function bp_blogs_record_comment( $comment_id, $is_approved = true ) {
-	// Bail if activity component is not active.
-	if ( ! bp_is_active( 'activity' ) ) {
-		return;
-	}
-
-	// Get the users comment.
-	$recorded_comment = get_comment( $comment_id );
-
-	// Don't record activity if the comment hasn't been approved.
-	if ( empty( $is_approved ) )
+function bp_blogs_comment_sync_activity_comment( &$activity_id, $comment = null, $activity_args = array(), $activity_post_object = null ) {
+	if ( empty( $activity_args ) || empty( $comment->post->ID ) || empty( $activity_post_object->comment_action_id ) ) {
 		return false;
+	}
 
-	// Don't record activity if no email address has been included.
-	if ( empty( $recorded_comment->comment_author_email ) )
-		return false;
-
-	// Don't record activity if the comment has already been marked as spam.
-	if ( 'spam' === $is_approved )
-		return false;
-
-	// Get the user by the comment author email.
-	$user = get_user_by( 'email', $recorded_comment->comment_author_email );
-
-	// If user isn't registered, don't record activity.
-	if ( empty( $user ) )
-		return false;
-
-	// Get the user_id.
-	$user_id = (int) $user->ID;
-
-	// Get blog and post data.
+	// Set the current blog id.
 	$blog_id = get_current_blog_id();
 
-	// If blog is not trackable, do not record the activity.
-	if ( ! bp_blogs_is_blog_trackable( $blog_id, $user_id ) )
-		return false;
-
-	$recorded_comment->post = get_post( $recorded_comment->comment_post_ID );
-
-	if ( empty( $recorded_comment->post ) || is_wp_error( $recorded_comment->post ) )
-		return false;
-
-	// If this is a password protected post, don't record the comment.
-	if ( !empty( $recorded_comment->post->post_password ) )
-		return false;
-
-	// Don't record activity if the comment's associated post isn't a WordPress Post.
-	if ( !in_array( $recorded_comment->post->post_type, apply_filters( 'bp_blogs_record_comment_post_types', array( 'post' ) ) ) )
-		return false;
-
-	$is_blog_public = apply_filters( 'bp_is_blog_public', (int)get_blog_option( $blog_id, 'blog_public' ) );
-
-	// If blog is public allow activity to be posted.
-	if ( $is_blog_public ) {
-
-		// Get activity related links.
-		$post_permalink = get_permalink( $recorded_comment->comment_post_ID );
-		$comment_link   = get_comment_link( $recorded_comment->comment_ID );
-
-		// Setup activity args.
-		$args = array();
-
-		$args['user_id']       = $user_id;
-		$args['content']       = apply_filters_ref_array( 'bp_blogs_activity_new_comment_content', array( $recorded_comment->comment_content, &$recorded_comment, $comment_link ) );
-		$args['primary_link']  = apply_filters_ref_array( 'bp_blogs_activity_new_comment_primary_link', array( $comment_link,     &$recorded_comment ) );
-		$args['recorded_time'] = $recorded_comment->comment_date_gmt;
-
-		// Setup some different activity args depending if activity commenting is
-		// enabled or not.
-		// if cannot comment, record separate activity entry
-		// this is the old way of doing things.
-		if ( bp_disable_blogforum_comments() ) {
-			$args['type']              = 'new_blog_comment';
-			$args['item_id']           = $blog_id;
-			$args['secondary_item_id'] = $comment_id;
-
-			// Record the activity entry.
-			$activity_id = bp_blogs_record_activity( $args );
+	// These activity metadatas are used to build the new_blog_comment action string
+	if ( ! empty( $activity_id ) && ! empty( $activity_args['item_id'] ) && 'new_blog_comment' === $activity_post_object->comment_action_id ) {
+		// add some post info in activity meta
+		bp_activity_update_meta( $activity_id, 'post_title', $comment->post->post_title );
+		bp_activity_update_meta( $activity_id, 'post_url',   esc_url_raw( add_query_arg( 'p', $comment->post->ID, home_url( '/' ) ) ) );
+	}
 
-			// Add some post info in activity meta.
-			bp_activity_update_meta( $activity_id, 'post_title', $recorded_comment->post->post_title );
-			bp_activity_update_meta( $activity_id, 'post_url',   add_query_arg( 'p', $recorded_comment->post->ID, home_url( '/' ) ) );
+	// Sync comment - activity comment
+	if ( ! bp_disable_blogforum_comments() ) {
 
-		// Record comment as BP activity comment under the parent 'new_blog_post'
-		// activity item.
-		} else {
-			// This is a comment edit
-			// check to see if corresponding activity entry already exists.
-			if ( ! empty( $_REQUEST['action'] ) ) {
-				$existing_activity_id = get_comment_meta( $comment_id, 'bp_activity_comment_id', true );
+		if ( ! empty( $_REQUEST['action'] ) ) {
+			$existing_activity_id = get_comment_meta( $comment->comment_ID, 'bp_activity_comment_id', true );
 
-				if ( ! empty( $existing_activity_id ) ) {
-					$args['id'] = $existing_activity_id;
-				}
+			if ( ! empty( $existing_activity_id ) ) {
+				$activity_args['id'] = $existing_activity_id;
 			}
+		}
+
+		if ( empty( $activity_post_object ) ) {
+			$activity_post_object = bp_activity_get_post_type_tracking_args( $comment->post->post_type );
+		}
 
-			// Find the parent 'new_blog_post' activity entry.
+		if ( isset( $activity_post_object->action_id ) && isset( $activity_post_object->component_id ) ) {
+			// find the parent 'new_post_type' activity entry
 			$parent_activity_id = bp_activity_get_activity_id( array(
-				'component'         => 'blogs',
-				'type'              => 'new_blog_post',
+				'component'         => $activity_post_object->component_id,
+				'type'              => $activity_post_object->action_id,
 				'item_id'           => $blog_id,
-				'secondary_item_id' => $recorded_comment->comment_post_ID
+				'secondary_item_id' => $comment->comment_post_ID
 			) );
 
 			// Try to create a new activity item for the parent blog post.
 			if ( empty( $parent_activity_id ) ) {
-				$parent_activity_id = bp_activity_post_type_publish( $recorded_comment->comment_post_ID, $recorded_comment->post );
+				$parent_activity_id = bp_activity_post_type_publish( $comment->post->ID, $comment->post );
 			}
+		}
 
-			// We found the parent activity entry
-			// so let's go ahead and reconfigure some activity args.
-			if ( ! empty( $parent_activity_id ) ) {
-				// Set the 'item_id' with the parent activity entry ID.
-				$args['item_id'] = $parent_activity_id;
+		// we found the parent activity entry
+		// so let's go ahead and reconfigure some activity args
+		if ( ! empty( $parent_activity_id ) ) {
+			// set the parent activity entry ID
+			$activity_args['activity_id'] = $parent_activity_id;
 
-				// Now see if the WP parent comment has a BP activity ID.
-				$comment_parent = 0;
-				if ( ! empty( $recorded_comment->comment_parent ) ) {
-					$comment_parent = get_comment_meta( $recorded_comment->comment_parent, 'bp_activity_comment_id', true );
-				}
+			// now see if the WP parent comment has a BP activity ID
+			$comment_parent = 0;
+			if ( ! empty( $comment->comment_parent ) ) {
+				$comment_parent = get_comment_meta( $comment->comment_parent, 'bp_activity_comment_id', true );
+			}
 
-				// WP parent comment does not have a BP activity ID
-				// so set to 'new_blog_post' activity ID.
-				if ( empty( $comment_parent ) ) {
-					$comment_parent = $parent_activity_id;
-				}
+			// WP parent comment does not have a BP activity ID
+			// so set to 'new_' . post_type activity ID
+			if ( empty( $comment_parent ) ) {
+				$comment_parent = $parent_activity_id;
+			}
 
-				$args['secondary_item_id'] = $comment_parent;
-				$args['component']         = 'activity';
-				$args['type']              = 'activity_comment';
+			$activity_args['parent_id']         = $comment_parent;
+			$activity_args['skip_notification'] = true;
 
-			// Could not find corresponding parent activity entry
-			// so wipe out $args array.
-			} else {
-				$args = array();
-			}
+		// could not find corresponding parent activity entry
+		// so wipe out $args array
+		} else {
+			$activity_args = array();
+		}
 
-			// Record in activity streams.
-			if ( ! empty( $args ) ) {
-				// @todo should we use bp_activity_new_comment()? that function will also send
-				// an email to people in the activity comment thread.
-				//
-				// What if a site already has some comment email notification plugin setup?
-				// this is why I decided to go with bp_activity_add() to avoid any conflict
-				// with existing comment email notification plugins.
-				$comment_activity_id = bp_activity_add( $args );
-
-				if ( empty( $args['id'] ) ) {
-					// Add meta to activity comment.
-					bp_activity_update_meta( $comment_activity_id, 'bp_blogs_post_comment_id', $comment_id );
-					bp_activity_update_meta( $comment_activity_id, 'post_title', $recorded_comment->post->post_title );
-					bp_activity_update_meta( $comment_activity_id, 'post_url', add_query_arg( 'p', $recorded_comment->post->ID, home_url( '/' ) ) );
-
-					// Add meta to comment.
-					add_comment_meta( $comment_id, 'bp_activity_comment_id', $comment_activity_id );
+		// Record in activity streams
+		if ( ! empty( $activity_args ) ) {
+			$activity_id = bp_activity_new_comment( $activity_args );
+
+			if ( empty( $activity_args['id'] ) ) {
+				// The activity metadata to inform about the corresponding comment ID
+				bp_activity_update_meta( $activity_id, "bp_blogs_{$comment->post->post_type}_comment_id", $comment->comment_ID );
+
+				// The comment metadata to inform about the corresponding activity ID
+				add_comment_meta( $comment->comment_ID, 'bp_activity_comment_id', $activity_id );
+
+				// These activity metadatas are used to build the new_blog_comment action string
+				if ( 'new_blog_comment' === $activity_post_object->comment_action_id ) {
+					bp_activity_update_meta( $activity_id, 'post_title', $comment->post->post_title );
+					bp_activity_update_meta( $activity_id, 'post_url', esc_url_raw( add_query_arg( 'p', $comment->post->ID, home_url( '/' ) ) ) );
 				}
 			}
 		}
+	}
 
-		// Update the blogs last active date.
-		bp_blogs_update_blogmeta( $blog_id, 'last_activity', bp_core_current_time() );
+	// Update the blogs last active date
+	bp_blogs_update_blogmeta( $blog_id, 'last_activity', bp_core_current_time() );
+
+	if ( 'new_blog_comment' === $activity_post_object->comment_action_id ) {
+		/**
+		 * Fires after BuddyPress has recorded metadata about a published blog post comment.
+		 *
+		 * @since 2.5.0
+		 *
+		 * @param int     $value    Comment ID of the blog post comment being recorded.
+		 * @param WP_Post $post  WP_Comment object for the current blog post.
+		 * @param string  $value ID of the user associated with the current blog post comment.
+		 */
+		do_action( 'bp_blogs_new_blog_comment', $comment->comment_ID, $comment, bp_loggedin_user_id() );
 	}
 
-	return $recorded_comment;
+	return $activity_id;
 }
-add_action( 'comment_post', 'bp_blogs_record_comment', 10, 2 );
-add_action( 'edit_comment', 'bp_blogs_record_comment', 10    );
+add_action( 'bp_activity_post_type_comment', 'bp_blogs_comment_sync_activity_comment', 10, 4 );
 
 /**
  * Record a user's association with a blog.
@@ -984,80 +932,83 @@ function bp_blogs_remove_post( $post_id, $blog_id = 0, $user_id = 0 ) {
 add_action( 'delete_post', 'bp_blogs_remove_post' );
 
 /**
- * Remove a blog comment activity item from the activity stream.
+ * Remove a synced activity comment from the activity stream.
  *
- * @param int $comment_id ID of the comment to be removed.
+ * @since 2.5.0
+ *
+ * @param bool   $deleted              True when a comment post type activity was successfully removed.
+ * @param int    $comment_id           ID of the comment to be removed.
+ * @param object $activity_post_object The post type tracking args object.
+ * @param string $activity_type        The post type comment activity type.
+ *
+ * @return bool True on success. False on error.
  */
-function bp_blogs_remove_comment( $comment_id ) {
-	global $wpdb;
-
-	// Activity comments are disabled for blog posts
-	// which means that individual activity items exist for blog comments.
-	if ( bp_disable_blogforum_comments() ) {
-		// Delete the individual activity stream item.
-		bp_blogs_delete_activity( array(
-			'item_id'           => $wpdb->blogid,
-			'secondary_item_id' => $comment_id,
-			'type'              => 'new_blog_comment'
-		) );
-
-	// Activity comments are enabled for blog posts
-	// remove the associated activity item.
-	} else {
-		// Get associated activity ID from comment meta.
+function bp_blogs_post_type_remove_comment( $deleted, $comment_id, $activity_post_object, $activity_type = '' ) {
+	// Remove synced activity comments, if needed.
+	if ( ! bp_disable_blogforum_comments() ) {
+		// Get associated activity ID from comment meta
 		$activity_id = get_comment_meta( $comment_id, 'bp_activity_comment_id', true );
 
-		// Delete the associated activity comment.
-		//
-		// Also removes child post comments and associated activity comments.
-		if ( ! empty( $activity_id ) && bp_is_active( 'activity' ) ) {
-			// Fetch the activity comments for the activity item.
+		/**
+		 * Delete the associated activity comment & also remove
+		 * child post comments and associated activity comments.
+		 */
+		if ( ! empty( $activity_id ) ) {
+			// fetch the activity comments for the activity item
 			$activity = bp_activity_get( array(
 				'in'               => $activity_id,
 				'display_comments' => 'stream',
 				'spam'             => 'all',
 			) );
 
-			// Get all activity comment IDs for the pending deleted item.
+			// get all activity comment IDs for the pending deleted item
 			if ( ! empty( $activity['activities'] ) ) {
 				$activity_ids   = bp_activity_recurse_comments_activity_ids( $activity );
 				$activity_ids[] = $activity_id;
 
-				// Delete activity items.
+				// delete activity items
 				foreach ( $activity_ids as $activity_id ) {
 					bp_activity_delete( array(
 						'id' => $activity_id
 					) );
 				}
 
-				// Remove associated blog comments.
+				// remove associated blog comments
 				bp_blogs_remove_associated_blog_comments( $activity_ids );
 
-				// Rebuild activity comment tree.
+				// rebuild activity comment tree
 				BP_Activity_Activity::rebuild_activity_comment_tree( $activity['activities'][0]->item_id );
+
+				// Set the result
+				$deleted = true;
 			}
 		}
 	}
 
-	/**
-	 * Fires after a blog comment activity item was removed from activity stream.
-	 *
-	 * @since 1.0.0
-	 *
-	 * @param int $blogid     Item ID for the blog associated with the removed comment.
-	 * @param int $comment_id ID of the comment being removed.
-	 * @param int $value      ID of the current logged in user.
-	 */
-	do_action( 'bp_blogs_remove_comment', $wpdb->blogid, $comment_id, bp_loggedin_user_id() );
+	// Backcompat for comments about the 'post' post type.
+	if ( 'new_blog_comment' === $activity_type ) {
+		/**
+		 * Fires after a blog comment activity item was removed from activity stream.
+		 *
+		 * @since 1.0.0
+		 *
+		 * @param int $value      ID for the blog associated with the removed comment.
+		 * @param int $comment_id ID of the comment being removed.
+		 * @param int $value      ID of the current logged in user.
+		 */
+		do_action( 'bp_blogs_remove_comment', get_current_blog_id(), $comment_id, bp_loggedin_user_id() );
+	}
+
+	return $deleted;
 }
-add_action( 'delete_comment', 'bp_blogs_remove_comment' );
+add_action( 'bp_activity_post_type_remove_comment', 'bp_blogs_post_type_remove_comment', 10, 4 );
 
 /**
  * Removes blog comments that are associated with activity comments.
  *
  * @since 2.0.0
  *
- * @see bp_blogs_remove_comment()
+ * @see bp_blogs_remove_synced_comment()
  * @see bp_blogs_sync_delete_from_activity_comment()
  *
  * @param array $activity_ids The activity IDs to check association with blog
@@ -1094,88 +1045,6 @@ function bp_blogs_remove_associated_blog_comments( $activity_ids = array(), $for
 }
 
 /**
- * When a blog comment status transition occurs, update the relevant activity's status.
- *
- * @since 1.6.0
- *
- * @param string $new_status New comment status.
- * @param string $old_status Previous comment status.
- * @param object $comment    Comment data.
- */
-function bp_blogs_transition_activity_status( $new_status, $old_status, $comment ) {
-
-	// Check the Activity component is active.
-	if ( ! bp_is_active( 'activity' ) )
-		return;
-
-	/**
-	 * Activity currently doesn't have any concept of a trash, or an unapproved/approved state.
-	 *
-	 * If a blog comment transitions to a "delete" or "hold" status, delete the activity item.
-	 * If a blog comment transitions to trashed, or spammed, mark the activity as spam.
-	 * If a blog comment transitions to approved (and the activity exists), mark the activity as ham.
-	 * If a blog comment transitions to unapproved (and the activity exists), mark the activity as spam.
-	 * Otherwise, record the comment into the activity stream.
-	 */
-
-	// This clause was moved in from bp_blogs_remove_comment() in BuddyPress 1.6. It handles delete/hold.
-	if ( in_array( $new_status, array( 'delete', 'hold' ) ) ) {
-		return bp_blogs_remove_comment( $comment->comment_ID );
-
-	// These clauses handle trash, spam, and un-spams.
-	} elseif ( in_array( $new_status, array( 'trash', 'spam', 'unapproved' ) ) ) {
-		$action = 'spam_activity';
-	} elseif ( 'approved' == $new_status ) {
-		$action = 'ham_activity';
-	}
-
-	// Get the activity.
-	if ( bp_disable_blogforum_comments() ) {
-		$activity_id = bp_activity_get_activity_id( array(
-			'component'         => buddypress()->blogs->id,
-			'item_id'           => get_current_blog_id(),
-			'secondary_item_id' => $comment->comment_ID,
-			'type'              => 'new_blog_comment'
-		) );
-	} else {
-		$activity_id = get_comment_meta( $comment->comment_ID, 'bp_activity_comment_id', true );
-	}
-
-	// Check activity item exists.
-	if ( empty( $activity_id ) ) {
-		// If no activity exists, but the comment has been approved, record it into the activity table.
-		if ( 'approved' == $new_status ) {
-			return bp_blogs_record_comment( $comment->comment_ID, true );
-		}
-
-		return;
-	}
-
-	// Create an activity object.
-	$activity = new BP_Activity_Activity( $activity_id );
-	if ( empty( $activity->component ) )
-		return;
-
-	// Spam/ham the activity if it's not already in that state.
-	if ( 'spam_activity' == $action && ! $activity->is_spam ) {
-		bp_activity_mark_as_spam( $activity );
-	} elseif ( 'ham_activity' == $action) {
-		bp_activity_mark_as_ham( $activity );
-	}
-
-	// Add "new_blog_comment" to the whitelisted activity types, so that the activity's Akismet history is generated.
-	$comment_akismet_history = create_function( '$t', '$t[] = "new_blog_comment"; return $t;' );
-	add_filter( 'bp_akismet_get_activity_types', $comment_akismet_history );
-
-	// Save the updated activity.
-	$activity->save();
-
-	// Remove the "new_blog_comment" activity type whitelist so we don't break anything.
-	remove_filter( 'bp_akismet_get_activity_types', $comment_akismet_history );
-}
-add_action( 'transition_comment_status', 'bp_blogs_transition_activity_status', 10, 3 );
-
-/**
  * Get the total number of blogs being tracked by BuddyPress.
  *
  * @return int $count Total blog count.
diff --git src/bp-blogs/bp-blogs-loader.php src/bp-blogs/bp-blogs-loader.php
index 67d84db..274bc5f 100644
--- src/bp-blogs/bp-blogs-loader.php
+++ src/bp-blogs/bp-blogs-loader.php
@@ -106,9 +106,6 @@ class BP_Blogs_Component extends BP_Component {
 				add_post_type_support( $post_type, 'buddypress-activity' );
 			}
 		}
-
-		// Filter the generic track parameters for the 'post' post type.
-		add_filter( 'bp_activity_get_post_type_tracking_args', array( $this, 'post_tracking_args' ), 10, 2 );
 	}
 
 	/**
@@ -128,10 +125,13 @@ class BP_Blogs_Component extends BP_Component {
 			'classes',
 			'template',
 			'filters',
-			'activity',
 			'functions',
 		);
 
+		if ( bp_is_active( 'activity' ) ) {
+			$includes[] = 'activity';
+		}
+
 		if ( is_multisite() ) {
 			$includes[] = 'widgets';
 		}
@@ -300,50 +300,6 @@ class BP_Blogs_Component extends BP_Component {
 
 		parent::setup_cache_groups();
 	}
-
-	/**
-	 * Set up the tracking arguments for the 'post' post type.
-	 *
-	 * @since 2.2.0
-	 *
-	 * @see bp_activity_get_post_type_tracking_args() for information on parameters.
-	 *
-	 * @param object|null $params    Tracking arguments.
-	 * @param string|int  $post_type Post type to track.
-	 * @return object
-	 */
-	public function post_tracking_args( $params = null, $post_type = 0 ) {
-
-		/**
-		 * Filters the post types to track for the Blogs component.
-		 *
-		 * @since 1.5.0
-		 * @deprecated 2.3.0
-		 *
-		 * Make sure plugins still using 'bp_blogs_record_post_post_types'
-		 * to track their post types will generate new_blog_post activities
-		 * See https://buddypress.trac.wordpress.org/ticket/6306
-		 *
-		 * @param array $value Array of post types to track.
-		 */
-		$post_types = apply_filters( 'bp_blogs_record_post_post_types', array( 'post' ) );
-		$post_types_array = array_flip( $post_types );
-
-		if ( ! isset( $post_types_array[ $post_type ] ) ) {
-			return $params;
-		}
-
-		// Set specific params for the 'post' post type.
-		$params->component_id    = $this->id;
-		$params->action_id       = 'new_blog_post';
-		$params->admin_filter    = __( 'New post published', 'buddypress' );
-		$params->format_callback = 'bp_blogs_format_activity_action_new_blog_post';
-		$params->front_filter    = __( 'Posts', 'buddypress' );
-		$params->contexts        = array( 'activity', 'member' );
-		$params->position        = 5;
-
-		return $params;
-	}
 }
 
 /**
diff --git src/bp-core/deprecated/1.6.php src/bp-core/deprecated/1.6.php
index 626d31b..c5550b6 100644
--- src/bp-core/deprecated/1.6.php
+++ src/bp-core/deprecated/1.6.php
@@ -84,7 +84,7 @@ function bp_core_is_user_spammer( $user_id = 0 ) {
 
 /**
  * @deprecated 1.6.0
- * @deprecated No longer used; see bp_blogs_transition_activity_status()
+ * @deprecated No longer used; see bp_activity_transition_post_type_comment_status()
  */
 function bp_blogs_manage_comment( $comment_id, $comment_status ) {
 	_deprecated_function( __FUNCTION__, '1.6', 'No longer used' );
diff --git src/bp-core/deprecated/2.5.php src/bp-core/deprecated/2.5.php
index f441def..c3246df 100644
--- src/bp-core/deprecated/2.5.php
+++ src/bp-core/deprecated/2.5.php
@@ -883,3 +883,48 @@ function bp_core_deprecated_email_actions( $email, $delivery_status ) {
 	}
 }
 add_action( 'bp_sent_email', 'bp_core_deprecated_email_actions', 20, 2 );
+
+/**
+ * When a blog comment status transition occurs, update the relevant activity's status.
+ *
+ * @since 1.6.0
+ * @deprecated 2.5.0
+ *
+ * @param string $new_status New comment status.
+ * @param string $old_status Previous comment status.
+ * @param object $comment Comment data.
+ */
+function bp_blogs_transition_activity_status( $new_status, $old_status, $comment ) {
+	_deprecated_function( __FUNCTION__, '2.5.0', 'bp_activity_transition_post_type_comment_status()' );
+	bp_activity_transition_post_type_comment_status( $new_status, $old_status, $comment );
+}
+
+/**
+ * Record a new blog comment in the BuddyPress activity stream.
+ *
+ * Only posts the item if blog is public and post is not password-protected.
+ *
+ * @deprecated 2.5.0
+ *
+ * @param int $comment_id ID of the comment being recorded.
+ * @param bool|string $is_approved Optional. The $is_approved value passed to
+ *        the 'comment_post' action. Default: true.
+ * @return bool|object Returns false on failure, the comment object on success.
+ */
+function bp_blogs_record_comment( $comment_id, $is_approved = true ) {
+	_deprecated_function( __FUNCTION__, '2.5.0', 'bp_activity_post_type_comment()' );
+	bp_activity_post_type_comment( $comment_id, $is_approved );
+}
+
+/**
+ * Remove a blog comment activity item from the activity stream.
+ *
+ * @deprecated 2.5.0
+ *
+ * @param int $comment_id ID of the comment to be removed.
+ */
+function bp_blogs_remove_comment( $comment_id ) {
+	_deprecated_function( __FUNCTION__, '2.5.0', 'bp_activity_post_type_remove_comment()' );
+	bp_activity_post_type_remove_comment( $comment_id );
+}
+
diff --git tests/phpunit/includes/testcase.php tests/phpunit/includes/testcase.php
index a75009a..1e8bcb4 100644
--- tests/phpunit/includes/testcase.php
+++ tests/phpunit/includes/testcase.php
@@ -49,6 +49,12 @@ class BP_UnitTestCase extends WP_UnitTestCase {
 
 		// Clean up after autocommits.
 		add_action( 'bp_blogs_recorded_existing_blogs', array( $this, 'set_autocommit_flag' ) );
+
+		// Make sure Activity actions are reset before each test
+		$this->reset_bp_activity_actions();
+
+		// Make sure all Post types activities globals are reset before each test
+		$this->reset_bp_activity_post_types_globals();
 	}
 
 	public function tearDown() {
@@ -97,6 +103,33 @@ class BP_UnitTestCase extends WP_UnitTestCase {
 		parent::clean_up_global_scope();
 	}
 
+	protected function reset_bp_activity_actions() {
+		buddypress()->activity->actions = new stdClass();
+
+		/**
+		 * Populate the global with default activity actions only
+		 * before each test.
+		 */
+		do_action( 'bp_register_activity_actions' );
+	}
+
+	protected function reset_bp_activity_post_types_globals() {
+		global $wp_post_types;
+
+		// Remove all remaining tracking arguments to each post type
+		foreach ( $wp_post_types as $post_type => $post_type_arg ) {
+			if ( post_type_supports( $post_type, 'buddypress-activity' ) ) {
+				remove_post_type_support( $post_type, 'buddypress-activity' );
+			}
+
+			if ( isset( $post_type_arg->bp_activity ) ) {
+				unset( $post_type_arg->bp_activity );
+			}
+		}
+
+		buddypress()->activity->track = array();
+	}
+
 	function assertPreConditions() {
 		parent::assertPreConditions();
 
diff --git tests/phpunit/testcases/activity/actions.php tests/phpunit/testcases/activity/actions.php
index d1ae6df..5549607 100644
--- tests/phpunit/testcases/activity/actions.php
+++ tests/phpunit/testcases/activity/actions.php
@@ -9,8 +9,6 @@ class BP_Tests_Activity_Actions extends BP_UnitTestCase {
 	 * @group activity_tracking
 	 */
 	public function test_bp_activity_catch_transition_post_type_status_publish() {
-		$bp = buddypress();
-
 		register_post_type( 'foo', array(
 			'label'   => 'foo',
 			'public'   => true,
@@ -28,10 +26,6 @@ class BP_Tests_Activity_Actions extends BP_UnitTestCase {
 		$this->assertTrue( $this->activity_exists_for_post( $post_id, 'new_foo' ), 'Published post type should have activity' );
 
 		_unregister_post_type( 'foo' );
-
-		// Reset globals
-		unset( $bp->activity->actions->activity->new_foo );
-		$bp->activity->track = array();
 	}
 
 	/**
@@ -39,8 +33,6 @@ class BP_Tests_Activity_Actions extends BP_UnitTestCase {
 	 * @group activity_tracking
 	 */
 	public function test_bp_activity_catch_transition_post_type_status_publish_to_publish() {
-		$bp = buddypress();
-
 		register_post_type( 'foo', array(
 			'label'   => 'foo',
 			'public'   => true,
@@ -68,10 +60,6 @@ class BP_Tests_Activity_Actions extends BP_UnitTestCase {
 		$this->assertFalse( $this->activity_exists_for_post( $post_id, 'new_foo' ), 'Updating a post type should not create a new activity' );
 
 		_unregister_post_type( 'foo' );
-
-		// Reset globals
-		unset( $bp->activity->actions->activity->new_foo );
-		$bp->activity->track = array();
 	}
 
 	/**
@@ -79,8 +67,6 @@ class BP_Tests_Activity_Actions extends BP_UnitTestCase {
 	 * @group activity_tracking
 	 */
 	public function test_bp_activity_catch_transition_post_type_status_publish_password() {
-		$bp = buddypress();
-
 		register_post_type( 'foo', array(
 			'label'   => 'foo',
 			'public'   => true,
@@ -106,10 +92,6 @@ class BP_Tests_Activity_Actions extends BP_UnitTestCase {
 		$this->assertFalse( $this->activity_exists_for_post( $post_id, 'new_foo' ), 'Password protected post type should not have activity' );
 
 		_unregister_post_type( 'foo' );
-
-		// Reset globals
-		unset( $bp->activity->actions->activity->new_foo );
-		$bp->activity->track = array();
 	}
 
 	/**
@@ -117,8 +99,6 @@ class BP_Tests_Activity_Actions extends BP_UnitTestCase {
 	 * @group activity_tracking
 	 */
 	public function test_bp_activity_catch_transition_post_type_status_publish_trash() {
-		$bp = buddypress();
-
 		register_post_type( 'foo', array(
 			'label'   => 'foo',
 			'public'   => true,
@@ -141,10 +121,6 @@ class BP_Tests_Activity_Actions extends BP_UnitTestCase {
 		$this->assertFalse( $this->activity_exists_for_post( $post_id, 'new_foo' ), 'Unpublished post type should not have activity' );
 
 		_unregister_post_type( 'foo' );
-
-		// Reset globals
-		unset( $bp->activity->actions->activity->new_foo );
-		$bp->activity->track = array();
 	}
 
 	protected function activity_exists_for_post( $post_id, $action ) {
diff --git tests/phpunit/testcases/activity/functions.php tests/phpunit/testcases/activity/functions.php
index 8a3304f..273d926 100644
--- tests/phpunit/testcases/activity/functions.php
+++ tests/phpunit/testcases/activity/functions.php
@@ -763,8 +763,6 @@ Bar!';
 			return;
 		}
 
-		$bp = buddypress();
-
 		register_post_type( 'foo', array(
 			'label'   => 'foo',
 			'public'   => true,
@@ -800,10 +798,6 @@ Bar!';
 		$this->assertSame( $expected, $a_obj->action );
 
 		_unregister_post_type( 'foo' );
-
-		// Reset globals
-		unset( $bp->activity->actions->activity->new_foo );
-		$bp->activity->track = array();
 	}
 
 	/**
@@ -816,8 +810,6 @@ Bar!';
 			return;
 		}
 
-		$bp = buddypress();
-
 		$b = $this->factory->blog->create();
 		$u = $this->factory->user->create();
 
@@ -863,10 +855,6 @@ Bar!';
 		$expected = sprintf( '%s wrote a new %s, on the site %s', $user_link, $post_link, '<a href="' . $blog_url . '">' . get_blog_option( $a_obj->item_id, 'blogname' ) . '</a>' );
 
 		$this->assertSame( $expected, $a_obj->action );
-
-		// Reset globals
-		unset( $bp->activity->actions->activity->new_foo );
-		$bp->activity->track = array();
 	}
 
 	/**
@@ -874,7 +862,6 @@ Bar!';
 	 * @group bp_activity_get_actions
 	 */
 	public function test_bp_activity_get_actions_should_sort_by_position() {
-		$old_actions = bp_activity_get_actions();
 		buddypress()->activity->actions = new stdClass;
 
 		register_post_type( 'foo5', array(
@@ -916,8 +903,6 @@ Bar!';
 		);
 		$foo_actions = (array) $actions->foo;
 		$this->assertEquals( $expected, array_values( wp_list_pluck( $foo_actions, 'key' ) ) );
-
-		buddypress()->activity->actions = $old_actions;
 	}
 
 	/**
@@ -929,8 +914,6 @@ Bar!';
 			return;
 		}
 
-		$bp = buddypress();
-
 		$labels = array(
 			'name'                 => 'bars',
 			'singular_name'        => 'bar',
@@ -974,10 +957,6 @@ Bar!';
 		$this->assertSame( $expected, $a_obj->action );
 
 		_unregister_post_type( 'foo' );
-
-		// Reset globals
-		unset( $bp->activity->actions->activity->foo_bar );
-		$bp->activity->track = array();
 	}
 
 	/**
@@ -990,9 +969,6 @@ Bar!';
 			return;
 		}
 
-		$bp = buddypress();
-		$reset = $bp->activity->actions;
-
 		$b = $this->factory->blog->create();
 		$u = $this->factory->user->create();
 
@@ -1041,10 +1017,6 @@ Bar!';
 		$expected = sprintf( '%1$s shared a new <a href="%2$s">bar</a>, on the site %3$s', $user_link, $post_url, '<a href="' . $blog_url . '">' . get_blog_option( $a_obj->item_id, 'blogname' ) . '</a>' );
 
 		$this->assertSame( $expected, $a_obj->action );
-
-		// Reset globals
-		unset( $bp->activity->actions->activity->new_foo );
-		$bp->activity->track = array();
 	}
 
 	/**
@@ -1081,10 +1053,6 @@ Bar!';
 		$this->assertSame( $bp->blogs->id, $a['activities'][0]->component );
 
 		remove_post_type_support( 'page', 'buddypress-activity' );
-
-		// Reset globals
-		unset( $bp->activity->actions->blogs->new_page );
-		$bp->activity->track = array();
 	}
 
 	/**
@@ -1126,6 +1094,81 @@ Bar!';
 	}
 
 	/**
+	 * @group activity_action
+	 * @group bp_activity_format_activity_action_custom_post_type_post_ms
+	 * @group post_type_comment_activities
+	 */
+	public function test_bp_activity_format_activity_action_custom_post_type_comment() {
+		if ( is_multisite() ) {
+			$b = $this->factory->blog->create();
+			switch_to_blog( $b );
+			add_filter( 'comment_flood_filter', '__return_false' );
+		} else {
+			$b = get_current_blog_id();
+		}
+
+		$u = $this->factory->user->create();
+		$userdata = get_userdata( $u );
+
+		$labels = array(
+			'name'                       => 'bars',
+			'singular_name'              => 'bar',
+			'bp_activity_new_comment'    => __( '%1$s commented on the <a href="%2$s">bar</a>', 'buddypress' ),
+			'bp_activity_new_comment_ms' => __( '%1$s commented on the <a href="%2$s">bar</a>, on the site %3$s', 'buddypress' ),
+		);
+
+		register_post_type( 'foo', array(
+			'labels'   => $labels,
+			'public'   => true,
+			'supports' => array( 'buddypress-activity', 'comments' ),
+			'bp_activity' => array(
+				'action_id'         => 'new_bar',
+				'comment_action_id' => 'new_bar_comment',
+			),
+		) );
+
+		// Build the actions to fetch the tracking args
+		bp_activity_get_actions();
+
+		$p = $this->factory->post->create( array(
+			'post_author' => $u,
+			'post_type'   => 'foo',
+		) );
+
+		$c = wp_new_comment( array(
+			'comment_post_ID'      => $p,
+			'comment_author'       => $userdata->user_nicename,
+			'comment_author_url'   => 'http://buddypress.org',
+			'comment_author_email' => $userdata->user_email,
+			'comment_content'      => 'this is a blog comment',
+			'comment_type'         => '',
+			'comment_parent'       => 0,
+			'user_id'              => $u,
+		) );
+
+		$a = bp_activity_get_activity_id( array( 'type' => 'new_bar_comment' ) );
+
+		$a_obj = new BP_Activity_Activity( $a );
+
+		$user_link    = bp_core_get_userlink( $u );
+		$comment_url  = get_comment_link( $c );
+
+		_unregister_post_type( 'foo' );
+
+		if ( is_multisite() ) {
+			$blog_url  = get_blog_option( $a_obj->item_id, 'home' );
+			restore_current_blog();
+			remove_filter( 'comment_flood_filter', '__return_false' );
+
+			$expected = sprintf( $labels['bp_activity_new_comment_ms'], $user_link, $comment_url, '<a href="' . $blog_url . '">' . get_blog_option( $a_obj->item_id, 'blogname' ) . '</a>' );
+		} else {
+			$expected = sprintf( $labels['bp_activity_new_comment'], $user_link, $comment_url );
+		}
+
+		$this->assertSame( $expected, $a_obj->action );
+	}
+
+	/**
 	 * @group bp_activity_new_comment
 	 * @group cache
 	 */
diff --git tests/phpunit/testcases/activity/template.php tests/phpunit/testcases/activity/template.php
index db33cda..090701a 100644
--- tests/phpunit/testcases/activity/template.php
+++ tests/phpunit/testcases/activity/template.php
@@ -909,6 +909,7 @@ class BP_Tests_Activity_Template extends BP_UnitTestCase {
 	/**
 	 * @group filter_query
 	 * @group BP_Activity_Query
+	 * @group post_type_comment_activities
 	 */
 	function test_bp_has_activities_with_filter_query_compare_regex() {
 		$u1 = $this->factory->user->create();
@@ -1299,6 +1300,7 @@ class BP_Tests_Activity_Template extends BP_UnitTestCase {
 
 	/**
 	 * @group bp_has_activities
+	 * @group post_type_comment_activities
 	 */
 	public function test_bp_has_activities_with_type_new_blog_comments() {
 		add_filter( 'bp_disable_blogforum_comments', '__return_false' );
@@ -1430,6 +1432,89 @@ class BP_Tests_Activity_Template extends BP_UnitTestCase {
 	}
 
 	/**
+	 * @group bp_activity_can_comment
+	 */
+	public function test_bp_activity_can_comment() {
+		global $activities_template;
+		$reset_activities_template = $activities_template;
+
+		$activities_template = new stdClass;
+		$activities_template->disable_blogforum_replies = true;
+		$activities_template->activity = (object) array( 'type' => 'activity_comment' );
+
+		$this->assertFalse( bp_activity_can_comment(), 'bp_activity_can_comment() should return false if the activity type is activity_comment' );
+
+		$types = array(
+			'new_blog_post',
+			'new_blog_comment',
+			'new_forum_topic',
+			'new_forum_post'
+		);
+
+		foreach ( $types as $type_false ) {
+			$activities_template->activity->type = $type_false;
+			$this->assertFalse( bp_activity_can_comment(), 'Comments about blog or forum posts/replies are disabled' );
+		}
+
+		$activities_template->disable_blogforum_replies = false;
+		add_filter( 'bp_disable_blogforum_comments', '__return_false' );
+
+		foreach ( $types as $type_true ) {
+			$activities_template->activity->type = $type_true;
+			$this->assertTrue( bp_activity_can_comment(), 'Comments about blog or forum posts/replies are enabled' );
+		}
+
+		remove_filter( 'bp_disable_blogforum_comments', '__return_false' );
+
+		// clean up!
+		$activities_template = $reset_activities_template;
+	}
+
+	/**
+	 * @group bp_activity_can_comment
+	 */
+	public function test_bp_activity_can_comment_post_type_activity() {
+		global $activities_template;
+		$bp = buddypress();
+
+		$reset_activities_template = $activities_template;
+		$reset_activity_track = $bp->activity->track;
+
+		$activities_template = new stdClass;
+		$activities_template->disable_blogforum_replies = true;
+
+		register_post_type( 'foo', array(
+			'label'   => 'foo',
+			'public'   => true,
+			'supports' => array( 'buddypress-activity' ),
+		) );
+
+		$bp->activity->track = bp_activity_get_post_types_tracking_args();
+
+		$activities_template->activity = (object) array( 'type' => 'new_foo' );
+
+		$this->assertTrue( bp_activity_can_comment(), 'If post type does not support comments, a post type activity can be commented' );
+
+		add_post_type_support( 'foo', 'comments' );
+
+		$bp->activity->track = bp_activity_get_post_types_tracking_args();
+
+		$this->assertFalse( bp_activity_can_comment(), 'If post type support comments, a post type activity cannot be commented' );
+
+		$bp_activity_support = (array) $bp->activity->track['new_foo'];
+		$bp_activity_support['activity_comment'] = true;
+
+		bp_activity_set_post_type_tracking_args( 'foo', $bp_activity_support );
+		$bp->activity->track = bp_activity_get_post_types_tracking_args();
+
+		$this->assertTrue( bp_activity_can_comment(), 'If post type supports activity comments, a post type activity can be commented' );
+
+		// clean up!
+		$activities_template = $reset_activities_template;
+		$bp->activity->track = $reset_activity_track;
+	}
+
+	/**
 	 * @group bp_activity_has_more_items
 	 */
 	public function test_bp_activity_has_more_items_no_count_total_false() {
diff --git tests/phpunit/testcases/blogs/activity.php tests/phpunit/testcases/blogs/activity.php
index 08941e2..d7595ef 100644
--- tests/phpunit/testcases/blogs/activity.php
+++ tests/phpunit/testcases/blogs/activity.php
@@ -156,6 +156,7 @@ class BP_Tests_Blogs_Activity extends BP_UnitTestCase {
 	/**
 	 * @group activity_action
 	 * @group bp_blogs_format_activity_action_new_blog_comment
+	 * @group post_type_comment_activities
 	 */
 	public function test_bp_blogs_format_activity_action_new_blog_comment_ms_nonrootblog() {
 		if ( ! is_multisite() ) {
@@ -318,9 +319,7 @@ class BP_Tests_Blogs_Activity extends BP_UnitTestCase {
 			return;
 		}
 
-		$bp = buddypress();
-		$activity_actions = $bp->activity->actions;
-		$bp->activity->actions = new stdClass();
+		buddypress()->activity->actions = new stdClass();
 
 		$u = $this->factory->user->create();
 		$p = wp_insert_post( array(
@@ -346,10 +345,6 @@ class BP_Tests_Blogs_Activity extends BP_UnitTestCase {
 		$expected = sprintf( '%s wrote a new post, %s', $user_link, $post_link );
 
 		$this->assertSame( $expected, $a_obj['activities'][0]->action );
-
-		// Reset activity actions
-		$bp->activity->actions = $activity_actions;
-		$bp->activity->track = array();
 	}
 
 	/**
@@ -361,9 +356,7 @@ class BP_Tests_Blogs_Activity extends BP_UnitTestCase {
 			return;
 		}
 
-		$bp = buddypress();
-		$activity_actions = $bp->activity->actions;
-		$bp->activity->actions = new stdClass();
+		buddypress()->activity->actions = new stdClass();
 
 		$u = $this->factory->user->create();
 		$p = wp_insert_post( array(
@@ -407,10 +400,277 @@ class BP_Tests_Blogs_Activity extends BP_UnitTestCase {
 		) );
 
 		$this->assertSame( $expected, $a_obj['activities'][0]->action );
+	}
+
+	/**
+	 * @group bp_blogs_sync_add_from_activity_comment
+	 * @group post_type_comment_activities
+	 */
+	public function test_bp_blogs_sync_add_from_activity_comment() {
+		$old_user = get_current_user_id();
+		$u = $this->factory->user->create();
+		$this->set_current_user( $u );
+		$userdata = get_userdata( $u );
+
+		// let's use activity comments instead of single "new_blog_comment" activity items
+		add_filter( 'bp_disable_blogforum_comments', '__return_false' );
+
+		// create the blog post
+		$post_id = $this->factory->post->create( array(
+			'post_status' => 'publish',
+			'post_type'   => 'post',
+			'post_title'  => 'Test activity comment to post comment',
+		) );
+
+		// grab the activity ID for the activity comment
+		$a1 = bp_activity_get_activity_id( array(
+			'type'      => 'new_blog_post',
+			'component' => buddypress()->blogs->id,
+			'filter'    => array(
+				'item_id' => get_current_blog_id(),
+				'secondary_item_id' => $post_id
+			),
+		) );
+
+		$a2 = bp_activity_new_comment( array(
+			'content'     => 'this content shoud be in a new post comment',
+			'user_id'     => $u,
+			'activity_id' => $a1,
+		) );
+
+		$approved_comments = get_approved_comments( $post_id );
+		$comment = reset( $approved_comments );
+
+		$this->assertTrue( (int) $comment->comment_ID === (int) bp_activity_get_meta( $a2, 'bp_blogs_post_comment_id' ), 'The comment ID should be in the activity meta' );
+		$this->assertTrue( (int) $a2 === (int) get_comment_meta( $comment->comment_ID, 'bp_activity_comment_id', true ), 'The activity ID should be in the comment meta' );
+
+		// reset
+		remove_filter( 'bp_disable_blogforum_comments', '__return_false' );
+
+		$this->set_current_user( $old_user );
+	}
+
+	/**
+	 * @group bp_blogs_sync_delete_from_activity_comment
+	 * @group post_type_comment_activities
+	 */
+	public function test_bp_blogs_sync_delete_from_activity_comment() {
+		$old_user = get_current_user_id();
+		$u = $this->factory->user->create();
+		$this->set_current_user( $u );
+		$userdata = get_userdata( $u );
+
+		// let's use activity comments instead of single "new_blog_comment" activity items
+		add_filter( 'bp_disable_blogforum_comments', '__return_false' );
+
+		// create the blog post
+		$post_id = $this->factory->post->create( array(
+			'post_status' => 'publish',
+			'post_type'   => 'post',
+			'post_title'  => 'Test activity comment to post comment',
+		) );
+
+		// grab the activity ID for the activity comment
+		$a1 = bp_activity_get_activity_id( array(
+			'type'      => 'new_blog_post',
+			'component' => buddypress()->blogs->id,
+			'filter'    => array(
+				'item_id' => get_current_blog_id(),
+				'secondary_item_id' => $post_id
+			),
+		) );
+
+		$a2 = bp_activity_new_comment( array(
+			'content'     => 'the generated comment should be deleted once the activity comment is removed',
+			'user_id'     => $u,
+			'activity_id' => $a1,
+		) );
+
+		bp_activity_delete_comment( $a1, $a2 );
+
+		$post_comments = get_comments( array( 'post_id' => $post_id ) );
+
+		$this->assertEmpty( $post_comments, 'A post comment should be deleted when the corresponding activity is' );
+
+		// reset
+		remove_filter( 'bp_disable_blogforum_comments', '__return_false' );
+
+		$this->set_current_user( $old_user );
+	}
+
+	/**
+	 * @group bp_blogs_sync_activity_edit_to_post_comment
+	 * @group post_type_comment_activities
+	 */
+	public function test_bp_blogs_sync_activity_edit_to_post_comment_spam_unspam_activity_comment() {
+		$old_user = get_current_user_id();
+		$u = $this->factory->user->create();
+		$this->set_current_user( $u );
+		$userdata = get_userdata( $u );
+
+		// let's use activity comments instead of single "new_blog_comment" activity items
+		add_filter( 'bp_disable_blogforum_comments', '__return_false' );
+
+		// create the blog post
+		$post_id = $this->factory->post->create( array(
+			'post_status' => 'publish',
+			'post_type'   => 'post',
+			'post_title'  => 'Test activity comment to post comment',
+		) );
+
+		// grab the activity ID for the activity comment
+		$a1 = bp_activity_get_activity_id( array(
+			'type'      => 'new_blog_post',
+			'component' => buddypress()->blogs->id,
+			'filter'    => array(
+				'item_id' => get_current_blog_id(),
+				'secondary_item_id' => $post_id
+			),
+		) );
+
+		$a2 = bp_activity_new_comment( array(
+			'content'     => 'the generated comment should be spamed/unspamed once the activity comment is spamed/unspamed',
+			'user_id'     => $u,
+			'activity_id' => $a1,
+		) );
+
+		$activity = new BP_Activity_Activity( $a2 );
+
+		bp_activity_mark_as_spam( $activity );
+		$activity->save();
+
+		$post_comments = get_comments( array( 'post_id' => $post_id, 'status' => 'approve' ) );
+
+		$this->assertEmpty( $post_comments, 'A post comment should be spammed when the corresponding activity is spammed' );
+
+		bp_activity_mark_as_ham( $activity );
+		$activity->save();
+
+		$post_comments = get_comments( array( 'post_id' => $post_id, 'status' => 'approve' ) );
+		$comment = reset( $post_comments );
+
+		$this->assertTrue( (int) $comment->comment_ID === (int) bp_activity_get_meta( $a2, 'bp_blogs_post_comment_id' ), 'The comment ID should be in the activity meta' );
+		$this->assertTrue( (int) $a2 === (int) get_comment_meta( $comment->comment_ID, 'bp_activity_comment_id', true ), 'The activity ID should be in the comment meta' );
+
+		// reset
+		remove_filter( 'bp_disable_blogforum_comments', '__return_false' );
+
+		$this->set_current_user( $old_user );
+	}
+
+	/**
+	 * @group bp_blogs_sync_activity_edit_to_post_comment
+	 * @group post_type_comment_activities
+	 */
+	public function test_bp_blogs_sync_activity_edit_to_post_comment_spam_activity_comment_unspam_post_comment() {
+		$old_user = get_current_user_id();
+		$u = $this->factory->user->create();
+		$this->set_current_user( $u );
+		$userdata = get_userdata( $u );
+
+		// let's use activity comments instead of single "new_blog_comment" activity items
+		add_filter( 'bp_disable_blogforum_comments', '__return_false' );
+
+		// create the blog post
+		$post_id = $this->factory->post->create( array(
+			'post_status' => 'publish',
+			'post_type'   => 'post',
+			'post_title'  => 'Test activity comment to post comment',
+		) );
+
+		// grab the activity ID for the activity comment
+		$a1 = bp_activity_get_activity_id( array(
+			'type'      => 'new_blog_post',
+			'component' => buddypress()->blogs->id,
+			'filter'    => array(
+				'item_id' => get_current_blog_id(),
+				'secondary_item_id' => $post_id
+			),
+		) );
+
+		$a2 = bp_activity_new_comment( array(
+			'content'     => 'the generated comment should be spamed/unspamed once the activity comment is spamed/unspamed',
+			'user_id'     => $u,
+			'activity_id' => $a1,
+		) );
+
+		$c = bp_activity_get_meta( $a2, 'bp_blogs_post_comment_id' );
+
+		$activity = new BP_Activity_Activity( $a2 );
+
+		bp_activity_mark_as_spam( $activity );
+		$activity->save();
+
+		wp_unspam_comment( $c );
+
+		$post_comments = get_comments( array( 'post_id' => $post_id, 'status' => 'approve' ) );
+		$comment = reset( $post_comments );
+
+		$this->assertTrue( (int) $comment->comment_ID === (int) bp_activity_get_meta( $a2, 'bp_blogs_post_comment_id' ), 'The comment ID should be in the activity meta' );
+		$this->assertTrue( (int) $a2 === (int) get_comment_meta( $comment->comment_ID, 'bp_activity_comment_id', true ), 'The activity ID should be in the comment meta' );
+
+		// reset
+		remove_filter( 'bp_disable_blogforum_comments', '__return_false' );
+
+		$this->set_current_user( $old_user );
+	}
+
+	/**
+	 * @group bp_blogs_sync_activity_edit_to_post_comment
+	 * @group post_type_comment_activities
+	 * @group imath
+	 */
+	public function test_bp_blogs_sync_activity_edit_to_post_comment_trash_comment_ham_activity() {
+		$old_user = get_current_user_id();
+		$u = $this->factory->user->create();
+		$this->set_current_user( $u );
+		$userdata = get_userdata( $u );
+
+		// let's use activity comments instead of single "new_blog_comment" activity items
+		add_filter( 'bp_disable_blogforum_comments', '__return_false' );
+
+		// create the blog post
+		$post_id = $this->factory->post->create( array(
+			'post_status' => 'publish',
+			'post_type'   => 'post',
+			'post_title'  => 'Test activity comment to post comment',
+		) );
+
+		// grab the activity ID for the activity comment
+		$a1 = bp_activity_get_activity_id( array(
+			'type'      => 'new_blog_post',
+			'component' => buddypress()->blogs->id,
+			'filter'    => array(
+				'item_id' => get_current_blog_id(),
+				'secondary_item_id' => $post_id
+			),
+		) );
+
+		$a2 = bp_activity_new_comment( array(
+			'content'     => 'the generated comment should be spamed/unspamed once the activity comment is spamed/unspamed',
+			'user_id'     => $u,
+			'activity_id' => $a1,
+		) );
+
+		$c = bp_activity_get_meta( $a2, 'bp_blogs_post_comment_id' );
+
+		wp_trash_comment( $c );
+
+		$activity = new BP_Activity_Activity( $a2 );
+
+		bp_activity_mark_as_ham( $activity );
+		$activity->save();
+
+		$post_comments = get_comments( array( 'post_id' => $post_id, 'status' => 'approve' ) );
+		$comment = reset( $post_comments );
+
+		$this->assertTrue( (int) $comment->comment_ID === (int) bp_activity_get_meta( $a2, 'bp_blogs_post_comment_id' ), 'The comment ID should be in the activity meta' );
+		$this->assertTrue( (int) $a2 === (int) get_comment_meta( $comment->comment_ID, 'bp_activity_comment_id', true ), 'The activity ID should be in the comment meta' );
+
+		// reset
+		remove_filter( 'bp_disable_blogforum_comments', '__return_false' );
 
-		// Reset activity actions
-		$bp->activity->actions = $activity_actions;
-		$bp->activity->track = array();
+		$this->set_current_user( $old_user );
 	}
 
 	/**
diff --git tests/phpunit/testcases/blogs/filters.php tests/phpunit/testcases/blogs/filters.php
index a0fc961..3d2af7f 100644
--- tests/phpunit/testcases/blogs/filters.php
+++ tests/phpunit/testcases/blogs/filters.php
@@ -10,11 +10,6 @@ class BP_Tests_Blogs_Filters extends BP_UnitTestCase {
 	public function setUp() {
 		parent::setUp();
 
-		$bp = buddypress();
-
-		$this->activity_actions = $bp->activity->actions;
-		$bp->activity->actions = new stdClass();
-
 		$this->custom_post_types = array( 'using_old_filter' );
 
 		register_post_type( 'using_old_filter', array(
@@ -35,10 +30,6 @@ class BP_Tests_Blogs_Filters extends BP_UnitTestCase {
 		_unregister_post_type( 'using_old_filter' );
 		remove_filter( 'bp_blogs_record_post_post_types',    array( $this, 'filter_post_types'), 10, 1 );
 		remove_filter( 'bp_blogs_record_comment_post_types', array( $this, 'filter_post_types'), 10, 1 );
-
-		// Reset activity actions
-		$bp->activity->actions = $this->activity_actions;
-		$bp->activity->track = array();
 	}
 
 	/**
@@ -64,6 +55,7 @@ class BP_Tests_Blogs_Filters extends BP_UnitTestCase {
 
 	/**
 	 * @goup bp_blogs_record_comment
+	 * @group post_type_comment_activities
 	 */
 	public function test_bp_blogs_record_comment() {
 		$u = $this->factory->user->create();
@@ -89,6 +81,7 @@ class BP_Tests_Blogs_Filters extends BP_UnitTestCase {
 
 	/**
 	 * @goup bp_blogs_record_comment_sync_activity_comment
+	 * @group post_type_comment_activities
 	 */
 	public function test_bp_blogs_record_comment_sync_activity_comment() {
 		$u = $this->factory->user->create();
diff --git tests/phpunit/testcases/blogs/functions.php tests/phpunit/testcases/blogs/functions.php
index a058db2..d7fad14 100644
--- tests/phpunit/testcases/blogs/functions.php
+++ tests/phpunit/testcases/blogs/functions.php
@@ -513,6 +513,7 @@ class BP_Tests_Blogs_Functions extends BP_UnitTestCase {
 
 	/**
 	 * @group bp_blogs_catch_transition_post_status
+	 * @group post_type_comment_activities
 	 */
 	public function test_update_blog_post_and_new_blog_comment_and_activity_comment_meta() {
 		// save the current user and override logged-in user
@@ -596,7 +597,8 @@ class BP_Tests_Blogs_Functions extends BP_UnitTestCase {
 
 	/**
 	 * @group bp_blogs_transition_activity_status
-	 * @group bp_blogs_remove_comment
+	 * @group bp_blogs_post_type_remove_comment
+	 * @group post_type_comment_activities
 	 */
 	public function test_bp_blogs_remove_comment_should_remove_spammed_activity_comment() {
 		// save the current user and override logged-in user
@@ -658,6 +660,48 @@ class BP_Tests_Blogs_Functions extends BP_UnitTestCase {
 	}
 
 	/**
+	 * @group bp_blogs_post_type_remove_comment
+	 * @group post_type_comment_activities
+	 */
+	public function test_bp_blogs_post_type_remove_comment() {
+		$old_user = get_current_user_id();
+		$u = $this->factory->user->create();
+		$this->set_current_user( $u );
+		$userdata = get_userdata( $u );
+
+		// create the blog post
+		$p = $this->factory->post->create( array(
+			'post_status' => 'publish',
+			'post_type' => 'post',
+			'post_title' => 'First title',
+		) );
+
+		$c = wp_new_comment( array(
+			'comment_post_ID'      => $p,
+			'comment_author'       => $userdata->user_nicename,
+			'comment_author_url'   => 'http://buddypress.org',
+			'comment_author_email' => $userdata->user_email,
+			'comment_content'      => 'this comment will be removed',
+			'comment_type'         => '',
+			'comment_parent'       => 0,
+			'user_id'              => $u,
+		) );
+
+		// An activity should exist
+		$a = bp_activity_get_activity_id( array(
+			'user_id' => $u,
+			'type'    => 'new_blog_comment'
+		) );
+
+		// now permanently delete the comment
+		wp_delete_comment( $c, true );
+
+		// The activity comment should no longer exist
+		$ac = bp_activity_get( array( 'in' => $a ) );
+		$this->assertTrue( empty( $ac['activities'] ) );
+	}
+
+	/**
 	 * @group bp_blogs_catch_transition_post_status
 	 */
 	public function test_bp_blogs_is_blog_trackable_false_publish_post() {
@@ -714,6 +758,7 @@ class BP_Tests_Blogs_Functions extends BP_UnitTestCase {
 	/**
 	 * @group bp_blogs_record_comment
 	 * @group unique
+	 * @group post_type_comment_activities
 	 */
 	public function test_bp_blogs_record_comment_no_duplicate_activity_comments() {
 		// save the current user and override logged-in user
@@ -777,6 +822,7 @@ class BP_Tests_Blogs_Functions extends BP_UnitTestCase {
 
 	/**
 	 * @group bp_blogs_record_comment
+	 * @group post_type_comment_activities
 	 */
 	public function test_bp_blogs_record_comment_should_record_parent_blog_post_activity_if_not_found() {
 		// Save the current user and override logged-in user
@@ -826,12 +872,110 @@ class BP_Tests_Blogs_Functions extends BP_UnitTestCase {
 			),
 		) );
 
+		remove_filter( 'bp_disable_blogforum_comments', '__return_false' );
+
 		// Assert that activity item for blog post was created after adding a comment
 		$this->assertNotNull( $a1, 'Activity item was not created for existing blog post when recording post comment.' );
 
 		$this->set_current_user( $old_user );
 	}
 
+	/**
+	 * @group bp_blogs_comment_sync_activity_comment
+	 * @group post_type_comment_activities
+	 */
+	public function test_bp_blogs_comment_sync_activity_comment_for_custom_post_type() {
+		if ( is_multisite() ) {
+			$b = $this->factory->blog->create();
+			switch_to_blog( $b );
+			add_filter( 'comment_flood_filter', '__return_false' );
+		} else {
+			$b = get_current_blog_id();
+		}
+
+		$u = $this->factory->user->create();
+		$userdata = get_userdata( $u );
+
+		$labels = array(
+			'name'                       => 'bars',
+			'singular_name'              => 'bar',
+		);
+
+		register_post_type( 'foo', array(
+			'labels'   => $labels,
+			'public'   => true,
+			'supports' => array( 'comments' ),
+		) );
+
+		add_post_type_support( 'foo', 'buddypress-activity' );
+
+		bp_activity_set_post_type_tracking_args( 'foo', array(
+			'comment_action_id' => 'new_foo_comment',
+		) );
+
+		add_filter( 'bp_disable_blogforum_comments', '__return_false' );
+
+		$p = $this->factory->post->create( array(
+			'post_author' => $u,
+			'post_type'   => 'foo',
+		) );
+
+		$a1 = bp_activity_get_activity_id( array(
+			'type'      => 'new_foo',
+			'filter'    => array(
+				'item_id' => $b,
+				'secondary_item_id' => $p
+			),
+		) );
+
+		$c = wp_new_comment( array(
+			'comment_post_ID'      => $p,
+			'comment_author'       => $userdata->user_nicename,
+			'comment_author_url'   => 'http://buddypress.org',
+			'comment_author_email' => $userdata->user_email,
+			'comment_content'      => 'this is a foo comment',
+			'comment_type'         => '',
+			'comment_parent'       => 0,
+			'user_id'              => $u,
+		) );
+
+		$a2 = bp_activity_new_comment( array(
+			'content'     => 'this should generate a new foo comment',
+			'user_id'     => $u,
+			'activity_id' => $a1,
+		) );
+
+		$activity_args = array(
+			'type'              => 'activity_comment',
+			'display_comments'  => 'stream',
+			'meta_query'        => array( array(
+				'key'       => 'bp_blogs_foo_comment_id',
+				'compare'   => 'exists',
+			) )
+		);
+
+		$a = bp_activity_get( $activity_args );
+		$aids = wp_list_pluck( $a['activities'], 'id' );
+		$cids = wp_list_pluck( get_approved_comments( $p ), 'comment_ID' );
+
+		foreach ( $aids as $aid ) {
+			$this->assertTrue( in_array( bp_activity_get_meta( $aid, 'bp_blogs_foo_comment_id' ), $cids ), 'The comment ID should be in the activity meta' );
+		}
+
+		foreach ( $cids as $cid ) {
+			$this->assertTrue( in_array( get_comment_meta( $cid, 'bp_activity_comment_id', true ), $aids ), 'The activity ID should be in the comment meta' );
+		}
+
+		_unregister_post_type( 'foo' );
+
+		if ( is_multisite() ) {
+			restore_current_blog();
+			remove_filter( 'comment_flood_filter', '__return_false' );
+		}
+
+		remove_filter( 'bp_disable_blogforum_comments', '__return_false' );
+	}
+
 	public function count_activity_comment_saved() {
 		$this->activity_saved_comment_count += 1;
 	}
