This content originally appeared on Web Performance Calendar and was authored by Luca Passani
If your quest for fast goes through device detection, you’ll want to pay attention to this.
Introduction
I’ll go out on a limb and make a wild guess: if you care about web performance, that’s because you want to deliver great UX to users. Assuming my guess is right, in the last two decades the performance of websites and apps on mobile devices has been a key aspect of getting it right across mobile devices as well.
I’m not here for a history lesson, yet a little summary is useful to bring everyone on the same page. There was a time somewhere between the late ‘90s and 2010 when making a distinction about the web and the mobile web made a lot of sense. In fact, we almost did not need to make a distinction, the difference was there for everyone to see: UX on (WAP) mobile phones and UX on “the wired web” were so far apart that developers needed to account for different experiences on the different platforms. Considering it one platform? Ridiculous for everyone but the most visionary among us techies.
That was an age when delivering great UX was tantamount to understanding which devices people were using. That was the time when the noble art of (mobile) Device Detection was born. Companies needed a framework to understand whether HTTP requests were coming from a fully-fledged desktop browser, or a little Nokia phone with a numeric keypad and a tiny display. As a minimum, mobile devices would be directed to a specific m.* (mDot) wap site, but further optimization that would look at the specific features of each device was also normal thanks to tools like WURFL (a repository of mobile devices that applications could query in real time through an API). Desktop web browser would be directed to www
.
Then 2010 came. Smartphones had arrived, for real this time. CSS Media Queries on mobile browsers became the norm and this made RWD – Responsive Web Design – the new standard for web development. Complex websites would columnify themselves on smartphones and tablets. From that moment, thinking of the mobile web as a separate entity from the web no longer made sense. That was the moment where the need for Device Detection decreased. It didn’t fade away, but certainly it became more confined to more “niche” use cases. (that was the time when WURFL went from being an open-source project to becoming a commercial product, coincidentally… or maybe not so coincidentally, but I digress).
Device Detection and Performance
Long story short, many developers who deal with performance today don’t think of device detection, and they’ll be happy with the level of device-awareness that Media Queries and JS feature detection delivers. Yet, some companies still elect to push the envelope, which means optimizing on a device by device basis. Here at ScientiaMobile we know it well. Not only are the WURFL guys, but one of our main products, ImageEngine, is an ImageCDN: we are in charge of delivering the optimal version of images to apps and (responsive) web sites depending on which device each user holds in their hands. The magic relies on our ability to detect the device, i.e. to analyze HTTP requests and determine in real time the capabilities of that phone, tablet, smart-TV or whatever other funky device the guy who likes to browse the web with his wristwatch may hold. In other words, Device Detection can be at the core of web performance in many cases.
Device Detection is changing. Google dixit.
Old timers may have detected (no pun intended) that I am probably talking about the HTTP User-Agent string when I talk about detecting mobile devices. And they would be right. That little string has been part of the HTTP specs time immemorable and tech companies of all kinds have come to rely on it for web performance, for security, for serving relevant ads, for streaming video and for a plethora of other use cases.
You might expect that the User-Agent string is here to stay then, right? Wrong. Google has decided that they don’t want it and have already started killing it in Chrome and all Chromium-based browsers. Technically they don’t call it “killing the User-Agent”. Initially they called it freezing the UA string, then they moved to “UA reduction”. What this means in practice is that “an excuse for a user-agent string” will still be there, but it won’t disclose any information on the device and it will even lie on the Android version the device is running.
You may wonder what the rationale behind this decision is, and I could use this space and more to provide my opinion (I think this is an example of a bully exploiting its market dominance to hurt the rest of the ecosystem with a might makes right move), but let’s not go there. The official story is that the User-Agent leaked too much personal information and Google cares about users privacy so much that they just had to get rid of the UA string. Enough laughing.
What you may be more curious about is how developers will be able to tell the make and model of a device for the thousands legit usages in the technology industry.
Enter Client-Hints
The alternative to the UA string are UA Client-Hints (UA-CH), i.e. an additional set of HTTP headers that will carry bits of information about a browser and device that were previously traceable in or through the UA string. The problem is that those headers won’t be automatically available for each request. Rather, they’ll need to be explicitly requested through a rather complex HTTP dance between browser and server. The browser will send a request without any device information, and the server that cares about it will say “I need that additional information, dear”. Hopefully, at that point, newer HTTPS requests will carry the UA-CH. From a WebPerf perspective this isn’t good. It sucks in fact. But there is more. Requesting UA-CH implies that developers are proactively configuring their servers to demand that the good data is sent. This is key if their business model depends on access to device information.
The Gory Details: what the UA string still is. And what it’s going to be.
This is what the UA string of a Pixel 5 looks like in December 2022:
Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4812.0 Mobile Safari/537.36
In a matter of weeks, as newer Android updates roll out in Q1 2023, this UA string will be replaced with:
Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Mobile Safari/537.36
The platform, platform version, the device model, the browser name and browser version are there today. They’ll soon be gone.
Not all client hints are created equal
There are actually two kinds of User-Agent Client Hints you can expect to see in your traffic – “low entropy” and “high entropy”. The former is the set of Client Hints you get for free with every request from a browser that supports User-Agent Client Hints. This kind of Client-Hints are not very “informative”. You want the second kind, though, the “high entropy” ones, as they provide all the bits and pieces for optimal device detection.
The terms “low entropy” and “high entropy” are used in the User-Agent Client Hint specification to describe two possible sets of headers you may receive. At ScientiaMobile we talk about “Basic” header quality and “Full” header quality respectively, as this is the key differentiator to what WURFL can do to perform high quality Device Detection.
While “Basic” User-Agent Client Hints are included with every request, the “Full” header quality must be specifically requested. This means that you need to configure your servers to request them. Here’s a table that explains what pieces of information you get with each set of User-Agent Client Hints.
User-Agent Client Hint | Low/High Entropy |
sec-ch-ua | Low Entropy |
sec-ch-ua-mobile | Low Entropy |
sec-ch-ua-platform | Low Entropy |
sec-ch-ua-platform-version | High Entropy |
sec-ch-ua-full-version (deprecated) | High Entropy |
sec-ch-ua-full-version-list | High Entropy |
sec-ch-ua-model | High Entropy |
sec-ch-ua-arch | High Entropy |
sec-ch-ua-bitness | High Entropy |
sec-ch-ua-wow64 | High Entropy |
If you don’t request the entire set of User-Agent Client Hints explicitly, the ones you are seeing in your logs are most likely the “low entropy” stuff. In practice, this means that you will only be able to tell the OS platform, a list of possible browsers that requested the page and Chromium’s idea of whether the client is a mobile device without further differentiation between tablets, desktops, Smart TVs, IOT devices and so on.
Here’s an example of what you are likely to see with just the “Basic” or “low entropy” set of User-Agent Client Hints:
User-Agent: Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Mobile Safari/537.36 Sec-Ch-Ua: "Chromium";v="106", "Microsoft Edge";v="106", "Not;A=Brand";v="99" Sec-Ch-Ua-Platform: "Android" Sec-Ch-Ua-Mobile: ?1
Note: If you are seeing “Full” header quality or “high entropy” User-Agent Client Hints in your logs, the “Basic” header quality or “low entropy” User-Agent Client Hints are also included in the request.
These set of “low entropy” User-Agent Client Hints tells us that:
- The browser originating the request could be either Chromium or Microsoft Edge
- That the originating device is considered a mobile device
More importantly, we know that this is an Android device, but not the version. The device make and model are unknown, and so is the exact version of the browser.
Please note that the “Not A Brand” token in the Sec-Ch-Ua aka the Brands header is intentional and is added according to the User-Agent Client Hints specification. This is called GREASE-ing, an allusion to how the Chromium team ensures cipher suite compatibility.
Now let’s put this in contrast with the complete “high entropy” User-Agent Client Hints. When you specifically request the “full” set of User-Agent Client Hint headers (and you must request them individually), you also receive the platform version, the full browser version, the model name, the architecture of the device and, depending on the platform, the “bitness” or the bit width of the device.
Here’s a specimen of a HTTP request that contains those high entropy Client-Hints:
User-Agent: Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Mobile Safari/537.36 Sec-Ch-Ua: "Chromium";v="106", "Microsoft Edge";v="106", "Not;A=Brand";v="99" Sec-Ch-Ua-Full-Version-List: "Chromium";v="106.0.5249.65", "Microsoft Edge";v="106.0.5249.65", "Not;A=Brand";v="99.0.0.0" Sec-Ch-Ua-Platform: "Android" Sec-Ch-Ua-Mobile: ?1 Sec-Ch-Ua-Platform-Version: 13.0.0 Sec-Ch-Ua-Model: Pixel 6 Pro
We can immediately see that we get quite a lot of additional information, such as:
- Full version for the browser that originated the request
- Full platform/OS version
- Device model name
In other words, all the good stuff is available again with high entropy Client Hints.
Interestingly, the actual browser name is never directly exposed via User-Agent Client Hints. Instead, the raw header data will always contain a comma separated list of browser brands.This is an intentional part of the User-Agent Client Hints specification and was introduced with the assumption that this would make it harder for developers to discriminate against minor browsers. Without debating that move here, it is important to note that the WURFL API is able to sort through this information and return the accurate browser name.
How to make sure that the good client-hints get sent
If your business depends on – or simply benefits from – accurate device detection, you should probably go out of your way to ensure access to the “Full” header quality User-Agent Client Hints. Without proactive action, Device Detection quality will not be preserved and this is likely to become degraded quality of service.
You should configure your application and HTTP servers to request those additional headers through the Accept-CH
header. It will need to advertise which Client-Hints are needed and – of course – you want the good ones, i.e. all the “Full” header quality User-Agent Client Hints. We recommend this:
Accept-CH: sec-ch-ua-platform-version,sec-ch-ua-full-version,sec-ch-ua-full-version-list,sec-ch-ua-model,sec-ch-ua-arch,sec-ch-ua-bitness,sec-ch-ua-wow64
Additionally, you may want the server to signal that these high entropy Client Hints are critical for an optimal browsing experience on your website. You can do this by setting the Critical-CH response header as follows:
Critical-CH: sec-ch-ua-platform-version,sec-ch-ua-full-version,sec-ch-ua-full-version-list,sec-ch-ua-model,sec-ch-ua-arch,sec-ch-ua-bitness,sec-ch-ua-wow64
If you are using a third-party cloud-based solution, you will also need to delegate access to the User-Agent Client Hints to that party. You can do this by using a Permissions-Policy header. Here’s an example from one of our services (WURFL.js Lite), i.e. what we recommend to users of that service:
permissions-policy: ch-ua-platform-version=("https://wurfl.io"),ch-ua-full-version=("https://wurfl.io"),ch-ua-full-version-list=("https://wurfl.io"),ch-ua-model=("https://wurfl.io"),ch-ua-arch=("https://wurfl.io"),ch-ua-bitness=("https://wurfl.io"),ch-ua-wow64=("https://wurfl.io")
(More detailed information on this topic is available in ScientiaMobile’s “Request and Implement User-Agent Client Hints” technical documentation here ).
We realize that different web servers have different methods of setting request headers, so we have kept these instructions general enough to be server/platform agnostic. We also have Apache specific instructions on enabling User-Agent Client Hints support (here)
This content originally appeared on Web Performance Calendar and was authored by Luca Passani
Luca Passani | Sciencx (2022-12-07T05:10:00+00:00) So you heard of Client-Hints and you think you got time, right? Wrong.. Retrieved from https://www.scien.cx/2022/12/07/so-you-heard-of-client-hints-and-you-think-you-got-time-right-wrong/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.