This page contains a section with information about the functionality of the plugin with the default settings, a caching quick start section for the impatient users, a section with detailed information about the available configuration options and a section with configuration examples.

Default behavior

Since version 2.0.0 caching is not enabled by default and non caching headers are sent for all dynamic pages.

The ETag, Last-Modified, Expires, Cache-Control and Pragma headers are all enabled and sent to the client by default.

Caching Quickstart

All that is required in order to enable caching for all pages is to set a positive integer as the value of the cache_max_age_seconds option. This option controls the number of seconds the pages should be cached by web browsers and caching proxies.

For instance, you can add the following PHP code snippet in your theme's functions.php file or in a custom plugin:

function addh_custom_options ( $options ) {
    $options['cache_max_age_seconds'] = 86400;
    return $options;
add_filter( 'addh_options', 'addh_custom_options' );

The above code configures Add-Headers to set the caching timeout for all pages to 1 day (86400 seconds).

In case some pages need to serve fresh content on every visit, these have to be excluded from caching.

In the following snippet, it is assumed that the web site contains a page with the slug contact which contains a contact form. This page needs to be excluded from caching (set cache_max_age_seconds to zero).

The following snippet makes the contact page non-cacheable, while all other pages are allowed to be cached for 86400 seconds.

function addh_custom_options ( $options ) {
    if ( is_page('contact') ) {
        $options['cache_max_age_seconds'] = 0;
    } else {
        $options['cache_max_age_seconds'] = 86400;
    return $options;
add_filter( 'addh_options', 'addh_custom_options' );

That's all you need to know for basic configuration and page exclusion. For more details regarding the available configuration options, please read on.

Configuration Options

This plugin does not have an administration interface so as to maintain the maximum level of flexibility when configuring it.

The plugin can be configured by attaching a filtering function to the addh_options filter hook, which returns an array containing the options that should be used for the current request. The code can be added in the functions.php file of the theme or in another plugin:

function addh_custom_options ( $options ) {
    // These are the default options.
    return array_merge( $options, array(
        'add_etag_header' => true,
        'generate_weak_etag' => false,
        'add_last_modified_header' => true,
        'add_expires_header' => true,
        'add_cache_control_header' => true,
        'cache_max_age_seconds' => 86400,
        'cache_max_age_seconds_for_search_results' => 0,
        'cache_max_age_seconds_for_authenticated_users' => 0,
        'cache_old_content_threshold_seconds' => 0,
        'cache_old_content_max_age_seconds' => 0,
        'remove_pre_existing_headers' => false,
    ) );
add_filter( 'addh_options', 'addh_custom_options' );

The settings above demonstrate the default values.

By setting any of the max-age settings to zero, a Cache-Control: no-cache, must-revalidate, max-age=0 header is sent to the client. cache_max_age_seconds_for_search_results only affects search results. cache_max_age_seconds affects all pages. If you need more customization, it is possible to filter the headers before they are sent to the client (see Available Filters section).

Below is information about each configuration option.


(true/false) - Enables the generation of the ETag header. Default: true


(true/false) - Instructs the plugin to generate a Weak ETag. Requires add_etag_header to be enabled. Default: false


(true/false) - Enables the generation of the Last-Modified header. Default: true

Note: In case of feeds, the Last-Modified header is also generated by WordPress. If the above option is set to false, then the Last-Modified header by WordPress is still sent to the client. In order to make Add-Headers clean up pre-existing headers, the remove_pre_existing_headers options needs to be enabled.


(true/false) - Enables the generation of the Expires header. Default: true


(true/false) - Enables the generation of the Cache-Control header. Default: true

Note: If the above option is set to false, then caching by clients, which base their caching functionality upon the existence of this header, might be affected.


(positive-integer) - Sets the caching timeout in seconds. The number of seconds the resource is allowed to be cached. Default: 0


(positive-integer) - Sets the number of seconds the pages containing search results are allowed to be cached. Default: 0


(positive-integer) - Sets the number of seconds any resource is allowed to be cached when accessed by an authenticated user. Default: 0


(positive-integer) - Sets the maximum difference in seconds between the current time (UTC) and the time the current post object or the first post object of an archive was last modified, after which the post object or the archive is treated as old content and its caching timeout is set according to the cache_old_content_max_age_seconds option. If this option is set to 0 (the default), this functionality is disabled. Default: 0


(positive-integer) - Sets the number of seconds any content, which has been identified as old (see the cache_old_content_threshold_seconds option), is allowed to be cached. The concept behind this is that old content should be allowed to be cached for longer periods of time, since it is rarely modified any more. Normally, this option needs to be set to a number greater than cache_max_age_seconds. Default: 0


(true/false) - If enabled, instructs the plugin to clear any preexisting ETag, Last-Modified, Expires, Cache-Control and Pragma headers before sending its own headers, according to the user defined options. Default: false

Configuration Examples

The following code snippets can be added in the the theme's functions.php file or in a plugin with customizations.

Changing the default options

function addh_custom_options ( $options ) {
    $options['cache_max_age_seconds'] = 3600;
    $options['add_expires_header'] = false;
    $options['generate_weak_etag'] = true;
    return $options;
add_filter( 'addh_options', 'addh_custom_options' );

Excluding a contact form from being cached

Assuming that the contact form page's slug is contact, making it non cacheable, requires the following configuration:

function addh_options_for_special_pages( $options ) {
    if ( is_page('contact') ) {
        $options['cache_max_age_seconds'] = 0;
add_filter( 'addh_options', 'addh_options_for_special_pages' );

Different caching timeout for old content

This example demonstrates how to use the cache_old_content_threshold_seconds and the cache_old_content_max_age_seconds options in order to set a different caching timeout for resources that haven't been modified after a specific point in time.

In the following configuration all resources are allowed to be cached for 1 hour (3600 seconds) by default. However, resources that haven't been modified during the last week (604800 seconds ago) are allowed to be cached for 1 day (86400 seconds).

function addh_custom_options ( $options ) {
    $options['cache_max_age_seconds']               = 3600;
    $options['cache_old_content_threshold_seconds'] = 604800;
    $options['cache_old_content_max_age_seconds']   = 86400;
    return $options;
add_filter( 'addh_options', 'addh_custom_options' );

Modifying the Cache-Control header format

The default Cache-Control header format is: public, max-age=%s

One %s placeholder must exist. It is replaced by the number of seconds.

The following will return: public, max-age=%s, no-transform

function addh_custom_cache_control_format ( $default ) {
    return $default . ', no-transform';
add_filter( 'addh_cache_control_header_format', 'addh_custom_cache_control_format' );

Add custom headers

You can use the addh_headers filter hook to have access to all the generated headers or add custom headers. For example:

function addh_custom_headers( $headers ) {
    $headers['X-XSS-Protection'] = '1; mode=block';
    $headers['X-Frame-Options'] = 'SAMEORIGIN';
    $headers['X-Content-Type-Options'] = 'nosniff';
    return $headers;
add_filter( 'addh_headers', 'addh_custom_headers' );

Filter and remove headers

In this example the Pragma header is removed.

function addh_filter_final_headers ( $headers ) {
    return $headers;
add_filter( 'addh_headers', 'addh_filter_final_headers' );