Web サイトのスマートフォン最適化: UA 判別篇

iPhone 買いました。iPhone 4。はじめてのスマートフォンですよ。

で、この機会にこのサイトのスマートフォン最適化を図ろうと考えたわけです。今までなにもしてなかったので。しかし恥ずかしながらスマートフォン向けのサイトを作った経験がなかったので、どこから手をつけたものかわからない。そこで、とりあえず参考になりそうなネタを探そうと「wordpress iphone 最適化」あたりでググってみたところ (このサイトは WordPress で作ってます)、どうも WPtouch iPhone Theme というプラグインが人気らしい。このプラグインは有効にするだけで WordPress サイトをスマートフォン向けに最適化してくれる便利なもので、採用してるサイトもよく見かけます。

でもプラグインをそのまま導入したんじゃ面白くない。やっぱテーマは自分でいじりたいし。となると、とりあえず知りたいのは「スマートフォンからのアクセスをどのように判別しているのか」または「スマートフォン向けのコンテントやスタイルをどのように振り分けているのか」といったところで、そこらへんがわかればあとはいつものテーマ作りの手法でどうにかなるだろうと考えまして、とりあえずダウンロードしてソースコードを覗いてみたんです。あわよくば自前のテーマの参考にしようと。すると wptouch.php というファイルに以下のような箇所を見つけました:

<?php
  $useragents = array(
    'iPhone',         // Apple iPhone
    'iPod',           // Apple iPod touch
    'Android',        // 1.5+ Android
    'dream',          // Pre 1.5 Android
    'CUPCAKE',        // 1.5+ Android
    'blackberry9500', // Storm
    'blackberry9530', // Storm
    'blackberry9520', // Storm v2
    'blackberry9550', // Storm v2
    'blackberry9800', // Torch
    'webOS',          // Palm Pre Experimental
    'incognito',      // Other iPhone browser
    'webmate'         // Other iPhone browser
  );
?>

これはどこからどう見てもスマートフォン判別用の文字列 (の配列)。どうやらこれを HTTP ヘッダの User-Agent と突き合わせて、スマートフォンからのアクセスを判別しているらしい。そうとわかればあとは簡単で、自作テーマの functions.php にこんな関数を書いてみました:

<?php
  // Thanks to BraveNewCode's WPtouch iPhone Theme for the UA list.
  // (http://wordpress.org/extend/plugins/wptouch/)
  function is_mobile () {
    $useragents = array(
      'iPhone',         // Apple iPhone
      'iPod',           // Apple iPod touch
      'Android',        // 1.5+ Android
      'dream',          // Pre 1.5 Android
      'CUPCAKE',        // 1.5+ Android
      'blackberry9500', // Storm
      'blackberry9530', // Storm
      'blackberry9520', // Storm v2
      'blackberry9550', // Storm v2
      'blackberry9800', // Torch
      'webOS',          // Palm Pre Experimental
      'incognito',      // Other iPhone browser
      'webmate'         // Other iPhone browser
    );
    $pattern = '/'.implode('|', $useragents).'/i';
    return preg_match($pattern, $_SERVER['HTTP_USER_AGENT']);
  }
?>

この is_mobile() 関数でやっているのは、

  1. まず想定されるスマートフォンを判別するための文字列の配列を作り、
  2. それを正規表現パターンに変換して、
  3. HTTP ヘッダの User-Agent にマッチすれば true を返す、

といったところです。これで、is_mobile()条件分岐タグ としてテンプレートで使うことができます。たとえばスマートフォン専用の CSS を読み込ませる場合はこうです:

<?php if (is_mobile()) { ?>
<link rel="stylesheet" type="text/css" href="/css/mobile.css" />
<?php } ?>

「スマートフォン以外の場合にサイドバーを読み込む」ならこう:

<?php
  if (!is_mobile()) {
    get_sidebar();
  }
?>

なお同様の判別は JavaScript でも可能です。スマートフォン用 CSS の適用はこんな感じでできます:

// Thanks to BraveNewCode's WPtouch iPhone Theme for the UA list.
// (http://wordpress.org/extend/plugins/wptouch/)
function is_mobile () {
  var useragents = [
    'iPhone',         // Apple iPhone
    'iPod',           // Apple iPod touch
    'Android',        // 1.5+ Android
    'dream',          // Pre 1.5 Android
    'CUPCAKE',        // 1.5+ Android
    'blackberry9500', // Storm
    'blackberry9530', // Storm
    'blackberry9520', // Storm v2
    'blackberry9550', // Storm v2
    'blackberry9800', // Torch
    'webOS',          // Palm Pre Experimental
    'incognito',      // Other iPhone browser
    'webmate'         // Other iPhone browser
  ];
  var pattern = new RegExp(useragents.join('|'), 'i');
  return pattern.test(navigator.userAgent);
}
if (is_mobile()) {
  var link = document.createElement('link');
  link.rel = 'stylesheet';
  link.type = 'text/css';
  link.href = '/css/mobile.css';
  document.getElementsByTagName('head')[0].appendChild(link);
}

蛇足ながら、上記 if 文の link 要素を生成する部分は、jQuery なら以下のように書けますね:

$(function () {
  if (is_mobile()) {
    $('<link/>').attr({
      rel: 'stylesheet',
      type: 'text/css',
      href: '/css/mobile.css'
    }).appendTo('head');
  }
});

しかし、ここまで長々と書いといてなんですが、こういった UA 判別のアプローチって、実際のところどうなんでしょうね? 判別のために文字列のリストを用意するっていう部分が、どうもいまいちなんじゃないかって気がするんですよね。たとえば、今後出てくるであろう新しいスマートフォンに対応しようとすると、このリストを永遠にメンテナンスし続けなきゃなんないじゃないですか。実際、つい先日も WPtouch iPhone Theme のアップデートで新しい BlackBerry が 3 つも追加されてたし。

コンテントを出し分けたり別の URL へリダイレクトしたりしようとすると、やはり今回のような UA 検出が必要かもしれませんが、もしスマートフォンを判別する目的がスタイルの振り分けなら、やっぱ メディアクエリー を使うのが王道なのかなと思い始めてます。というわけで、この続きは「メディアクエリー篇」で…