add-expires-header-external-scripts

PHP: How to Add Expire Headers for External Scripts

Every website is using external JavaScript files. They are required for example when using Google Analytics, or an ad provider like BuySellAds. In order to leverage browser caching and optimize your website speed, it is recommended that you add expire headers to your scripts, which you can’t do on external files. In this article, I’ll show you how to dynamically import external JavaScript or CSS files into your own site for better performance.

What are Expires Headers?

Expires headers allow a web developer to tell the browser whether a resource on a website needs to be requested from the source or if it can be fetched from the browser’s cache. Usually, website static resources like images or .pdf documents have expires headers, which results in the browser storing those resources in its cache. When a visitor comes back to your site, the browser fetches the resource from its own cache instead of requesting it from your server with an HTTP request.

Add Expires headers to External Scripts

Therefore, when you add expires headers to your site, it will enhance the load time of your page, and provide a better user experience to the website visitors.

In Apache, expires headers are generally set in the .htaccess file. For reference, here is the part I use in one of my site’s .htaccess file:

## EXPIRES CACHING ##

ExpiresActive On
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType text/x-javascript "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresDefault "access plus 2 days"

## EXPIRES CACHING ##

As you can see, the code above is pretty self-explanatory. Basically, for each filetype (image/jpg, image/gif, text/css, etc) we specify for how long the resources should be cached. “Access plus 1 month” means that the resources of the specified filetype will be cached for 1 month after being first accessed.

On line 13, you’ll notice the ExpiresDefault directive. This directive sets the default algorithm for calculating the expiration time for all documents in the affected realm. It can be overridden on a type-by-type basis by the ExpiresByType directive.

The Problem With External Scripts

When using an external service as such as Google Analytics, you are often required to include external JavaScript files into your own website.

While this isn’t a problem per se, you obviously don’t have as much control over those files than over files hosted on your own server. This is especially problematic since you should always set an expire header to static files in order to leverage browser caching and optimize your website speed.

Google PageSpeed Insight will recommend you to do so:
PHP: How to Add Expire Headers for External Scripts 1

But external JavaScript and CSS files aren’t hosted on your server. It is therefore not possible to simply add expires headers using your .htaccess file.

The Solution: Adding Expire Headers to External Scripts

So what we need to do is to import all the .js files dynamically into our website. To do so, we’ll use PHP and the file_get_contents() function.

The first thing to do is to locate the external script:

<script type="text/javascript" src="https://ssl.google-analytics.com/ga.js"></script>

The next step is to create a .php file. Let’s call it externaljs.php. Insert the following code in it:

<?php

$files = array(
	'ga.js' => 'https://ssl.google-analytics.com/ga.js',
	'bsa.js' => 'https://s3.buysellads.com/ac/bsa.js',
	'pro.js' => 'https://s3.buysellads.com/ac/pro.js'
);

if(isset($files[$_GET['file']])) {
	if ($files[$_GET['file']] == 'ga.js'){
		header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T', time() + ((60 * 60) * 48))); // 2 days for GA
	} else {
		header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T', time() + (60 * 60))); // Default set to 1 hour
	}

	echo file_get_contents($files[$_GET['file']]);
}

?>

Let’s have a look at the code:

  • Lines 3 to 7: An array containing the accepted files is created. This is super important since otherwise any file could be embedded into your site, leading to potential security problems.
  • Lines 9 to 14: Since we need to adjust the expiring time for every script, we need a conditional statement to do so.
  • Line 16: If the script passed out as a GET parameter is found in our array, we can now safely display it.

You’ll need to adjust the code and enter the URLs of your external scripts. Once done, just upload it onto your server. If you’re using WordPress, it’s a good idea to put the file in your theme folder.

Then, simply replace the external .js call and replace it by a call to your externaljs.php file, as shown below:

<script type="text/javascript" src="externaljs.php?file=ga.js"></script>

And you’re done. You can now dynamically import external .js file on your server and therefore, set the right expires header for each script.

Frequently Asked Questions

Expires Headers

Is This Code Secure?

Absolutely. As you can see on line 3 to 7, only specified resources will be downloaded with file_get_contents(). No security risk there.

Will my Site be Faster if I Add Expires?

If a resource is fetched from the browser cache, it will be one less HTTP request made. Therefore, yes, expires headers does make your site faster.

Should I Add Expires Headers on All my gif, jpg, or png images?

It depends on how often the resource is updated. It is generally recommended that you don’t add the ExpiresDefault header that sets a default time span for all resources. In most cases, you will not want to set a general expiry date for everything, and rather manually specify resources that can be safely cached.

Can I Use This Technique on a WordPress Site?

Absolutely, as long as your WordPress site is powered by Apache.

Share This Post:
Share on facebook
Share on twitter
Share on linkedin
Share on reddit
Share on whatsapp