Experimenting with PageSpeed

Experimental Framework

The Run Experiment module allows you to gather data on what filters perform best for your site using A/B testing. It reports to your Google Analytics account, storing data in a custom variable. It often makes sense to first experiment manually using the per-request configuration described below to get an idea of which filters might help your site, and then run a controlled experiment to test whether these filters actually speed it up in practice.

Per-request configuration

Query parameters, request headers, and response headers can be used to disable PageSpeed, specify the set of filters applied to an HTML page, and control some inlining limits.

Query parameters take the form of name=value and parameters are separated by an ampersand (&). For example:

  http://modpagespeed.com/rewrite_css.html?PageSpeed=on&PageSpeedFilters=rewrite_css

Request and response headers take the form of name: value and each header is on its own line. For example:

GET /rewrite_css.html HTTP/1.1
Host: modpagespeed.com
PageSpeed: on
PageSpeedFilters: rewrite_css

For backwards compatibility, these can start with ModPagespeed instead of PageSpeed, but this usage is deprecated.

Query parameters can be added to the URL of the page or resource being fetched, request headers can be set in the request for pages and resources, and response headers can be set in the response of HTML pages (but not resources). These settings affect only the given request. If all three (query parameters and both headers) are used in the same request the query parameters will be applied first, followed by the request headers, followed by the response headers. Later settings override earlier settings but a filter disable in any location always overrides subsequent enables.

There are two supported methods of adding response headers that PageSpeed will be able to observe and process. The first is to add response headers with a content handler such as PHP or Perl. The second is to add response headers at an origin server and run PageSpeed as a proxy in front of it. The use of mod_headers (Apache) or add_header (Nginx) on the same webserver as PageSpeed will not work because headers will be inserted after PageSpeed has already processed the page.

Sticky Query Parameters

Query parameters can be set to be "sticky" and persist across requests using cookies. Sticky query parameters can be set by providing the sticky query parameter option in a request, and the server will respond with a cookie, valid for the duration specified in the PageSpeed configuration.

To prevent abuse, a "secret token" must be provided in the initial request to enable setting cookies.

Apache:
ModPagespeedStickyQueryParameters example_token
Nginx:
pagespeed StickyQueryParameters example_token

The duration, in milliseconds, for which the cookie will be valid can be set in the PageSpeed configuration.

Apache:
ModPagespeedOptionCookiesDurationMs 12345
Nginx:
pagespeed OptionCookiesDurationMs 12345

The request must specify the token in a query parameter, for example:

http://modpagespeed.com/rewrite_css.html?PageSpeedStickyQueryParameters=example_token&PageSpeedFilters=+remove_comments

A request with the proper sticky query parameter token will cause the server to respond with a Set-Cookie in the response. Any request not containing the correct token will not receive the Set-Cookie response. Future responses with the received cookie will also enable the options set in the query parameter with the sticky query parameter. In this case, the remove-comments filter would be enabled.

Enabling and disabling PageSpeed

Query parameters:

  PageSpeed=off
  PageSpeed=on

Request & Response headers:

  PageSpeed: off
  PageSpeed: on

The first line disables PageSpeed rewriting, the second line enables it.

Specifying the filters applied

Query parameters:

  PageSpeedFilters=comma-separated list of names

Request & Response headers:

  PageSpeedFilters: comma-separated list of names

This specifies the set of filters to apply to the page. The list of settings includes all filter names and a few shortcut names:

When any filter is specified without a "+" or "-", any filters not explicitly enabled are disabled. Filters and shortcuts can be explicitly disabled by preceding the name by a minus sign ('-'), which is useful after using a shortcut. For example, "core,-combine_css" enables all the core filters except combine_css.

If all names are prefixed with "+" or "-" then the filter set is incrementally adjusted from the current system settings based on the configuration files. For example, in a server with RewriteLevel set to CoreFilters, the query-string

  ?PageSpeedFilters=+lazyload_images,-inline_images

will leave all the core filters enabled, but will add lazyload_images and disable inline images.

Controlling inlining limits

Query parameters:

  PageSpeedCssFlattenMaxBytes=value
  PageSpeedCssImageInlineMaxBytes=value
  PageSpeedCssInlineMaxBytes=value
  PageSpeedImageInlineMaxBytes=value
  PageSpeedJsInlineMaxBytes=value

Request & Response headers:

  PageSpeedCssFlattenMaxBytes: value
  PageSpeedCssImageInlineMaxBytes: value
  PageSpeedCssInlineMaxBytes: value
  PageSpeedImageInlineMaxBytes: value
  PageSpeedJsInlineMaxBytes: value

These specify the limits for the following inlining options:

Here is an example that combines many of the above query parameters to enable all the core filters except the cache extension filters, and sets the JavaScript inlining limit to a high value so that most JavaScript files will be inlined:

  http://..../index.html?PageSpeedFilters=core,-extend_cache&PageSpeedJsInlineMaxBytes=102400

Client options in queries and headers

This is an experimental option, its name and values are subject to change. This option allows the client to customize the optimizations applied to a request and can be used in a header or query parameter.

As a query parameter:

  X-PSA-Client-Options=client-options

As a Request or Response header:

  X-PSA-Client-Options: client-options

The format of client-options is

  name1=value1,name2=value2, ...

The order of the name-value pairs does not matter. The supported options are:

  v=1

Version of the header. '1' is the only supported version for now.

  m=integer-value

Mode. Valid values are

  iqp=integer-value

Image quality preference. Valid values are

Restrict per-request configuration

Note: New feature as of 1.9.32.1

Interpretation of PageSpeed query parameters and headers can be restricted to requests specifying a request option override token. The token is specified in the server configuration file and disallows request option overriding when the request does not specify the correct token. This option can be used to reduce the attack surface of denial of service attacks.

Apache:
ModPagespeedRequestOptionOverride example_token
Nginx:
pagespeed RequestOptionOverride example_token

This feature provides a mechanism to restrict the ability for filters and options to be specified in query parameters and request headers. To enable it, an override token must be specified in the configuration file, and requests must specify the same token for filters and options to be applied. Query parameters, except for PageSpeed=on, PageSpeed=off, or PageSpeed=noscript will then only be interpreted when accompanied by the correct RequestOptionOverride token. For example, the rewrite_css filter would be used in this example.

The request must specify the token in a query parameter or header, for example:

  http://modpagespeed.com/rewrite_css.html?PageSpeed=on&PageSpeedFilters=rewrite_css&PageSpeedRequestOptionOverride=example_token

Any request not containing the correct RequestOptionOverride token or not containing a RequestOptionOverride token will ignore all other PageSpeed filters and options specified.

Note: even if applied, PageSpeed=on/off/noscript still takes effect.

Noop query-parameter

Note: New feature as of 1.10.33.0

To help bust browser caches, especially with experiments, any PageSpeed URL can accept the PageSpeedNoop query-paramter with an integer value. This query-parameter will be ignored by PageSpeed and stripped from the URL early in the processing flow. The origin will not see the Noop parameter, and PageSpeed's server-caches will not be affected. However, it will prevent your browser from using a cached value.

Examples:

http://images.example.com/foo.png?PageSpeedNoop=571
http://www.example.com/index.html?q=foo&PageSpeedNoop=99438

Configuring mod_pagespeed_examples

Note: Apache-only

mod_pagespeed ships with a directory of sample HTML, JavaScript, Image, and CSS files to demonstrate the rewrite passes that it executes. These also form the basis of an installation smoke-test to ensure that the configured system is operating correctly. Assuming the files are installed in /var/www/mod_pagespeed_example, the following configuration file fragment will enable them to be served using reasonable caching headers.

    # These caching headers are set up for the mod_pagespeed example, and
    # also serve as a demonstration of good values to set for the entire
    # site, if it is to be optimized by mod_pagespeed.

    <Directory /var/www/mod_pagespeed_example>
      # To enable to show that mod_pagespeed to rewrites web pages, we must
      # turn off Etags for HTML files and eliminate caching altogether.
      # mod_pagespeed should rewrite HTML files each time they are served.
      # The first time mod_pagespeed sees an HTML file, it may not optimize
      # it fully.  It will optimize better after the second view.  Caching
      # defeats this behavior.
      <FilesMatch "\.(html|htm)$">
        Header unset Etag
        Header set Cache-control "max-age=0, no-cache"
      </FilesMatch>

      # Images, styles, and JavaScript are all cache-extended for
      # a year by rewriting URLs to include a content hash..  mod_pagespeed,
      # can only do this if the resources are cacheable in the first place.
      # The origin caching policy, set here to 10 minutes, dictates how
      # frequently mod_pagespeed must re-read the content files and recompute
      # the content-hash.  As long as the content doesn't actually change,
      # the content-hash will remain the same, and the resources stored
      # in browser caches will stay relevant.
      <FilesMatch "\.(jpg|jpeg|gif|png|js|css)$">
        Header unset Etag
        Header set Cache-control "public, max-age=600"
      </FilesMatch>
    </Directory>