Integration Guide
BuddyPress Moderation Pro overviewPremiumGet BuddyPress Moderation Pro →
Learn how to integrate BuddyPress Moderation Pro with your theme or plugin.
What You’ll Learn
Section titled “What You’ll Learn”- Add moderation support to custom themes
- Integrate moderation with custom plugins
- Extend moderation for custom content types
- Customize the moderation UI
- Handle moderation events in your code
Prerequisites
Section titled “Prerequisites”- WordPress 6.0+
- PHP 8.0+
- BuddyPress 7.0+
- BuddyPress Moderation Pro 4.0+
- Basic understanding of WordPress hooks and filters
Quick Start
Section titled “Quick Start”Check if Plugin is Active
Section titled “Check if Plugin is Active”Before using any moderation functions, verify the plugin is loaded:
if ( function_exists( 'bmpro_user_can_report' ) ) { // Plugin is active, safe to use functions}
// Or check for the classif ( class_exists( 'Buddypress_Moderation_Pro' ) ) { // Plugin is active}Add a Basic Report Button
Section titled “Add a Basic Report Button”add_action( 'my_custom_content_actions', 'add_moderation_button' );
function add_moderation_button( $content_id ) { // Check if user can report if ( ! bmpro_user_can_report() ) { return; }
$flag_text = bmpro_get_flag_button_text( 'flag' );
printf( '<button class="bmpro-flag-btn" data-content-id="%d">%s</button>', esc_attr( $content_id ), esc_html( $flag_text ) );}Theme Integration
Section titled “Theme Integration”Adding Theme Support
Section titled “Adding Theme Support”Register your theme as a supported theme for built-in styling:
add_filter( 'buddypress_moderation_theme_suuport', 'my_theme_moderation_support' );
function my_theme_moderation_support( $themes ) { $themes[] = 'my-theme-slug'; return $themes;}Tip: Supported themes automatically receive optimized CSS and button placement.
Custom Button Placement
Section titled “Custom Button Placement”Override default button placement in your theme:
// Remove default activity buttonremove_action( 'bp_activity_entry_meta', array( Buddypress_Moderation_Pro_Activity_Moderation::class, 'show_flag_button') );
// Add custom placementadd_action( 'my_theme_activity_actions', 'custom_flag_button_placement' );
function custom_flag_button_placement() { if ( ! bmpro_user_can_report() ) { return; }
// Your custom button HTML do_action( 'bmpro_render_activity_flag_button' );}Styling the Modal
Section titled “Styling the Modal”Override modal styles in your theme:
/* Custom modal styling */.bmpro-modal { --bmpro-modal-bg: #ffffff; --bmpro-modal-border-radius: 12px; --bmpro-primary-color: #0066cc;}
.bmpro-modal-wrap { background: var(--bmpro-modal-bg); border-radius: var(--bmpro-modal-border-radius); box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);}
.bmpro-modal-button { background: var(--bmpro-primary-color); border-radius: 6px; padding: 12px 24px;}Template Overrides
Section titled “Template Overrides”Copy templates to your theme for customization:
your-theme/├── buddypress-moderation-pro/│ ├── bmpo-bp-moderations.php│ ├── blocking.php│ └── blocked.php// In your theme's functions.phpadd_filter( 'bmpro_template_path', 'my_theme_moderation_templates' );
function my_theme_moderation_templates( $path ) { $theme_template = get_template_directory() . '/buddypress-moderation-pro/';
if ( file_exists( $theme_template ) ) { return $theme_template; }
return $path;}Plugin Integration
Section titled “Plugin Integration”Adding Custom Content Type Support
Section titled “Adding Custom Content Type Support”Step 1: Register Content Type
add_filter( 'bmpro_content_to_flag', 'register_my_content_type' );
function register_my_content_type( $content_types ) { $content_types['my_custom_content'] = __( 'My Custom Content', 'my-plugin' ); return $content_types;}Step 2: Handle Report Submission
add_action( 'wp_ajax_bmpro_flag_my_custom_content_function', 'handle_my_content_report' );
function handle_my_content_report() { // Verify nonce check_ajax_referer( 'bmpro_ajax_nonce', 'nonce' );
$content_id = absint( $_POST['content_id'] ); $reason = sanitize_text_field( $_POST['reason'] ); $details = sanitize_textarea_field( $_POST['details'] );
// Create report post $post_id = wp_insert_post( array( 'post_type' => 'bmpro_spam', 'post_title' => sprintf( 'Report: My Content #%d', $content_id ), 'post_status' => 'publish', 'post_author' => get_current_user_id(), ) );
if ( $post_id ) { // Add meta data update_post_meta( $post_id, 'bmpro_spam_activity_id', $content_id ); update_post_meta( $post_id, 'bmpro_spam_status', 'awaiting_moderation' ); update_post_meta( $post_id, 'bmpro_spam_reported_by', array( get_current_user_id() ) );
// Set taxonomy term wp_set_object_terms( $post_id, 'my_custom_content', 'bmpro_content_type' );
// Fire action hook do_action( 'bmpro_my_custom_content_flagged', $content_id, get_current_user_id(), $post_id );
wp_send_json_success( array( 'message' => __( 'Report submitted', 'my-plugin' ) ) ); }
wp_send_json_error( array( 'message' => __( 'Failed to submit report', 'my-plugin' ) ) );}Step 3: Add Admin Meta Box
add_action( 'bmpro_create_meta_box_for_content_type', 'my_content_metabox', 10, 1 );
function my_content_metabox( $term_slug ) { if ( $term_slug !== 'my_custom_content' ) { return; }
add_meta_box( 'bmpro_my_content_actions', __( 'My Content Actions', 'my-plugin' ), 'render_my_content_metabox', 'bmpro_spam', 'side', 'high' );}
function render_my_content_metabox( $post ) { $content_id = get_post_meta( $post->ID, 'bmpro_spam_activity_id', true ); ?> <p> <strong><?php _e( 'Content ID:', 'my-plugin' ); ?></strong> <?php echo esc_html( $content_id ); ?> </p> <p> <a href="/bp-family/buddypress-moderation/developer-guide/</?php echo esc_url( get_permalink( $content_id ) ); ?>" class="button" target="_blank"> <?php _e( 'View Content', 'my-plugin' ); ?> </a> </p> <p> <button type="button" class="button button-primary" onclick="handleMyContentAction('approve', <?php echo $post->ID; ?>)"> <?php _e( 'Approve', 'my-plugin' ); ?> </button> <button type="button" class="button" onclick="handleMyContentAction('remove', <?php echo $post->ID; ?>)"> <?php _e( 'Remove Content', 'my-plugin' ); ?> </button> </p> <?php}Listening to Moderation Events
Section titled “Listening to Moderation Events”// When member is flaggedadd_action( 'bpmp_members_flagged', 'on_member_flagged', 10, 3 );
function on_member_flagged( $member_id, $reporter_id, $post_id ) { // Log to external service my_analytics_track( 'member_reported', array( 'member_id' => $member_id, 'reporter_id' => $reporter_id, 'timestamp' => current_time( 'timestamp' ), ) );
// Send Slack notification my_slack_notify( sprintf( 'Member #%d was reported by #%d. Review: %s', $member_id, $reporter_id, admin_url( 'post.php?post=' . $post_id . '&action=edit' ) ) );}
// When member is suspendedadd_action( 'bmpro_member_suspended', 'on_member_suspended', 10, 3 );
function on_member_suspended( $member_id, $duration, $reason ) { // Revoke API access delete_user_meta( $member_id, 'api_access_token' );
// Cancel subscriptions my_subscription_service_suspend( $member_id, $duration );
// Send notification email $user = get_userdata( $member_id ); wp_mail( $user->user_email, __( 'Account Suspended', 'my-plugin' ), sprintf( __( 'Your account has been suspended for %d days. Reason: %s', 'my-plugin' ), $duration, $reason ) );}
// When user blocks another useradd_action( 'bmpro_user_blocked', 'on_user_blocked', 10, 2 );
function on_user_blocked( $blocked_id, $blocker_id ) { // Remove from friend list if ( function_exists( 'friends_remove_friend' ) ) { friends_remove_friend( $blocker_id, $blocked_id ); }
// Remove from group memberships my_remove_shared_group_memberships( $blocker_id, $blocked_id );}Modifying Auto-Moderation Behavior
Section titled “Modifying Auto-Moderation Behavior”// Dynamic threshold based on user reputationadd_filter( 'bmpro_auto_mod_limit_filter', 'reputation_based_threshold', 10, 2 );
function reputation_based_threshold( $limit, $settings ) { global $bp;
// Get content author $author_id = $bp->current_activity->user_id ?? 0;
if ( ! $author_id ) { return $limit; }
$reputation = (int) get_user_meta( $author_id, 'user_reputation', true );
// Higher reputation = higher threshold if ( $reputation > 1000 ) { return 10; // Trusted users } elseif ( $reputation > 500 ) { return 7; } elseif ( $reputation > 100 ) { return 5; }
return 3; // New users}
// Disable auto-moderation during business hoursadd_filter( 'bmpro_auto_moderation_enable', 'business_hours_moderation', 10, 2 );
function business_hours_moderation( $enabled, $component ) { $hour = (int) current_time( 'H' );
// Business hours: 9 AM - 5 PM if ( $hour >= 9 && $hour <= 17 ) { return false; // Manual review during business hours }
return $enabled;}REST API Integration
Section titled “REST API Integration”Adding Moderation Data to Endpoints
Section titled “Adding Moderation Data to Endpoints”add_filter( 'bp_rest_activity_prepare_value', 'add_moderation_to_rest', 10, 3 );
function add_moderation_to_rest( $response, $request, $activity ) { $data = $response->get_data();
// Add moderation info $data['moderation'] = array( 'is_flagged' => bmpro_exclude_moderated_content( 'activity', $activity->id ), 'report_count' => bmpro_get_reports_count( $activity->id, 'activity' )['count'], 'can_report' => bmpro_user_can_report(), 'flag_text' => bmpro_get_flag_button_text( 'flag' ), );
$response->set_data( $data ); return $response;}Custom REST Endpoint
Section titled “Custom REST Endpoint”add_action( 'rest_api_init', 'register_moderation_endpoints' );
function register_moderation_endpoints() { register_rest_route( 'my-plugin/v1', '/report', array( 'methods' => 'POST', 'callback' => 'handle_rest_report', 'permission_callback' => function() { return is_user_logged_in() && bmpro_user_can_report(); }, 'args' => array( 'content_type' => array( 'required' => true, 'type' => 'string', ), 'content_id' => array( 'required' => true, 'type' => 'integer', ), 'reason' => array( 'required' => true, 'type' => 'string', ), ), ) );}
function handle_rest_report( $request ) { $content_type = $request->get_param( 'content_type' ); $content_id = $request->get_param( 'content_id' ); $reason = $request->get_param( 'reason' );
// Create report using existing AJAX handler logic // ...
return new WP_REST_Response( array( 'success' => true, 'message' => __( 'Report submitted', 'my-plugin' ), ), 200 );}JavaScript Integration
Section titled “JavaScript Integration”Custom Report Handler
Section titled “Custom Report Handler”// Custom report functionality(function($) { 'use strict';
class CustomReportHandler { constructor() { this.ajaxUrl = bmpro_ajax_object.ajax_url; this.nonce = bmpro_ajax_object.ajax_nonce; this.init(); }
init() { $(document).on('click', '.my-custom-report-btn', this.showModal.bind(this)); $(document).on('click', '.my-custom-submit-report', this.submitReport.bind(this)); }
showModal(e) { e.preventDefault(); const contentId = $(e.currentTarget).data('content-id');
// Show your custom modal this.modal = $('<div class="my-report-modal">') .html(this.getModalContent(contentId)) .appendTo('body'); }
getModalContent(contentId) { return ` <div class="modal-overlay"> <div class="modal-content"> <h3>Report Content</h3> <form id="my-report-form"> <input type="hidden" name="content_id" value="${contentId}"> <select name="reason" required> <option value="">Select reason...</option> <option value="spam">Spam</option> <option value="inappropriate">Inappropriate</option> <option value="harassment">Harassment</option> </select> <textarea name="details" placeholder="Additional details..."></textarea> <button type="submit" class="my-custom-submit-report">Submit Report</button> <button type="button" class="close-modal">Cancel</button> </form> </div> </div> `; }
submitReport(e) { e.preventDefault(); const $form = $('#my-report-form'); const data = { action: 'bmpro_flag_my_custom_content_function', nonce: this.nonce, content_id: $form.find('[name="content_id"]').val(), reason: $form.find('[name="reason"]').val(), details: $form.find('[name="details"]').val() };
$.post(this.ajaxUrl, data) .done((response) => { if (response.success) { this.showSuccess(response.data.message); this.closeModal(); } else { this.showError(response.data.message); } }) .fail(() => { this.showError('Request failed. Please try again.'); }); }
showSuccess(message) { // Your success notification }
showError(message) { // Your error notification }
closeModal() { if (this.modal) { this.modal.remove(); } } }
// Initialize $(document).ready(() => new CustomReportHandler());
})(jQuery);Listen for Moderation Events
Section titled “Listen for Moderation Events”// Listen for built-in eventsjQuery(document).on('bmpro:report:submitted', function(e, data) { console.log('Report submitted:', data);
// Update UI jQuery('.report-count-' + data.contentId).text(data.newCount);
// Track analytics if (typeof gtag === 'function') { gtag('event', 'content_reported', { content_type: data.contentType, content_id: data.contentId }); }});
jQuery(document).on('bmpro:modal:opened', function(e, modalType) { console.log('Modal opened:', modalType);});
jQuery(document).on('bmpro:modal:closed', function(e, modalType) { console.log('Modal closed:', modalType);});WooCommerce Integration Example
Section titled “WooCommerce Integration Example”Report Products
Section titled “Report Products”/** * Add product reporting to WooCommerce */
// Register content typeadd_filter( 'bmpro_content_to_flag', 'add_wc_product_reporting' );function add_wc_product_reporting( $types ) { if ( class_exists( 'WooCommerce' ) ) { $types['wc_product'] = __( 'Products', 'my-plugin' ); } return $types;}
// Add report button to product pageadd_action( 'woocommerce_single_product_summary', 'show_product_report_button', 35 );function show_product_report_button() { if ( ! bmpro_user_can_report() ) { return; }
global $product; ?> <button class="bmpro-flag-product-btn button" data-product-id="<?php echo esc_attr( $product->get_id() ); ?>"> <?php echo esc_html( bmpro_get_flag_button_text( 'flag' ) ); ?> Product </button> <?php}
// Handle reportadd_action( 'wp_ajax_bmpro_flag_wc_product', 'handle_product_report' );function handle_product_report() { check_ajax_referer( 'bmpro_ajax_nonce', 'nonce' );
$product_id = absint( $_POST['product_id'] ); $reason = sanitize_text_field( $_POST['reason'] );
$product = wc_get_product( $product_id ); if ( ! $product ) { wp_send_json_error( array( 'message' => 'Product not found' ) ); }
// Create report $post_id = wp_insert_post( array( 'post_type' => 'bmpro_spam', 'post_title' => sprintf( 'Product Report: %s', $product->get_name() ), 'post_status' => 'publish', ) );
update_post_meta( $post_id, 'bmpro_spam_activity_id', $product_id ); update_post_meta( $post_id, 'bmpro_spam_status', 'awaiting_moderation' ); wp_set_object_terms( $post_id, 'wc_product', 'bmpro_content_type' );
// Notify shop manager $shop_managers = get_users( array( 'role' => 'shop_manager' ) ); foreach ( $shop_managers as $manager ) { wp_mail( $manager->user_email, 'Product Reported: ' . $product->get_name(), sprintf( 'Product "%s" has been reported. Reason: %s. Review: %s', $product->get_name(), $reason, admin_url( 'post.php?post=' . $post_id . '&action=edit' ) ) ); }
wp_send_json_success( array( 'message' => 'Report submitted' ) );}Testing Your Integration
Section titled “Testing Your Integration”Unit Tests
Section titled “Unit Tests”class My_Moderation_Integration_Test extends WP_UnitTestCase {
public function test_can_report_check() { // Create test user $user_id = $this->factory->user->create( array( 'role' => 'subscriber' ) ); wp_set_current_user( $user_id );
// Test permission $this->assertTrue( bmpro_user_can_report( $user_id ) ); }
public function test_custom_content_type_registered() { $types = bmpro_content_to_flag_array(); $this->assertArrayHasKey( 'my_custom_content', $types ); }
public function test_report_creation() { // Create report $post_id = wp_insert_post( array( 'post_type' => 'bmpro_spam', 'post_title' => 'Test Report', 'post_status' => 'publish', ) );
update_post_meta( $post_id, 'bmpro_spam_status', 'awaiting_moderation' );
// Verify $this->assertEquals( 'awaiting_moderation', get_post_meta( $post_id, 'bmpro_spam_status', true ) ); }}Manual Testing Checklist
Section titled “Manual Testing Checklist”- Report button appears for logged-in users
- Report modal opens correctly
- Report submission creates database entry
- Admin receives notification
- Auto-moderation triggers at threshold
- Content visibility changes after moderation
- User blocking prevents interactions
Troubleshooting
Section titled “Troubleshooting”Button Not Appearing
Section titled “Button Not Appearing”Possible causes:
- User not logged in
- User role not allowed to report
- Content type not enabled
Solution:
// Debug permissionsadd_action( 'wp_footer', function() { if ( is_user_logged_in() ) { $can_report = bmpro_user_can_report(); error_log( 'Can report: ' . ( $can_report ? 'yes' : 'no' ) ); }} );AJAX Request Failing
Section titled “AJAX Request Failing”Check nonce:
console.log('Nonce:', bmpro_ajax_object.ajax_nonce);Verify action:
// In your AJAX handlererror_log( 'Received action: ' . $_POST['action'] );error_log( 'POST data: ' . print_r( $_POST, true ) );Hooks Not Firing
Section titled “Hooks Not Firing”Verify hook is registered:
global $wp_filter;if ( isset( $wp_filter['bpmp_members_flagged'] ) ) { error_log( 'Hook has ' . count( $wp_filter['bpmp_members_flagged']->callbacks ) . ' callbacks' );}Best Practices
Section titled “Best Practices”- Always check permissions before showing moderation UI
- Use nonces for all AJAX requests
- Sanitize all input data
- Cache expensive queries using transients
- Log moderation actions for audit trail
- Test with different user roles
- Handle edge cases (deleted content, banned users)
Last Updated: 2025-12-20 Plugin Version: 4.x+
See Also:

