WordPress: Remove query strings from static resources

When checking your site with PageSpeed Insights, you might get the following finding:

Remove query strings from static resources

Enabling public caching in the HTTP headers for static resources allows the browser to download resources from a nearby proxy server rather than from a remote origin server.

Suggestions for this page

Resources with a “?” in the URL are not cached by some proxy caching servers. Remove the query string and encode the parameters into the URL.

It will report the finding for CSS or JavaScript files referenced with a specific version number in your site e.g.:

http://spielsachenweb.de/wp-content/plugins/google-analyticator/external-tracking.min.js?ver=6.4.3

In many cases, you will see that the version number is not required as you actually only have one version available at that location and you’d get exactly the same file with or without the version number. But the version specification as a parameter does have a negative impact on caching on proxy servers (especially old Squid proxies). That’s why PageSpeed Insights recommends dropping the version specification from the URL.

If you have written the <script> or <link> tag directly in some template files, you can just delete the part starting from the question mark (?). But most probably it will come from themes or plugins you use.

1. The first step is to check whether you really do need the version number or not. You can do this by copying the URL from the PageSpeed Insights report and open it in a browser. Do it twice, once with the version number and once without. Copy each of them and compare them (e.g. using WinMerge). If you see no difference, then you’re safe removing the version number.

2. Once you’re done with the step above. You have a list of files which can do without the version number and a list of those which cannot. Now you can add a very simple function in functions.php in your current theme (in the theme editor) to remove the parameters for specific URLs:

function remove_style_and_script_version($url) {
	$url_to_fix = array('http://spielsachenweb.de/wp-content/plugins/google-analyticator/external-tracking.min.js?ver=6.4.3',
					    'http://spielsachenweb.de/wp-includes/js/jquery/jquery.js?ver=1.8.3');

	if (in_array($url, $url_to_fix)) {
		//if it is one of the URLs to process, remove everything after the question mark
		$parts = explode('?', $url);
		return $parts[0];
	}
	//otherwise return the URL as is
	return $url;
}
add_filter('script_loader_src', 'remove_style_and_script_version', 20, 1);
add_filter('style_loader_src', 'remove_style_and_script_version', 20, 1);

Note that the two last parameters of the add_filter calls (20, 1) mean that the new function should be called with priority 20 (default is 10) and will thus happen after all other filters on the script or style loader which have a priority of less than 20 (so including the ones using the default priority).

Also note that this trick only works if the scripts and styles are loaded using the WordPress enqueueing mechanism, which is almost always the case.

Now if you want to do it the other way around and strip the part after the question mark for all script and style URLs except for the ones for which you known you’d get the wrong file, you can do the following instead:

function remove_style_and_script_version($url) {
	$url_not_to_fix = array('http://spielsachenweb.de/wp-content/plugins/google-analyticator/external-tracking.min.js?ver=6.4.3',
					    'http://spielsachenweb.de/wp-includes/js/jquery/jquery.js?ver=1.8.3');

	if (in_array($url, $url_to_fix)) {
		//if it is one of the URLs to exclude, return the URL as is
		return $url;
	}
	//otherwise, remove everything after the question mark
	$parts = explode('?', $url);
	return $parts[0];
}
add_filter('script_loader_src', 'remove_style_and_script_version', 20, 1);
add_filter('style_loader_src', 'remove_style_and_script_version', 20, 1);

If you just want to remove everything after the question mark for all script and style URLs:

function remove_style_and_script_version($url) {
	$parts = explode('?', $url);
	return $parts[0];
}
add_filter('script_loader_src', 'remove_style_and_script_version', 20, 1);
add_filter('style_loader_src', 'remove_style_and_script_version', 20, 1);

Note that you might also get parameters added to the URL of scripts and styles when using W3 Total Cache. Please have a look at this post in this case.

There is also an additional special case. If you only want to remove the script or style URLs called with the WordPress version number e.g. because it shows which version you use and if it’s an older one, it might give away some information which can be used by a hacker (although the best solution in this case would be to upgrade to the latest version), you can specifically process only these URLs:

function remove_style_and_script_version($url) {
	global $wp_version;
	return str_replace("?ver=$wp_version", '', $url);
}
add_filter('script_loader_src', 'remove_style_and_script_version', 20, 1);
add_filter('style_loader_src', 'remove_style_and_script_version', 20, 1);

Or you can show a different version:

function remove_style_and_script_version($url) {
	global $wp_version;
	return str_replace("?ver=$wp_version", '?ver=X.XX', $url);
}
add_filter('script_loader_src', 'remove_style_and_script_version', 20, 1);
add_filter('style_loader_src', 'remove_style_and_script_version', 20, 1);

Replace X.XX by the version you want to show.

Leave a Reply

Your email address will not be published. Required fields are marked *