Separate Nginx Mobile and Desktop User-Agent Cache

Share This:
Nginx Separate Mobile and Desktop Cache

You may want to separate your server-side Nginx cache between mobile and desktop users determined by their browser. This guide will show you how to configure your Nginx FastCGI or reverse proxy cache to have separate caches for mobile and desktop user agents. You can make this work for Redis cache integrated with Nginx too.

The inspiration for this tutorial came from one of my favorite hosts (read why here) which has beautiful analytics data for your WordPress sites as shown in the screenshot below (check out the demo of their dashboard here).

Handheld vs. Desktop

Separate Nginx Mobile and Desktop User-Agent Cache

Google helped me find a list of User-agent strings that seemed pretty complete so I used this as the basis for separating the mobile, tablet, handheld and desktop.

This is by no means exhaustive so please consider this a proof of concept.

We are going to use the nginx map directive to detect user agents and place them in mobile and desktop categories.

Then we will use this variable and adjust the cache key for either a proxy_cache (see tutorial) or fastcgi_cache using Nginx.

Here is the map command that must go in the http { block of your nginx.conf

# map the list of user agents must escape ( with \(
map $http_user_agent $mobile_user {
   default "WPSTEAM_DESKTOP";
   # Android
   "~Mozilla/5.0 \(Linux; Android" WPSTEAM_MOBILE;
   # Opera
   "~Opera Mini" WPSTEAM_MOBILE;
   # iOS
   "~Mozilla/5.0 \(iPhone" WPSTEAM_MOBILE;
   # Windows Phone
   "~Mozilla/5.0 \(Windows Phone" WPSTEAM_MOBILE;
   }

Now we need to modify the cache key so we can logically separate desktop and mobile users by altering the fastcgi_cache_key directive to include the $mobile_user key.

You can make similar adjustments for a proxy_cache by adjusting the proxy_cache_key directive.

location ~ \.php$ {
	try_files $uri =404;
	# add cache status
	add_header WP-Steam-Fastcgi-Cache $upstream_cache_status;
	# add the cache skip reason if relevant
	add_header WP-Steam-Skip $skip_reason;
	add_header X-Exception $exception;
	include fastcgi_params;
	fastcgi_pass unix:/run/php/php7.3-fpm.sock;
	fastcgi_split_path_info ^(.+\.php)(.*)$;
	fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
	fastcgi_cache_bypass $http_secret_header $skip_cache;
	fastcgi_no_cache $skip_cache;
	fastcgi_cache WORDPRESS;
        fastcgi_cache_key "$scheme$request_method$host$mobile_user$request_uri";
	fastcgi_cache_valid 404 1m;
	fastcgi_cache_valid 60m;
}

You can also use this $mobile_user variable in a custom access_log directive with nginx to track the mobile visitors using something like this in your http { block

log_format customuseragent '[$time_local] $remote_addr $upstream_cache_status '
                           '$mobile_user $request_method '
                           '"$request_uri" $upstream_response_time';

Then in your nginx virtual host you can define the custom access log

access_log /var/log/nginx/customuseragent.log customuseragent;

Make sure to reload nginx and then you can check the custom access log file

tail -f /var/log/nginx/customuseragent.log

You should see output similar to this

[04/Apr/2020:13:41:10 +0000] 192.226.152.59 MISS WPBSTEAM_MOBILE GET "/" 0.272
[04/Apr/2020:13:41:11 +0000] 192.226.152.59 MISS WPSTEAM_MOBILE GET "/wp-json/recently/v1/widget/5?lang=" 0.076
[04/Apr/2020:13:41:18 +0000] 192.226.152.59 - WPSTEAM_DESKTOP POST "/wp-admin/admin-ajax.php" 0.072
[04/Apr/2020:13:41:19 +0000] 86.101.36.78 HIT WPSTEAM_MOBILE GET "/" -
[04/Apr/2020:13:41:20 +0000] 86.101.36.78 HIT WPSTEAM_MOBILE GET "/wp-json/recently/v1/widget/5?lang=" -
[04/Apr/2020:13:41:20 +0000] 86.101.36.78 MISS WPSTEAM_MOBILE GET "/wp-json/wordpress-popular-posts/v1/popular-posts/widget/3?is_single=" 0.112
[04/Apr/2020:13:41:23 +0000] 2804:1b2:81:b271:85d2:778c:a336:fd28 MISS WPSTEAM_DESKTOP GET "/install-apcu-object-cache-for-php7-for-wordpress-ubuntu-16-04/" 0.140
[04/Apr/2020:13:41:27 +0000] 2804:1b2:81:b271:85d2:778c:a336:fd28 HIT WPSTEAM_DESKTOP GET "/wp-json/recently/v1/widget/5?lang=" -
[04/Apr/2020:13:41:27 +0000] 2804:1b2:81:b271:85d2:778c:a336:fd28 MISS WPSTEAM_DESKTOP GET "/wp-json/wordpress-popular-posts/v1/popular-posts/widget/3?is_single=808" 0.060
[04/Apr/2020:13:41:28 +0000] 1.164.141.46 MISS WPSTEAM_DESKTOP GET "/lets-encrypt-wildcard-ssl-nginx-for-wordpress-ubuntu-18-04/" 0.144
[04/Apr/2020:13:41:30 +0000] 1.164.141.46 HIT WPSTEAM_DESKTOP GET "/wp-json/recently/v1/widget/5?lang=" -
[04/Apr/2020:13:41:30 +0000] 1.164.141.46 MISS WPSTEAM_DESKTOP GET "/wp-json/wordpress-popular-posts/v1/popular-posts/widget/3?is_single=6539" 0.076
Share This:

Popular on WPSteam Right Now!

Leave a Reply

Your email address will not be published. Required fields are marked *

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 22 other subscribers

I need help with...

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 22 other subscribers

I need help with...