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="http://detectmobilebrowser.com/mobile"></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="http://www.foo.com/?nomobile=1" 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).
Archived Comments
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.
I always ask, before I post, "What does SuperAlly need?"
;)
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.
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.
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.
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]
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.
Thats.... shoot... CSS.... ok I'm not remember the term. Time to google.
Bam, "Media Queries"
Here is just one example: http://www.bushidodesigns.n...
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. ;)
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.
http://www.adobe.com/produc...
Hope it helps!!
Sorry, should have said "remembered seeing this", I in no way claim that this is IT :)
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.
Thanks!
Rob
Much appreciated Rob. This is what I live for. ;)
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.
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.
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.
That's a fascinating stat Jaana. Thanks for sharing that.
Jaana and Raymond,
Wonder if that stat holds up across different business needs and markets?
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.
Jaana,
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.
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.
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.)
I'm one to admit that I always assume the mobile version to have limited functionality compared to the main site :)
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.
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.
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.
http://www.alistapart.com/a...
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.
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.
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:
http://mediaqueri.es/popular/
Hi Raymond what if I wanted to check if a mobile supports JQuery Mobile??
I know how to do this using JQuery:
if($.mobile.gradeA()){
}
How can I do this using Coldfusion?
You can't. It's a JS function. You could use JS to do a XHR request to CF and store a session variable.
Yes been searching on Google but so far no luck even with PHP. Thanks for your help.
Well - no surprise. It's client side code. :)
Ray, until I saw that YOU recommended detectmobilebrowser.com, 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."
Heh, I can't take credit for that find. I believe it was Dave Ferguson who added it to BlogCFC first.
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".
"click here" - I was channeling my 1998 Web self.
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
Tom
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.
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:
http://www.lakeside.uk.com/...
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
Tom
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 detectmobilebrowser.com 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" :)
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.