Detecting mobile, and providing a way out

This post is more than 2 years old.

After a little run in with a Gawker site this weekend that pushed me into a mobile version of their site and wouldn't let me out, I thought I'd share two quick tips, and examples, of how to both auto detect a mobile device as well as allowing mobile devices to run your normal web site.

First, for detection, myself and others have been making use of a free script from Detect Mobile Browser. This little one page site provides scripts in multiple languages including ColdFusion. It's user agent based which means it won't be perfect. If some new device uses a unique user agent in the future then you will need to update, but for quick and dirty nothing beats it. Here's an example of the output from the site.

<cfif reFindNoCase("android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino",CGI.HTTP_USER_AGENT) GT 0 OR reFindNoCase("1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-",Left(CGI.HTTP_USER_AGENT,4)) GT 0><cflocation url=""></cfif>

(Note - I may add a space or two in the block above if it renders poorly on the site.) I've used this in a few places and it's been fine for me. That's only part of the issue though. This will work fine if someone comes to your site's home page, but what if they come to a deeper page? You have a few different options here. One is to simply look at the requested page, and the query string, and pass them along to the mobile version. So a request for entry.cfm?id=X means you want to redirect to mobile/entry.cfm?id=x. A site that makes use of cgi.path_info, like BlogCFC, required slightly different code. Here's how Dave Ferguson handled it with BlogCFC:

<!--- this is all wrapped in a CFIF like shown above ---> <cfset urlVars=reReplaceNoCase(trim(cgi.path_info), '.+\.cfm/? *', '')> <cfif listlen(urlVars, '/') LTE 1> <!---NOT AN SES URL---> <cfset urlVars = ''> </cfif> <cfset path = cgi.http_host & ListDeleteAt(cgi.script_name, listLen(cgi.script_name, "/"), "/")> <cfif NOT right(path, 6) EQ "mobile"> <cflocation url="http://#path#/mobile/index.cfm#urlVars#" addToken="false"> </cfif>

Obviously you have a few options here, but I think the critical point is this: Do not bother auto pushing someone to a mobile site if you're going to lose the original context of their request. Supporting this should be considering a required, not optional feature.

And speaking of what's required, I also believe, very strongly, that you should provide a way for folks to leave your mobile site. I recently acquired a Motorola Xoom tablet (long story short - I love it), and it renders web pages really well. On more then one site I get automatically pushed to a mobile version. Most support allowing me to click a link and return to the normal version. Unfortunately, all of Gawker's web sites do not. (But let's be honest, their entire network has been pretty badly redesigned lately so this comes as no surprise. I swear I'm not bitter. Honest.) Here is a simple way to support allowing people to leave your mobile site, again, based on BlogCFC.

First, provide a link with some kind of flag:

<p><a href="" id="leaveMobileLink">Click Here</a> to exit mobile version.</p>

Then simply look for it in your core Application file:

<cfif structKeyExists(url, "nomobile")> <cfset session.nomobile = true> </cfif>

You can then look for this session variable when detecting mobile...

<cfif not structKeyExists(session, "nomobile") and ....>

In my case, I've used a session variable, but you could use a cookie to have more control over how long the "no mobile" flag persists.

Anyway, I hope this helps out. One thing I'm curious about - and I think it will take some time to really flesh out - is to see what "real" users think about this. If a typical user is pushed to a mobile site, will they get confused seeing a link out? Will they get confused in general if the site doesn't match what they see on the desktop (even if it's much better for their device).

Raymond Camden's Picture

About Raymond Camden

Raymond is a developer advocate for HERE Technologies. He focuses on JavaScript, serverless and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA

Archived Comments

Comment 1 by SuperAlly posted on 3/28/2011 at 9:28 PM

I was literally writing code to do this when I got the email notification about a new entry on your blog :)
Good thing I always stop what I'm doing to see what you have to say, huh?

Cheers Ray.

Comment 2 by Raymond Camden posted on 3/28/2011 at 9:35 PM

I always ask, before I post, "What does SuperAlly need?"


Comment 3 by Ed posted on 3/28/2011 at 9:39 PM

It is a good possibility that this year I am going to have to do some work to allow mobile access to one or more of our portal apps. I have not done a lot of research into it yet, but I have seen some mention of being able to specify CSS file(s) specifically for mobile (rel="mobile" if I remember correctly). Assuming that page content will be the same whether on mobile or desktop/laptop computer, and the content just needs to be formatted to fit better on a mobile screen, wouldn't this be a better way to go? Disclaimer... I do not have a mobile device yet so no practical experience on them.

Comment 4 by Raymond Camden posted on 3/28/2011 at 9:43 PM

As always - take this with a grain of salt. My opinion is that CSS can only take you so far in terms of supporting both desktop/mobile with the same content. I'm not sure if that type of solution would work well. To be clear, I don't mean CSS can't provide a good mobile experience - it does with jQuery Mobile for example, I'd just worry about trying to support both types of clients from the same base HTML.

That's my rough feeling. It's back up by little to no experience and I'm VERY willing to be corrected sharply on this.

Comment 5 by Fernando Lopez posted on 3/28/2011 at 10:12 PM

I'm currently working on mobilizing a small directory app and I made the mistake you mentioned. I detect the mobile device and then redirect to a Mobile view. nowhere in the page I provided a way to see the app as a regular web page.

Thanks for the post, saved me from sending this code to prod without the proper way out.

Comment 6 by Tim Garver posted on 3/28/2011 at 10:13 PM

Good article, i just did one of these about a month ago. Then on the mobile side i use the viewport meta tag
[code] <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; minimum-scale=1.0; user-scalable=0;" /> [/code]

Comment 7 by Gary Funk posted on 3/29/2011 at 12:26 AM

Ray, during the past few months, I saw a demo, by an Adobe person, that showed the layout change, when the width of the page was changed. This was done in CSS and was written to demo what the screen would look like on different size devices. What I can't rememer is who did the demo and if it was at a UG or online. I may have seen this online from a MAX session.

Comment 8 by Raymond Camden posted on 3/29/2011 at 12:27 AM

Thats.... shoot... CSS.... ok I'm not remember the term. Time to google.

Comment 9 by Raymond Camden posted on 3/29/2011 at 12:28 AM

Bam, "Media Queries"

Here is just one example: http://www.bushidodesigns.n...

Comment 10 by Raymond Camden posted on 3/29/2011 at 12:29 AM

So that would be a good way to say, "use this form factor for this size", but again, my concern is being able to make it work fine with one set of HTML. I don't think you can always take existing content and rework it to be ok on mobile.

Does that distinction/concern make sense? I'm not saying it is a valid concern. I'm not saying we must always build some new site for mobile. I'm just saying... um - maybe most of the time?

I'm new here too - so be gentle. ;)

Comment 11 by SuperAlly posted on 3/29/2011 at 12:35 AM

I remembered seeing it a little while back. If I remember right, the HTML5 video talks about specific CSS for phone/tablet/desktop.
It's specifically about Dreamweaver and how you can preview all 3 at the same time, but the concept I'm sure works fine without Dreamweaver.

Hope it helps!!

Comment 12 by SuperAlly posted on 3/29/2011 at 12:38 AM

Sorry, should have said "remembered seeing this", I in no way claim that this is IT :)

Comment 13 by Robert Henson posted on 3/29/2011 at 5:46 PM

Fantastic. Just did a Google search on "mobile redirect coldfusion" and find you've done a blog post on it in the last 24 hours. I should really just check your website first before resorting to Google - so much useful stuff on here.


Comment 14 by Raymond Camden posted on 3/29/2011 at 5:48 PM

Much appreciated Rob. This is what I live for. ;)

Comment 15 by TNT posted on 3/29/2011 at 11:23 PM

With respect, your own mobile functionality presents problems. Navigate to your blog from a search engine link for example when browsing on an Android... stuck! No backing out. My point is that as the mobile space evolves, everyones techniques will improve, both yours and Gawker's included.

Comment 16 by Raymond Camden posted on 3/29/2011 at 11:27 PM

I fully acknowledge my own mobile version needs work. :) Although every entry on the mobile site here should have a link at the bottom. You don't see that?

Ah just tested and confirmed. Although hitting the Back button in the UI on top takes you to the mobile home page with the link.

Yep - looks like it's by design - just the home page has the link. Well, I still consider that "a way out", but yeah, it should be -everywhere- in the UI.

BlogCFC is moving to jQM for the mobile version. I'll ensure it's everywhere.

Comment 17 by Jaana Gilbert posted on 3/30/2011 at 11:20 PM

Thanks for validating my approach :)

Last year I built a mobile version of a portal site that is used by 600+ different domains. I'm using a cookie approach because we're not using sessions on the site (will switch to sticky sessions on the load balanced servers later this year).

I've kept an eye on the stats on how many visitor actually clicks on the *main site* link and nearly 50% of visitors do that.

Comment 18 by Raymond Camden posted on 3/30/2011 at 11:21 PM

That's a fascinating stat Jaana. Thanks for sharing that.

Comment 19 by Kevin Marino posted on 3/30/2011 at 11:42 PM

Jaana and Raymond,

Wonder if that stat holds up across different business needs and markets?

Comment 20 by Jaana Gilbert posted on 3/30/2011 at 11:50 PM

Good question Kevin :)

I was really surprised that the % wasn't bigger.
Business sector is tennis and people who belong to tennis clubs, country clubs etc usually have available funds and tend to follow the trends in both clothing and gadgets.

Comment 21 by Kevin Marino posted on 3/30/2011 at 11:59 PM


With that said. I wonder how this would play out for a pure B2B setup. I am working on a small project for a B2B that focuses on retail store fittings. Right now doing the main site, but talk of mobile in future. So unlike a B2C where browsing may be more the norm, this is targeted searching and is often buttressed by conversations with the supplier (at least initially) so I would expect in my situation to see that percentage steadily decline on repeated trips, assuming mobile platform designed correctly.

So will definitely have to keep this in mind.

Comment 22 by Jaana Gilbert posted on 3/31/2011 at 12:09 AM

I agree, if you can provide the same functionality via the mobile site as the B2B site, that should make the % very low.

In our case the mobile version is mainly used for providing only a few applications from the whole site; hours of operation, maps, driving directions, event calendar, sending a txt message, other contact info and available demo rackets.

In the next stage we'll have tennis court scheduler and mobile payments integrated. That should make the % decline as well because those are some of the most used parts of the site.

Comment 23 by Raymond Camden posted on 3/31/2011 at 12:15 AM

I wonder how many people though will _always_ assume a mobile version < desktop version? Like even if you built everything, and it worked awesome, how many people are just going to assume its a pale shadow of the real thing and take the way out?

I _hate_ to question user's actions, but perhaps this would be a use case for a "Are you sure" type prompt when clicking. (I cannot believe I said that.)

Comment 24 by Jaana Gilbert posted on 3/31/2011 at 12:17 AM

I'm one to admit that I always assume the mobile version to have limited functionality compared to the main site :)

Comment 25 by Matthew Reinbold posted on 3/31/2011 at 12:26 AM

A better solution would be not to detect and support particular devices but optimize the user experience to the user's request (screen size, dpi, orientation, etc).

For a little under a year "Responsive Web Design" has become a hot topic among designers.

Comment 26 by Raymond Camden posted on 3/31/2011 at 12:28 AM

There is only so much screen size can tell you. It does not tell you, for example, that touch events would be supported, or that hover automatically would not.

Comment 27 by Matthew Reinbold posted on 3/31/2011 at 1:04 AM

Hover as a means of conveying additional information is a crutch for bad design and totally impractical for devices that feature direct manipulations (how do you hover a tooltip when using your thumb?).

Responsive web design isn't about doing decision trees and programming to specific screen sizes; that wouldn't be much better than device sniffing. Instead, its about creating a single fluid experience supporting any screen consumption.

Comment 28 by Raymond Camden posted on 3/31/2011 at 1:19 AM

I'm not arguing against the desired result - I'm arguing that it can be achieved by just checking simple things like current screen size.

Then again - maybe I'm not getting the whole picture. Reading the article now.

Comment 29 by Raymond Camden posted on 3/31/2011 at 1:27 AM

Very interesting article. And I grok the intent. Just wondering how well it would work with an existing site. I think a 'second version approach' may be more practical in that case.

I've got to say- every time I see media queries mentioned the focus is on "do this at size x", and it was nice to see an article talk about the _other_ things they can do - like check resolution and orientation.

Thanks Matthew.

Comment 30 by Matthew Reinbold posted on 3/31/2011 at 7:43 PM

For anyone else interested in the technique there's a great site to help quickly grok what happens on different devices when using that technique:

Comment 31 by Paco posted on 6/23/2011 at 1:56 AM

Hi Raymond what if I wanted to check if a mobile supports JQuery Mobile??

I know how to do this using JQuery:



How can I do this using Coldfusion?

Comment 32 by Raymond Camden posted on 6/23/2011 at 1:58 AM

You can't. It's a JS function. You could use JS to do a XHR request to CF and store a session variable.

Comment 33 by Paco posted on 6/23/2011 at 2:11 AM

Yes been searching on Google but so far no luck even with PHP. Thanks for your help.

Comment 34 by Raymond Camden posted on 6/23/2011 at 2:28 AM

Well - no surprise. It's client side code. :)

Comment 35 by Peter Kleid posted on 7/2/2011 at 7:47 PM

Ray, until I saw that YOU recommended, I wasn't sure if I should put much faith in it. My moto: "when in Rome or writing CF apps, do as Camden does."

Comment 36 by Raymond Camden posted on 7/2/2011 at 7:48 PM

Heh, I can't take credit for that find. I believe it was Dave Ferguson who added it to BlogCFC first.

Comment 37 by Yvonne posted on 9/23/2011 at 7:07 PM

Thanks for this - I have made a mobile version of my site and wanted to do an automatic redirect, so this is exactly what I was looking for.

Just one tiny thing (from a usability and accessibility point of view): the label of the link to exit the mobile version should be "exit mobile version" and not "click here".

Comment 38 by Raymond Camden posted on 9/23/2011 at 7:11 PM

"click here" - I was channeling my 1998 Web self.

Comment 39 by Tom Jenkins posted on 2/27/2012 at 5:45 PM

Hi Ray

I'm using the reg ex on the USER_AGENT in exactly the same format as above. Quick question though; what does the second half actually check for? As I have been experiencing massive problems with XmlParse on the same site as that reg ex ... as for some reason it gets caught in the <cfif> block. As soon as I remove the second half of the <cfif> it works fine?

Most odd :(

Look forward to you reply

Kind regards


Comment 40 by Raymond Camden posted on 2/27/2012 at 8:25 PM

Eh? I have no idea what you are talking about. xmlparse? Are you parsing the result of hitting one of the pages on your site? Are you using the feature where xmlParse can open a URL? If so- I assume you are hitting a CFM that spits out XML. Your "mobile friendly" checker should NOT check for requests to pages like that.

Comment 41 by Tom Jenkins posted on 2/27/2012 at 9:02 PM

Hi Ray

Ok, my bad for not explaining fully, sorry for that. I will try again and hopefully explain myself a little better.

So, I have your reFindNoCase() mobile check string in my application.cfc, within the onRequestStart function. Within this <cfif> check I have a <cflocation> to the mobile site. Easy so far and works perfectly.

Now, elsewhere in my application I have a dynamically generated XML sheet, xml.cfm, that returns a valid XML. You can check this here:

However, when I use XMLParse on this working URL, for some reason it gets caught in the initial USER_AGENT "mobile check" within the application.cfc and breaks. This, to a point, makes sense; because the XML that is returned is technically a .CFM page, the onRequestStart will be triggered. What is stumping me is why the USER_AGENT of the XmlParse() function is getting caught in the <cfif>? If I remove the second part of your reFindNoCase() (after the OR) then the returned value of the XmlParse() works in the exact way it should i.e. skipping the mobile site and returning the XML.

Hopefully that makes a little more sense, sorry for the initial post I was getting a little confused myself and forgot to give enough details.

Kind regards


Comment 42 by Raymond Camden posted on 2/27/2012 at 9:09 PM

Ah yes. So - I'm guessing that the UA sent by ColdFusion (remember, it's CF making a network request to load your XML) is confusig the regex. That means it is a bug for the guys. You could work on fixing it, but I'd probably just avoid the issue and say, "if the request is for X, don't check the UA" :)

Comment 43 by Raymond Camden posted on 2/27/2012 at 9:11 PM

I just did a quick test. The UA ColdFusion is sending is: Java/1.6.0_29.

It's my JRE version, so the actual # may vary for you.