While server based detection using mod_rewrite or similar will provide a much better level of performance, sometimes you just want to handle it from within a script. Below are examples in javascript, perl and php so you can choose your language/environment. I would strongly recommend using a server side script (e.g. perl or php) but I’ve included a javascript version for reference. Of course if you’re cutting edge then you could run the javascript on the server-side too.
I hope you find this code useful. If you find any bugs or logical errors please let me know.
NOTE: This code is designed to support 3 key classes of device – PC, iPhone and POM (Plain Old Mobile). See the comments by the winmo detection that shows where you may like to extend this for other high-end devices (e.g. Windows Mobile or Symbian).
Javascript Example:
/** * Copyright © 2009 * Rob Manson, Sean McCarthy and http://MOBusiness.com.au * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Javascript Not-Device Detection Function * Find out what type of device this is * returns string - either pc, pom or iphone */ function _not_device_detection() { var ua = navigator.userAgent; var qs = window.location.search.substring(1); var agent = "error"; var re = { "pcswitch" : new RegExp("pc", "i"), "pomswitch" : new RegExp("pom", "i"), "iphoneswitch" : new RegExp("iphone", "i"), "iphone" : new RegExp("iP(hone|od)(;|\s)", "i"), "winmo" : new RegExp("Windows\s+CE", "i"), "linux" : new RegExp("Linux", "i"), "windows" : new RegExp("Windows", "i"), "mac" : new RegExp("OS\s+(X|9)", "i"), "solaris" : new RegExp("Solaris", "i"), "bsd" : new RegExp("BSD", "i") }; if (qs.match(re.pcswitch)) { /* This assumes you have a single query string value of "pc" */ agent = "pc"; } else if (qs.match(re.pomswitch)) { /* This assumes you have a single query string value of "pom" */ agent = "pom"; } else if (qs.match(re.iphoneswitch)) { /* This assumes you have a single query string value of "iphone" */ agent = "iphone"; } else if (ua.match(re.iphone)) { /* This user agent should be an iPhone/iPod */ agent = "iphone"; } else if (ua.match(re.winmo)) { /* This user agent should be a Windows Mobile device - you may want a special class for this and possibly high-end Symbian too */ agent = "pom"; } else if ( (!ua.match(re.linux)) && (!ua.match(re.windows)) && (!ua.match(re.mac)) && (!ua.match(re.solaris)) && (!ua.match(re.bsd)) ) { /* This user agent is not Linux, Windows, a Mac, Solaris or BSD */ agent = "pom"; } else { /* Otherwise assume it's a PC */ agent = "pc"; } return agent; }
Perl Example:
###################################################################################################### ## Copyright © 2009 ## Rob Manson, Sean McCarthy and http://MOBusiness.com.au ## ## This program is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program. If not, see . ## ## Perl Not-Device Detection method ## Find out what type of device this is ## returns string - either pc, pom or iphone ###################################################################################################### sub _not_device_detection() { # either pass in \%ENV or pack the UA and QUERY into a hashref and pass that in my $env = shift; my $ua = $env->{HTTP_USER_AGENT}; my $qs = $env->{QUERY_STRING}; my $agent = "error"; if ($qs =~ /^pc$/i) { # This assumes you have a single query string value of "pc" $agent = "pc"; } elsif ($qs =~ /^pom$/i) { # This assumes you have a single query string value of "pom" $agent = "pom"; } elsif ($qs =~ /^iphone$/i) { # This assumes you have a single query string value of "iphone" $agent = "iphone"; } elsif ($ua =~ /iP(hone|od)(;|\s)/i) { # This user agent should be an iPhone/iPod $agent = "iphone"; } elsif ($ua =~ /Windows\s+CE/i) { # This user agent should be a Windows Mobile device - you may want a special class for this and possibly high-end Symbian too $agent = "pom"; } elsif ( (!$ua =~ /Linux/i) && (!$ua =~ /Win/i) && (!$ua =~ /OS\s+(X|9)/i) && (!$ua =~ /Solaris/i) && (!$ua =~ /BSD/i) ) { # This user agent is not Linux, Windows, a Mac, Solaris or BSD $agent = "pom"; } else { # Otherwise assume it's a PC $agent = "pc"; } return $agent; }
PHP Example:
/** * Copyright © 2009 * Rob Manson, Sean McCarthy and http://MOBusiness.com.au * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * PHP Not-Device Detection Function * Find out what type of device this is * returns string - either pc, pom or iphone */ function _not_device_detection() { $ua = $_SERVER['HTTP_USER_AGENT']; $qs = $_SERVER['QUERY_STRING']; $agent = "error"; if (preg_match('/^pc$/i', $qs)) { /* This assumes you have a single query string value of "pc" */ $agent = "pc"; } else if (preg_match('/^pom$/i', $qs)) { /* This assumes you have a single query string value of "pom" */ $agent = "pom"; } else if (preg_match('/^iphone$/i', $qs)) { /* This assumes you have a single query string value of "iphone" */ $agent = "iphone"; } else if (preg_match('/.*iP(hone|od)(;|\s).*$/i', $ua)) { /* This user agent should be an iPhone/iPod */ $agent = "iphone"; } else if (preg_match('/Windows\s+CE/i', $ua)) { /* This user agent should be a Windows Mobile device - you may want a special class for this and possibly high-end Symbian too */ $agent = "pom"; } else if ( (!preg_match('/Linux/i', $ua)) and (!preg_match('/Win/i', $ua)) and (!preg_match('/OS\s+(X|9)/i', $ua)) and (!preg_match('/Solaris/i', $ua)) and (!preg_match('/BSD/i', $ua)) ) { /* This user agent is not Linux, Windows, a Mac, Solaris or BSD */ $agent = "pom"; } else { /* Otherwise assume it's a PC */ $agent = "pc"; } return $agent; }
There are some other more exact methods to detect a mobile device. My preferred one is WURFL.
Hi Adrian,
har…I think we established your love of WURFL during our discussion on your blog earlier 8)
I also still stand by my comments that WURFL is a great tool for general device capability research – but a terrible tool for doing live profiling if you try to use it to cater for too many different capabilities.
Either you create a design nightmare or you use automatic size and format transcoding and lose control over image quality and design integrity. You also drive up complexity.
I have yet to see a good business case that justifies a site supporting hundreds if not thousands of different individual device profiles. I believe they should only support somewhere between 3 and 10 depending upon your business model and target audience.
Don’t get me wrong…I LOVE WURFL too…I just think we have really different views on how to use it.
I agree with both the above comments to some degree. I have been putting together some code for device detection and will probably incorporate the above code (the Perl version). I use WURFL Device Data for detection but strip out the capabilities I don’t need, which does reduce the complexity and size a bit. I also use it as the ‘fallback’ when javascript doesn’t tell the perl site script what size a user’s display is, since all I really want to know is what size device display the visitor is using. This also means I don’t do the computationally heavy WURFL stuff if it isn’t necessary.
And I agree that trying to design a site for thousands of devices is probable not efficient use of your time. But being able to define certain site parameters, when necessary, can be a very good thing.
Thanks for the code.