Hooks & Filters

Hooks & Filters Reference

MagicBlog provides extensive hooks and filters for developers to customize functionality, extend features, and integrate with other plugins. This comprehensive reference covers all available customization points.

🎯 Action Hooks

Plugin Lifecycle Hooks

magicblog_plugin_loaded

Fires when MagicBlog is fully loaded and initialized.

add_action('magicblog_plugin_loaded', 'my_magicblog_init');
function my_magicblog_init() {
    // Plugin is ready for customization
    error_log('MagicBlog is now loaded');
}

magicblog_before_activation

Fires before plugin activation process begins.

add_action('magicblog_before_activation', 'my_pre_activation_tasks');
function my_pre_activation_tasks() {
    // Perform checks before activation
    if (!current_user_can('manage_options')) {
        wp_die('Insufficient permissions');
    }
}

magicblog_after_activation

Fires after successful plugin activation.

add_action('magicblog_after_activation', 'my_post_activation_tasks');
function my_post_activation_tasks() {
    // Custom setup after activation
    update_option('my_magicblog_custom_setting', 'enabled');
}

magicblog_before_deactivation

Fires before plugin deactivation.

add_action('magicblog_before_deactivation', 'my_cleanup_tasks');
function my_cleanup_tasks() {
    // Clean up custom data
    wp_clear_scheduled_hook('my_custom_cron');
}

Database Hooks

magicblog_before_track_engagement

Fires before engagement data is saved to database.

add_action('magicblog_before_track_engagement', 'log_engagement_attempt', 10, 4);
function log_engagement_attempt($post_id, $type, $value, $user_data) {
    error_log("Tracking {$type} for post {$post_id} with value {$value}");
}

magicblog_after_track_engagement

Fires after engagement data is successfully saved.

add_action('magicblog_after_track_engagement', 'trigger_engagement_notifications', 10, 4);
function trigger_engagement_notifications($post_id, $type, $value, $result) {
    if ($type === 'rating' && $value >= 5) {
        // Notify admin of 5-star rating
        wp_mail(get_option('admin_email'), 'New 5-Star Rating', 
               "Post {$post_id} received a 5-star rating!");
    }
}

magicblog_stats_updated

Fires when post statistics are recalculated.

add_action('magicblog_stats_updated', 'handle_stats_update', 10, 2);
function handle_stats_update($post_id, $stats) {
    // Trigger cache clearing for post
    wp_cache_delete("post_stats_{$post_id}", 'my_cache_group');
    
    // Update custom analytics
    if ($stats->total_views > 1000) {
        update_post_meta($post_id, '_popular_post', true);
    }
}

Block & Widget Hooks

magicblog_before_render_block

Fires before any MagicBlog block is rendered.

add_action('magicblog_before_render_block', 'customize_block_rendering', 10, 2);
function customize_block_rendering($block_name, $attributes) {
    // Add custom classes or modify attributes
    if ($block_name === 'magicblog/post-grid') {
        // Enqueue additional CSS for post grid
        wp_enqueue_style('my-post-grid-styles', 'path/to/custom.css');
    }
}

magicblog_after_render_block

Fires after block rendering is complete.

add_action('magicblog_after_render_block', 'track_block_usage', 10, 3);
function track_block_usage($block_name, $attributes, $output) {
    // Analytics tracking
    $usage_stats = get_option('magicblog_block_usage', array());
    $usage_stats[$block_name] = ($usage_stats[$block_name] ?? 0) + 1;
    update_option('magicblog_block_usage', $usage_stats);
}

magicblog_widget_before_render

Fires before Elementor widgets are rendered.

add_action('magicblog_widget_before_render', 'prepare_widget_data', 10, 2);
function prepare_widget_data($widget_name, $settings) {
    // Modify widget behavior based on settings
    if ($widget_name === 'post-grid-widget' && isset($settings['custom_query'])) {
        // Modify query parameters
        add_filter('magicblog_widget_query_args', 'modify_grid_query');
    }
}

Admin Interface Hooks

magicblog_admin_dashboard_before

Fires before admin dashboard content is rendered.

add_action('magicblog_admin_dashboard_before', 'add_custom_dashboard_notice');
function add_custom_dashboard_notice() {
    echo '<div class="notice notice-info"><p>Custom dashboard message</p></div>';
}

magicblog_admin_dashboard_after

Fires after admin dashboard content.

add_action('magicblog_admin_dashboard_after', 'add_custom_dashboard_widgets');
function add_custom_dashboard_widgets() {
    ?>
    <div class="magicblog-custom-widget">
        <h3>Custom Analytics</h3>
        <!-- Custom content -->
    </div>
    <?php
}

magicblog_settings_page_loaded

Fires when settings page is loaded.

add_action('magicblog_settings_page_loaded', 'add_custom_settings_section');
function add_custom_settings_section() {
    // Register additional settings
    register_setting('magicblog_settings', 'my_custom_setting');
}

🔍 Filter Hooks

Data Modification Filters

magicblog_engagement_value

Filters engagement value before saving.

add_filter('magicblog_engagement_value', 'modify_engagement_value', 10, 3);
function modify_engagement_value($value, $type, $post_id) {
    // Double the value for premium posts
    if (get_post_meta($post_id, '_premium_post', true)) {
        return $value * 2;
    }
    return $value;
}

magicblog_user_can_engage

Filters whether user can engage with content.

add_filter('magicblog_user_can_engage', 'custom_engagement_permissions', 10, 3);
function custom_engagement_permissions($can_engage, $type, $post_id) {
    // Restrict ratings to logged-in users only
    if ($type === 'rating' && !is_user_logged_in()) {
        return false;
    }
    
    // Block engagement on private posts
    if (get_post_status($post_id) === 'private') {
        return false;
    }
    
    return $can_engage;
}

magicblog_rate_limit_time

Filters rate limiting duration.

add_filter('magicblog_rate_limit_time', 'custom_rate_limits', 10, 2);
function custom_rate_limits($time, $type) {
    // Longer rate limit for ratings
    if ($type === 'rating') {
        return 600; // 10 minutes
    }
    
    // No rate limit for views
    if ($type === 'view') {
        return 0;
    }
    
    return $time;
}

Query Modification Filters

magicblog_posts_query_args

Filters query arguments for post fetching.

add_filter('magicblog_posts_query_args', 'customize_post_queries', 10, 2);
function customize_post_queries($args, $context) {
    // Show only published posts in widgets
    if ($context === 'widget') {
        $args['post_status'] = 'publish';
        $args['meta_query'] = array(
            array(
                'key' => '_featured_post',
                'value' => '1',
                'compare' => '='
            )
        );
    }
    
    return $args;
}

magicblog_stats_query

Filters statistics database query.

add_filter('magicblog_stats_query', 'modify_stats_query', 10, 2);
function modify_stats_query($query, $post_id) {
    // Add custom WHERE clause
    $query .= " AND created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)";
    return $query;
}

Display Filters

magicblog_format_number

Filters number formatting for display.

add_filter('magicblog_format_number', 'custom_number_format', 10, 2);
function custom_number_format($formatted, $number) {
    // Use custom formatting for large numbers
    if ($number >= 1000000) {
        return round($number / 1000000, 1) . 'M';
    } elseif ($number >= 1000) {
        return round($number / 1000, 1) . 'k';
    }
    return number_format($number);
}

magicblog_star_rating_html

Filters star rating HTML output.

add_filter('magicblog_star_rating_html', 'custom_star_html', 10, 3);
function custom_star_html($html, $rating, $max_rating) {
    // Use custom star icons
    $star_filled = '<i class="fas fa-star"></i>';
    $star_empty = '<i class="far fa-star"></i>';
    
    $output = '<div class="custom-star-rating">';
    for ($i = 1; $i <= $max_rating; $i++) {
        $output .= ($i <= $rating) ? $star_filled : $star_empty;
    }
    $output .= '</div>';
    
    return $output;
}

magicblog_engagement_buttons_html

Filters engagement buttons HTML.

add_filter('magicblog_engagement_buttons_html', 'customize_buttons', 10, 2);
function customize_buttons($html, $post_id) {
    // Add custom social sharing button
    $share_url = urlencode(get_permalink($post_id));
    $share_title = urlencode(get_the_title($post_id));
    
    $html .= sprintf(
        '<a href="https://twitter.com/intent/tweet?url=%s&text=%s" class="magicblog-share-twitter" target="_blank">Share on Twitter</a>',
        $share_url,
        $share_title
    );
    
    return $html;
}

Block & Widget Filters

magicblog_block_attributes

Filters block attributes before rendering.

add_filter('magicblog_block_attributes', 'modify_block_attributes', 10, 2);
function modify_block_attributes($attributes, $block_name) {
    // Set default number of posts for grid blocks
    if ($block_name === 'magicblog/post-grid' && !isset($attributes['postsPerPage'])) {
        $attributes['postsPerPage'] = 9;
    }
    
    // Force specific layout on mobile
    if (wp_is_mobile() && $block_name === 'magicblog/post-carousel') {
        $attributes['slidesToShow'] = 1;
    }
    
    return $attributes;
}

magicblog_widget_settings

Filters Elementor widget settings.

add_filter('magicblog_widget_settings', 'customize_widget_settings', 10, 2);
function customize_widget_settings($settings, $widget_name) {
    // Add custom default settings
    if ($widget_name === 'post-grid-widget') {
        $settings['show_excerpt'] = $settings['show_excerpt'] ?? true;
        $settings['excerpt_length'] = $settings['excerpt_length'] ?? 150;
    }
    
    return $settings;
}

Performance & Caching Filters

magicblog_cache_duration

Filters cache duration for different data types.

add_filter('magicblog_cache_duration', 'set_cache_durations', 10, 2);
function set_cache_durations($duration, $data_type) {
    switch ($data_type) {
        case 'post_stats':
            return 300; // 5 minutes
        case 'analytics_data':
            return 3600; // 1 hour
        case 'popular_posts':
            return 1800; // 30 minutes
        default:
            return $duration;
    }
}

magicblog_should_cache

Filters whether specific data should be cached.

add_filter('magicblog_should_cache', 'conditional_caching', 10, 3);
function conditional_caching($should_cache, $data_type, $context) {
    // Don't cache in admin or during development
    if (is_admin() || defined('WP_DEBUG') && WP_DEBUG) {
        return false;
    }
    
    // Don't cache for logged-in users
    if (is_user_logged_in() && $data_type === 'personalized_data') {
        return false;
    }
    
    return $should_cache;
}

🔧 Custom Integration Examples

Custom Engagement Type

Add a new "bookmark" engagement type:

// Register new engagement type
add_filter('magicblog_engagement_types', 'add_bookmark_type');
function add_bookmark_type($types) {
    $types['bookmark'] = array(
        'label' => 'Bookmark',
        'icon' => '🔖',
        'description' => 'Save post for later',
        'rate_limit' => 0 // No rate limit
    );
    return $types;
}

// Handle bookmark tracking
add_action('wp_ajax_magicblog_track_bookmark', 'handle_bookmark_tracking');
add_action('wp_ajax_nopriv_magicblog_track_bookmark', 'handle_bookmark_tracking');
function handle_bookmark_tracking() {
    // Custom bookmark logic
    $post_id = intval($_POST['post_id']);
    $user_id = get_current_user_id();
    
    // Save to user meta or custom table
    $bookmarks = get_user_meta($user_id, 'bookmarked_posts', true) ?: array();
    if (!in_array($post_id, $bookmarks)) {
        $bookmarks[] = $post_id;
        update_user_meta($user_id, 'bookmarked_posts', $bookmarks);
        
        // Also track in MagicBlog system
        do_action('magicblog_track_engagement', $post_id, 'bookmark', 1);
    }
    
    wp_send_json_success(array('bookmarked' => true));
}

Custom Analytics Dashboard Widget

Add a custom widget to the admin dashboard:

add_action('magicblog_admin_dashboard_after', 'add_custom_analytics_widget');
function add_custom_analytics_widget() {
    ?>
    <div class="magicblog-custom-widget">
        <div class="widget-header">
            <h3>Top Authors by Engagement</h3>
        </div>
        <div class="widget-content">
            <?php
            global $wpdb;
            $stats = $wpdb->get_results("
                SELECT p.post_author, u.display_name, 
                       SUM(s.total_views) as total_views,
                       SUM(s.total_likes) as total_likes
                FROM {$wpdb->prefix}magicblog_stats s
                JOIN {$wpdb->posts} p ON s.post_id = p.ID
                JOIN {$wpdb->users} u ON p.post_author = u.ID
                GROUP BY p.post_author
                ORDER BY total_views DESC
                LIMIT 5
            ");
            
            foreach ($stats as $stat) {
                echo "<div class='author-stat'>";
                echo "<strong>{$stat->display_name}</strong><br>";
                echo "Views

Last updated