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