Archives: Snippets | Page 9

Change JPEG Compression Quality in WordPress

WordPress generates several image sizes according to your theme settings. These images are created at quality 90 on a scale of 1-100 by default. You can save bandwidth by changing this setting to 75 for more aggressive compression.

/**
 * Snippet Name: Change jpg compression level
 */
function sv_jpeg_quality() {
	return 75;
}
add_filter( 'jpeg_quality', 'sv_jpeg_quality' );

For more on optimizing images for WordPress, see optimizing WordPress images for SEO.

Remove Sticky Posts from the Main Loop

We use the pre_get_posts hook to modify the main loop and tell it to ignore sticky posts. Note that this removes them from the blog’s main loop entirely, not just from the top. If you want to display them, you will need to write your own loop above the main loop that only queries those sticky posts:

/**
 * Snippet Name: Remove sticky posts from the main query
 */
function sv_ignore_sticky( $query ) {
	if ( ! is_admin() && $query->is_home() && $query->is_main_query() ) {
		$query->set( 'ignore_sticky_posts', true );
		$query->set( 'post__not_in', get_option( 'sticky_posts' ) );
	}
}

add_action( 'pre_get_posts', 'sv_ignore_sticky' );

The condition limits the change to the main query on the blog home page, so sticky posts still show in widgets, custom loops and the admin. ignore_sticky_posts on its own only stops them from being moved to the top. post__not_in is what removes them from the list.

Change WordPress Auto-Save Interval

Yes, WordPress autosaves your work. While you edit a post with unsaved changes, it saves a copy every 60 seconds by default, in both the block editor and the classic editor. If the browser crashes or the connection drops, you can restore that copy.

The AUTOSAVE_INTERVAL constant controls how often that happens. Raise it for fewer saves to the server, or lower it if losing even a minute of writing is too much.

Change the Autosave Interval

Add this line to wp-config.php, above the /* That's all, stop editing! */ line. The value is in seconds.

define( 'AUTOSAVE_INTERVAL', 120 );

This example saves every 2 minutes. It has to go above that line because WordPress sets its own default of 60 seconds right after, but only if the constant isn’t already defined.

How Autosave Works in Each Editor

Both editors read the same constant, but they send the autosave differently.

  • Block editor: passes AUTOSAVE_INTERVAL to the editor settings and saves through the REST API autosaves endpoint.
  • Classic editor: sends autosaves with the Heartbeat API. If you disable Heartbeat on the post edit screen to reduce server load, classic autosave stops too.

The block editor also keeps a backup in the browser’s sessionStorage every 15 seconds. That local copy is separate from AUTOSAVE_INTERVAL and never reaches the server.

Autosaves vs Revisions

An autosave isn’t a regular revision, and the rules depend on the post status and who is editing.

  • Your own draft: the autosave overwrites the draft itself. No extra row is created.
  • A published post, or another user’s draft: the autosave is stored in wp_posts as a revision named {post_ID}-autosave-v1. There is one per user per post, overwritten on each save.

When WordPress trims old revisions down to the WP_POST_REVISIONS limit, it never deletes autosaves. Setting WP_POST_REVISIONS to false doesn’t turn autosave off either.

Since there is at most one autosave per user per post, a longer interval barely affects database size. To control revision growth, limit the number of post revisions or disable post revisions instead.

Choosing a Value

The default of 60 seconds suits most sites. A few cases justify changing it:

  • Several editors working at once on shared hosting: 120 to 300 seconds means fewer autosave writes. In the classic editor, Heartbeat requests continue on their own schedule.
  • Long-form writing where every paragraph matters: 30 seconds. Each autosave replaces the previous one, so the database doesn’t grow.

For other constants worth setting in the same file, see Optimize WordPress Configuration via wp-config.php.

FAQs

Common questions about WordPress autosave:

Does WordPress autosave posts?
Yes. When there are unsaved changes, WordPress autosaves every 60 seconds by default. Change the interval with the AUTOSAVE_INTERVAL constant in wp-config.php.
Where does WordPress store autosaves?
In the wp_posts table. Drafts you own are overwritten in place, while autosaves of published posts are stored as a revision post named {post_ID}-autosave-v1, one per user.
Can I disable autosave completely?
There is no core setting for it. A very large AUTOSAVE_INTERVAL, such as 86400, effectively stops server autosaves, but the block editor's local browser backup keeps running. Losing unsaved work is usually a bigger problem than the extra saves.
Does AUTOSAVE_INTERVAL affect the Customizer?
Yes. The Customizer uses the same constant for how often it autosaves unpublished changes in the current changeset.

Move the WordPress Admin Bar to the Bottom

More than once the WordPress admin bar has bothered me because it hid menus that were set to position:fixed in CSS. A few lines in functions.php and the admin bar moves to the bottom of the page:

<?php
function fb_move_admin_bar() { ?>
	<style type="text/css">
		body {
			margin-top: -28px;
			padding-bottom: 28px;
		}
		body.admin-bar #wphead {
			padding-top: 0;
		}
		body.admin-bar #footer {
			padding-bottom: 28px;
		}
		#wpadminbar {
			top: auto !important;
			bottom: 0;
		}
		#wpadminbar .quicklinks .menupop ul {
			bottom: 28px;
		}
	</style>
<?php }
add_action( 'admin_head', 'fb_move_admin_bar' );
add_action( 'wp_head', 'fb_move_admin_bar' );

For safe WordPress customizations, see What Are Child Themes and How to Use Them.

Hide the Sitemap from Search Engines

The Sitemap file helps search engines index your site and find the most important pages easily. If you do not want the Sitemap to appear in Google search results, add the following lines to the .htaccess file in the root directory where WordPress is installed:

<IfModule mod_rewrite.c>
 <Files sitemap.xml>
    Header set X-Robots-Tag "noindex"
 </Files>
 </IfModule>

Replace sitemap.xml with your Sitemap file name. For more on what a Sitemap is, see the post How to create a Sitemap in WordPress and how to submit it via Google Search Console.

Block Search Engines from Indexing Directories

You want search engines to index your blog pages but not the PHP files of your WordPress installation. Edit the robots.txt file and add the following lines to block search engines from indexing these files:

User-agent: *
Disallow: /wp-admin/
Disallow: /wp-includes/
Disallow: /wp-content/plugins/
Disallow: /wp-content/themes/
Disallow: /feed/
Disallow: */feed/

For more on managing search engine access, see Create and Send a Sitemap for WordPress SEO.

Send Email on New Post Published in WordPress

Here is a short snippet that sends an email when you publish a new post on your blog. This code can also work for Custom Post Types.

add_action('future_to_publish', 'send_emails_on_new_event');
add_action('new_to_publish', 'send_emails_on_new_event');
add_action('draft_to_publish' ,'send_emails_on_new_event');
add_action('auto-draft_to_publish' ,'send_emails_on_new_event');
 
/**
 * Send emails on event publication
 *
 * @param WP_Post $post
 */
function send_emails_on_new_event($post)
{
    $emails = "[email protected], [email protected]"; //If you want to send to site administrator, use $emails = get_option('admin_email');
    $title = wp_strip_all_tags(get_the_title($post->ID));
    $url = get_permalink($post->ID);
    $message = "Link to post: n{$url}";
 
    wp_mail($emails, "New post published: {$title}", $message);
}

The result will look something like:

[Title] New post published: Your Post
    
Link to post:
http://site.co.il/your-post/

If you want to enable this for a specific Custom Post Type, add a condition inside the function like this:

...
if(get_post_type($post->ID) === 'page') //post, page, attachment or whatever other CPT you may have
{
    //use wp_mail() here!
}
...

Add User Role to Body Class in WordPress Admin

Here is a way to add a class based on the user role in the WordPress admin. Add the following code to your theme’s functions.php file:

add_filter('admin_body_class', function($classes) {
    global $current_user;
 
    if(is_array($current_user->roles)) {
        foreach($current_user->roles as $role) {
            $classes .= "user-role-{$role} ";
        }
    }
 
    return rtrim($classes);
});

The result will look something like:

<body class="... user-role-administrator ...">

This uses the body_class filter. Learn more in WordPress Hooks Explained.