search

Archives: Snippets | Page 2

Add a Custom Post Meta Box in WordPress

Add a custom meta box to the post editor for storing additional data without a plugin like ACF. For more on registering custom fields.

add_action( 'add_meta_boxes', function () {
    add_meta_box(
        'savvy_post_subtitle',
        'Post Subtitle',
        'savvy_subtitle_metabox_html',
        'post',
        'normal',
        'high'
    );
} );

function savvy_subtitle_metabox_html( $post ) {
    $value = get_post_meta( $post->ID, '_savvy_subtitle', true );
    wp_nonce_field( 'savvy_subtitle_nonce', 'savvy_subtitle_nonce' );
    printf(
        '<input type="text" name="savvy_subtitle" value="%s" style="width:100%%;" />',
        esc_attr( $value )
    );
}

add_action( 'save_post', function ( $post_id ) {
    if ( ! isset( $_POST['savvy_subtitle_nonce'] ) ||
         ! wp_verify_nonce( $_POST['savvy_subtitle_nonce'], 'savvy_subtitle_nonce' ) ) {
        return;
    }

    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
        return;
    }

    if ( isset( $_POST['savvy_subtitle'] ) ) {
        update_post_meta(
            $post_id,
            '_savvy_subtitle',
            sanitize_text_field( $_POST['savvy_subtitle'] )
        );
    }
} );

Add to functions.php. Change the meta key, label, and input type to match your needs.

Enqueue Scripts Only for Specific Admin Pages

Load scripts and styles only on specific WordPress admin pages to avoid conflicts and keep the dashboard fast. For more on optimizing script loading.

add_action( 'admin_enqueue_scripts', function ( $hook ) {
    // Only load on the post edit screen
    if ( $hook !== 'post.php' && $hook !== 'post-new.php' ) {
        return;
    }

    wp_enqueue_style(
        'savvy-admin-custom',
        get_template_directory_uri() . '/css/admin-custom.css',
        array(),
        '1.0.0'
    );

    wp_enqueue_script(
        'savvy-admin-custom',
        get_template_directory_uri() . '/js/admin-custom.js',
        array( 'jquery' ),
        '1.0.0',
        true
    );
} );

Add to functions.php. The $hook parameter tells you which admin page is loading. Common values: post.php, edit.php, upload.php, options-general.php.

Add Custom Bulk Actions to the Posts List in WordPress

Add a custom option to the bulk actions dropdown on the posts list screen. This example marks selected posts as “Featured”. For more on WordPress hooks.

add_filter( 'bulk_actions-edit-post', function ( $actions ) {
    $actions['mark_featured'] = 'Mark as Featured';
    return $actions;
} );

add_filter( 'handle_bulk_actions-edit-post', function ( $redirect_to, $action, $post_ids ) {
    if ( $action !== 'mark_featured' ) {
        return $redirect_to;
    }

    foreach ( $post_ids as $post_id ) {
        update_post_meta( $post_id, '_is_featured', '1' );
    }

    return add_query_arg( 'marked_featured', count( $post_ids ), $redirect_to );
}, 10, 3 );

add_action( 'admin_notices', function () {
    if ( empty( $_REQUEST['marked_featured'] ) ) {
        return;
    }

    $count = intval( $_REQUEST['marked_featured'] );
    printf(
        '<div class="notice notice-success is-dismissible"><p>%d post(s) marked as featured.</p></div>',
        $count
    );
} );

Add to functions.php. Change mark_featured and the meta key to fit your use case.

Create a Simple Shortcode with Attributes in WordPress

Create a reusable shortcode that accepts attributes. This pattern is the foundation for any custom shortcode in WordPress. For more on WordPress hooks.

function savvy_button_shortcode( $atts ) {
    $atts = shortcode_atts( array(
        'url'   => '#',
        'text'  => 'Click Here',
        'color' => 'blue',
    ), $atts, 'savvy_button' );

    return sprintf(
        '<a href="%s" class="savvy-btn savvy-btn-%s">%s</a>',
        esc_url( $atts['url'] ),
        esc_attr( $atts['color'] ),
        esc_html( $atts['text'] )
    );
}

add_shortcode( 'savvy_button', 'savvy_button_shortcode' );

Add to functions.php. Usage: [savvy_button url="/contact/" text="Contact Us" color="gold"].

Register a Custom REST API Endpoint in WordPress

Register a custom REST API endpoint to expose data from your theme or plugin. For more on securing the REST API.

add_action( 'rest_api_init', function () {
    register_rest_route( 'savvy/v1', '/recent-posts/', array(
        'methods'             => 'GET',
        'callback'            => 'savvy_get_recent_posts',
        'permission_callback' => '__return_true',
    ) );
} );

function savvy_get_recent_posts() {
    $posts = get_posts( array(
        'numberposts' => 5,
        'post_status' => 'publish',
    ) );

    $data = array();
    foreach ( $posts as $post ) {
        $data[] = array(
            'id'    => $post->ID,
            'title' => $post->post_title,
            'link'  => get_permalink( $post ),
        );
    }

    return rest_ensure_response( $data );
}

Add to functions.php. Access at /wp-json/savvy/v1/recent-posts/. Set permission_callback to restrict access if needed.

Add Custom Admin Notices in WordPress

Display custom notices in the WordPress admin dashboard. Useful for warnings, reminders, or success messages for your team. For more on WordPress hooks.

add_action( 'admin_notices', function () {
    $screen = get_current_screen();

    if ( $screen->id !== 'edit-post' ) {
        return;
    }

    echo '<div class="notice notice-warning is-dismissible">';
    echo '<p>Remember to set a featured image before publishing.</p>';
    echo '</div>';
} );

Add to functions.php. Change the $screen->id check and message text to fit your needs. Use notice-success, notice-error, or notice-info for other styles.

Schedule Cron to Delete Expired Transients

Over time, expired transients pile up in the wp_options table and slow down queries. This snippet schedules a weekly cleanup. For more on improving WordPress performance.

if ( ! wp_next_scheduled( 'savvy_cleanup_transients' ) ) {
    wp_schedule_event( time(), 'weekly', 'savvy_cleanup_transients' );
}

add_action( 'savvy_cleanup_transients', function () {
    global $wpdb;
    $wpdb->query(
        "DELETE a, b FROM {$wpdb->options} a
        LEFT JOIN {$wpdb->options} b
            ON b.option_name = REPLACE( a.option_name, '_transient_timeout_', '_transient_' )
        WHERE a.option_name LIKE '\_transient\_timeout\_%'
            AND a.option_value < UNIX_TIMESTAMP()"
    );
} );

Add to functions.php. The cron runs once a week and removes only expired transients.

Remove jQuery Migrate

WordPress loads jQuery Migrate for backward compatibility. If your site and plugins support modern jQuery, you can remove Migrate and save an HTTP request. Add to your functions.php file. For more on performance optimization.

add_action( 'wp_default_scripts', function( $scripts ) {
	if ( ! is_admin() && isset( $scripts->registered['jquery'] ) ) {
		$script = $scripts->registered['jquery'];
		if ( $script->deps ) {
			$script->deps = array_diff( $script->deps, array( 'jquery-migrate' ) );
		}
	}
} );

Add Custom Image Sizes

You can define custom image sizes for your site. Images are generated on upload or when regenerating thumbnails. Add to your functions.php file. For more on image optimization.

add_action( 'after_setup_theme', function() {
	add_image_size( 'card-thumbnail', 400, 300, true );
	add_image_size( 'hero-banner', 1920, 600, true );
} );

Replace names and dimensions as needed. Use true for crop or false for scale.

Change Posts Per Page in Archives

WordPress defaults to 10 posts per page. You can change this for all archives or a specific one. Add to your functions.php file. For more on adding pagination.

add_action( 'pre_get_posts', function( $query ) {
	if ( ! is_admin() && $query->is_main_query() && $query->is_home() ) {
		$query->set( 'posts_per_page', 12 );
	}
} );

Replace is_home() with is_archive() or is_post_type_archive('your_cpt') as needed.

Savvy WordPress Development official logo