Help Your Users `Save-Data`
The breadth and depth of knowledge to absorb in the web performance space is ridiculous. At a minimum, I’m discovering something new nearly every week. Case in point: The Save-Data
header, which I discovered via a Google Developers article by Ilya Grigorik.
If you’re looking for the tl;dr version of how Save-Data
works, let me oblige you: If you use Chrome’s Data Saver extension on your desktop device or opt into data savings on the Android version of Chrome, every request that Chrome sends to a server will contain a Save-Data
header with a value of On
. While this doesn’t do anything for your site out of the gate, you can consider it an opportunity. Given an opportunity to operate on a header like this, what would you do?
Let me give you a few ideas!
Change your image delivery strategy
I don’t know if you’ve noticed, but images are often the largest chunk of the total payload of any given page. So perhaps the most impactful step you can take with Save-Data
is to change how images are delivered. What I settled on for my blog was to rewrite requests for high DPI images to low DPI images. When I serve image sets like this on my site, I do so using the <picture>
element to serve WebP images with a JPEG or PNG fallback like so:
<picture>
<source srcset="/img/george-and-susan-1x.webp 1x, /img/george-and-susan-2x.webp 2x">
<source srcset="/img/george-and-susan-1x.jpg 1x, /img/george-and-susan-2x.jpg 2x">
<img src="/img/george-and-susan-1x.jpg" alt="LET'S NOT GET CRAZY HERE" width="320" height="240">
</picture>
This solution is backed by tech that’s baked into modern browsers. The <picture>
element delivers the optimal image format according to a browser’s capabilities, while srcset
will help the browser decide what looks best for any given device’s screen. Unfortunately, both <picture>
and srcset
lacks control over which image source to serve for users who want to save data. Nor should they! That’s not the job of srcset
or <picture>
.
This is where Save-Data
comes in handy. When users visit my site and send a Save-Data
request header, I use mod_rewrite in Apache to serve low DPI images in lieu of high DPI ones:
RewriteCond %{HTTP:Save-Data} =on [NC]
RewriteRule ^(.*)-2x.(png|jpe?g|webp)$ $1-1x.$2 [R=302,L]
If you’re unfamiliar with mod_rewrite, the first line is a condition that checks if the Save-Data
header is present and contains a value of on
. The [NC]
flag merely tells mod_rewrite to perform a case-insensitive match. If the condition is met, the RewriteRule
looks for any requests for a PNG, JPEG or WebP asset ending in -2x
(the high DPI version), and redirects such requests to an asset ending in -1x
(the low DPI version). The R=302
flag signals to the browser that this is a temporary (302) redirect. Since the user can toggle Data Saver on or off at will, we don’t want to send a permanent (301) redirect, as the browser will cache it. Caching the redirect ensures that it will be in effect even if Data Saver is turned off later on.

Aren’t redirects bad for performance? Most of the time, yes. Redirects add to latency because it takes longer for a request to be resolved. In this instance, however, it’s a fitting solution. We don’t want to rewrite requests without redirecting them because then low-quality images get cached under the same URLs as high-quality ones. What if the user connects to a wifi network, turns off Data Saver, and return to the site at a later time? The low-quality image will be served from the cache, even when Data Saver is turned off. That’s not at all what we want. If the user isn’t using Data Saver, we should assume the default image delivery strategy.
Of course, there are other ways you could change your image delivery in the presence of Save-Data
. For example, Cory Dowdy wrote a post detailing how he uses Save-Data
to serve lower quality images. Save-Data
gives you lots of room to devise an image delivery strategy that makes the best sense for your site or application.
Opt out of server pushes
Server push is good stuff if you’re on HTTP/2 and can use it. It allows you send assets to the client before they ever know they need them. The problem with it, though, is it can be weirdly unpredictable in select scenarios. On my site, I use it to push CSS only, and this generally works well. Although, I do tailor my push strategy in Apache to avoid browsers that have issues with it (i.e., Safari) like so:
<If "%{HTTP_USER_AGENT} =~ /^(?=.*safari)(?!.*chrome).*/i">
Header add Link "</css/global.5aa545cb.css>; rel=preload; as=style; nopush"
</If>
<Else>
Header add Link "</css/global.5aa545cb.css>; rel=preload; as=style"
</Else>
In this instance, I’m saying “Hey, I want you to preemptively push my site’s CSS to people, but only if they’re not using Safari.” Even if Safari users come by, they’ll still get a preload
resource hint (albeit with a nopush
attribute to discourage my server from pushing anything).
Even so, it would behoove us to be extra cautious when it comes to pushing assets for users with Data Saver turned on. In the case of my blog, I decided I wouldn’t push anything to anyone who had Data Saver enabled. To accomplish this, I made the following change to the initial <If>
header:
<If "%{HTTP:Save-Data} == 'on' || %{HTTP_USER_AGENT} =~ /^(?=.*safari)(?!.*chrome).*/i">
This is the same as my initial configuration, but with an additional condition that says “Hey, if Save-Data
is present and set to a value of on
, don’t be pushing that stylesheet. Just preload
it instead.” It might not be a big change, but it’s one of those little things that could help visitors to avoid wasted data if a push was in vain for any reason.
Change how you deliver markup
With Save-Data
, you could elect to change what parts of the document you deliver. This presents all sorts of opportunities, but before you can embark on this errand, you’ll need to check for the Save-Data
header in a back end language. In PHP, such a check might look something like this:
$saveData = (isset($_SERVER["HTTP_SAVE_DATA"]) && stristr($_SERVER["HTTP_SAVE_DATA"], "on") !== false) ? true : false;
On my blog, I use this $saveData
boolean in various places to remove markup for images that aren’t crucial to the content of a given page. For example, one of my articles has some animated GIFs and other humorous images that are funny little flourishes for users who don’t mind them. But they are heavy, and not really necessary to communicate the central point of the article. I also remove the header illustration and a teeny tiny thumbnail of my book from the nav.

From a payload perspective, this can certainly have a profound effect:

Another opportunity would be to use the aforementioned $saveData
boolean to put a save-data
class on the <html>
element:
<html class="if($saveData === true) : echo("save-data"); endif; ?>">
With this class, I could then write styles that could change what assets are used in background-image
properties, or any CSS property that references external assets. For example:
/* Just a regular ol' background image */
body {
background-image: url("/images/bg.png");
}
/* A lower quality background image for users with Data Saver turned on */
.save-data body {
background-image: url("/images/bg-lowsrc.png");
}
Markup isn’t the only thing you could modify the delivery of. You could do the same for videos, or even do something as simple as delivering fewer search results per page. Or whatever you can think of!
Conclusion
The Save-Data
header gives you a great opportunity to lend a hand to users who are asking you to help them, well, save data. You could use URL rewriting to change media delivery, change how you deliver markup, or really just about anything that you could think of.
How will you help your users Save-Data
? Leave a comment and let your ideas be heard!
Help Your Users `Save-Data` is a post from CSS-Tricks
LEAVE A REPLY
You must be logged in to post a comment.