Posts Tagged “PHP”

While a lot of people have written in with kudos on my PHP code for detecting mobile browsers, others have written in with questions on how to use it.

The code in question is a PHP function that returns a true or false value depending on whether the browser viewing the page has been identified as mobile or not. If it's identified as mobile, it returns a "true" status. If it's not, it returns a "false" status. So, if you use the code exactly as presented in the original article, you're going to put it somewhere near the end of the PHP code block in your page. Somewhere near the beginning of the page, you'll want a PHP code block like this...

if(checkmobile()){
     //code to execute if a mobile browser is detected
}

Now what code you'll execute is up to you. It might be that you simply select a mobile style sheet instead of your regular one. To do that, you'd do something like...

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
<TITLE>My Page Title</TITLE>
<?php
if(checkmobile()){
echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"/mobilestyle.css\">";
} else {
echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"/regularstyle.css\">";
}
?>

<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
...

Now remember, this assumes you've put the mobile browser detection code somewhere in the page between <?PHP ... ?> tags.

Some of you, on the other hand, may want to send mobile browsers over to an entirely different version of your site. The simplest way is to do...

<?php
if(checkmobile()) header("Location:http://www.whatever-url-you-want.com");
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<HTML>
...

Note that this is at the VERY VERY top of the page, before anything else. That's because, you need to do the redirect before any other information has been sent to the user's browser.

You can put the code for catching mobile browsers right in that PHP block, after the "if(checkmobile())" line and before the "?>" line. I haven't included it in the examples just to keep this page from being humongously long.

Depending on how your server is set up, any file that contains PHP may require that the file name end in .php instead of .htm or .html. So make sure you know what your server requires.

Hope this helps some of you who aren't familiar with programming. If you need further help, I suggest buying a book on PHP if you're in a DIY mood or hiring someone who knows it if you're not.

Share

Comments 12 Comments »

UPDATE 11/30/09: After two years, I have decided to stop maintaining and updating this code. I'm not currently using it and it was getting to be in need of an overhaul with all the devices that keep changing the landscape. I'd suggest the open source DetectMobileBrowser.com.

UPDATE: The code has just been tested against the WURFL database of over 6,750 different mobile browser User Agent IDs, and proved 94.34% effective at catching the User Agent IDs in their database, yet providing NO false positives on the 63 most popular browser/OS combos on the desktop. And remember, that's just one of three checks this function performs.

UPDATE #2: Need help using the code in this article? I've written a second article with code to help you handle your mobile users when this piece of code detects them.

UPDATE December 2008: Looks like IE8 has a trick of adding all sorts of software to the user agent string. Someone sent me one that listed the version of Zune software they were using and "Creative AutoUpdate" which was triggering the substring search for "pda", meaning a whole bunch of people were getting false positives on IE8. I've added an exception to catch the "Creative AutoUpdate" string.

UPDATE June 2009: As reported in the comments and occasionally by e-mail, the Office Live Connector in IE 8 was causing false positives with the check to see if you're running an NEC phone. People were adding their own lines to the code to check for this, but I figured I'd group the checks for known false positives the same way the grouping for known positives is done. That way you can just add an item to the array and not keep adding lines and lines of code.

UPDATE July 2009: Small code clean-up and addition of another false positive exclusion to the "badmatches" array. Please keep those notes and comments coming.

UPDATE August 2009: WebOS added to the uamatches array to catch Palm Pre. Please keep those notes and comments coming.

When it comes to detecting PDA and cell phone web browsers visiting your web site, you'd think there would be a standard "hi, I'm a mobile browser" handshake that a mobile browser would send to your server. And if you thought that (like I did), you'd be wrong.

Let's skip the story and get to the PHP code.

While working on a new site, I wanted to make a few pages "mobile aware" so they reformatted themselves for mobile phones. And while I could do some of that with CSS, detecting mobile browsers with PHP so I can customize the HTML that's delivered is even better.

But I found that there's no standardized way this works. A lot of sites had a piece of the puzzle, but most were only partially effective. I even ran across a British doofus who wanted $20 for a commercial license to code that couldn't catch a Treo.

So, what I did, was... hunt the triggers that identify most PDA and phone browsers without scoring false positives on major browsers. I culled through huge lists of User Agent IDs to find unique bits I could test for, plus found a couple of other tests at various sites, and pulled them all together. Oddly enough, despite all the pages I went to that discussed how to do this, none of them did all of these tests.

I've tested the following code against 63 desktop browser versions across Linux, Mac, and multiple versions of Windows, using a free trial at BrowserCam. From Konqueror to AOL to Opera to Firefox to IE, no false positives. That pretty much guarantees no false positives for 99.9% of your visitors using desktop browsers.

For catching mobile browsers, it's caught every mobile browser I've thrown at it... 3 real ones (Palm Blazer, Opera Mini, Google's web to plain old text converter) and 2 simulated ones (Sony K750, Nokia N70). It also scored 94.34% against a database of 6,788 mobile browser User Agent ID codes via the WURFL database. And since its WURFL score was only based on one of three different tests the script does, and the ones it wasn't catching were from more obscure browsers, I'd estimate this little chunk of code should be able to identify 97% of mobile visitors, if not more.

function checkmobile(){

if(isset($_SERVER["HTTP_X_WAP_PROFILE"])) return true;

if(preg_match("/wap\.|\.wap/i",$_SERVER["HTTP_ACCEPT"])) return true;

if(isset($_SERVER["HTTP_USER_AGENT"])){

// Quick Array to kill out matches in the user agent
// that might cause false positives

$badmatches = array("OfficeLiveConnector","MSIE\ 8\.0","OptimizedIE8","MSN\ Optimized","Creative\ AutoUpdate","Swapper");

foreach($badmatches as $badstring){
if(preg_match("/".$badstring."/i",$_SERVER["HTTP_USER_AGENT"])) return false;
}

// Now we'll go for positive matches

$uamatches = array("midp", "j2me", "avantg", "docomo", "novarra", "palmos", "palmsource", "240x320", "opwv", "chtml", "pda", "windows\ ce", "mmp\/", "blackberry", "mib\/", "symbian", "wireless", "nokia", "hand", "mobi", "phone", "cdm", "up\.b", "audio", "SIE\-", "SEC\-", "samsung", "HTC", "mot\-", "mitsu", "sagem", "sony", "alcatel", "lg", "erics", "vx", "NEC", "philips", "mmm", "xx", "panasonic", "sharp", "wap", "sch", "rover", "pocket", "benq", "java", "pt", "pg", "vox", "amoi", "bird", "compal", "kg", "voda", "sany", "kdd", "dbt", "sendo", "sgh", "gradi", "jb", "\d\d\di", "moto","webos");

foreach($uamatches as $uastring){
if(preg_match("/".$uastring."/i",$_SERVER["HTTP_USER_AGENT"])) return true;
}

}
return false;
}

It's pretty simple. Line 1 of the function checks to see if the browser is sending a WAP profile. No desktop browser would want or need to, and based on my testing, none do. OTOH, Blazer on my Treo 700p sends one, but Opera Mini doesn't, so it's far from the only test needed.

The second line looks for WAP formats in the HTTP Accept string, which tells the server the types of content the browser can accept.

The rest of the code checks the User Agent ID for bits of text that you'll find in mobile browser IDs but not in the IDs of major desktop browsers. Each of these text snippets are meaningful indicators pulled from real PDA and mobile phone User Agent IDs.

If you'd like to test this code, I've got a test page at http://www.brainhandles.com/testmobile.php. Not only will it tell you if your browser registers as mobile, but what tests out of the three (WAP profile, WAP accepted, User Agent substrings) your mobile browser scored a hit on. If the script scores a false positive (desktop browser shows up as mobile) or doesn't identify your mobile browser as mobile, instructions for reporting it are provided.

SECOND UPDATE: It's been brought to my attention that some site owners like the iPhone's method of rendering regular (i.e. not optimized for mobile) pages and want to exclude the iPhone from the list. Luckily, the Safari on the iPhone is nice enough to identify itself in its User Agent ID. To exclude the iPhone, add in the following line of code near the top as the first check the script performs.

if(preg_match("/iphone/i",$_SERVER["HTTP_USER_AGENT"])) return false;

That will create an exclusion for the iPhone and treat it as if it were a desktop browser.

You can now add "iphone" to the badmatches array and have it treated as a false positive if you want to exclude iPhone.

Thanks, and I hope this works for you.

Share

Comments 54 Comments »

When I've read PHP tutorials and you've got a list of values you want to check a variable against, the values are usually in an array, and a loop is used to check the variable against each value.

For example, we'll look at this block of code, assuming that $userin is user input...


$people = array("fred","wilma","barney","betty","pebbles","bam bam");
$match=false;
for($i=0;$i<count($people);$i++){
     if($people[$i]==$userin) $match = true;
}

if ($match) {whatever code you'd execute if there was a match}

That's all well and good, but it's more code than you need. Let's look at an optimized version...


$people = array("fred"=>1,"wilma"=>1,"barney"=>1,"betty"=>1,"pebbles"=>1,"bam bam"=>1);
if (isset($people[$userin])) {whatever code you'd execute if there was a match}

Instead of setting the names as values in an array, you've set them as keys in an associative array. Then, instead of iterating through all the values of the array, checking each value against the user input, all you need to do is check whether the user input value exists as a key in the array using the isset() function. This basically cuts out that entire loop in the middle and brings you from six lines of code to two.

If you ever need to iterate through the array, you use a for each loop.

Simple as that.

Share

Comments Comments Off

What is "link cloaking," you ask? It's when you use an alternative URL to represent the actual URL you're linking to. For example, if you were linking to...

http://www.fakeurl.jib/blog/post.php?postname=why_the_heck_is_this_url_so_long

...you might instead cloak it and link to:

http://www.mysite.jib/out.php?link=89.

The arguments for link cloaking include:

  • Easier link/click tracking

  • Making links short enough to fit in an e-mail
  • Making links harder for spyware to hijack
  • Ease of link management (use the cloaked link in 10 places, then change them all with one database edit).

For me, the only time I use link cloaking is in text e-mails. In those cases it can be very useful. If you have a really long link, a lot of mail clients will break it into two or even three lines, but only link up the first line. When that happens, people get a "page not found" error and either have to piece the link back together to get to your page or just give up.

So even if it's only for that one purpose, it can have value. And when you see how easy it is, you'll be shocked.

A simple link cloaking script consists of two parts: "the array" and "the forwarder".

The Array

If you're not familiar with the programming concept of arrays, they're basically a way to keep a list in a single object. Here's how you build your array.

$links = array(
       "http://www.fundraw.com/",
       "http://www.bulmash.com/",
       "http://www.brainhandles.com/",
       "http://www.funbabyclothes.com/",
       "http://www.insultfinder.com/"
);

Each of those URLs will have a number and the numbering starts at zero. So www.brainhandles.com would be #2.

The Forwarder

Let's say your cloaking script will be called "out.php" and will be in your top level web directory. Then a link to "fundraw.com" would look like this...

<a href="/out.php?L=0">

Your cloaker script would then begin with the array and have these lines of code following it:

//This block ensures a link name was submitted
if(isset($_GET["L"])){
$linkval = intval($_GET["L"]); // use intval() to ensure the value is an integer
} else {
error();
}

if(isset($links[$linkval])){ //this if condition uses isset() to make sure the value is valid
$linkout = $links[$linkval];
} else {
error();
}

//This line sends the visitor to the link
header("Location: $linkout");

//This block handles the errors
function error(){
     echo "We're sorry, but that was not a valid link";
     exit;
}

And That's It

Put the array and forwarder in a PHP script and you've got an easy, simple, link cloaker. The only real downside is that when you want to add a new link, you have to edit the array by hand and upload the revised script to your server. Now, we could make it easier to add links by hooking this up with a couple of forms and some database code, and it's pretty easy to do too, but that's a subject for another post.

Share

Comments 1 Comment »

Get an angel for your site An Angel Watches Over This Site