JavaScriptでUser-Agent Client Hints(UA-CH)を利用したユーザーのデバイスを判別する方法



Web制作では必要に応じて、WindowsやMac、iPhone、iPad、Androidなど、ユーザーが利用するデバイスを判別して処理を切り分けることもあります。
ユーザーが利用するWebブラウザやデバイスを判別するのには、JavaScriptでuserAgent(UA)を活用して取得した情報をもとに行なってきたかと思います。

ただ、これまで多く使われてきたuserAgentはセキュリティ上の問題があることから、Chromeの開発チームが2020年ごろから廃止する考えを示し、今後は廃止の方向に進むこととなっています。
今後のユーザーエージェントを調べる方法としては、情報をオブジェクトで返すUser-Agent Client Hints(UA-CH)を活用していくことになるでしょう。

しかし、User-Agent Client Hintsが有効なWebブラウザは徐々に増えてきているものの、主要ブラウザすべてが有効ではありません。
User-Agent Client HintsはJavaScript APIとして公開されており、userAgentDataオブジェクトでデータを参照することができますが、まだサポートされていないブラウザもあります。
以下のリンクよりWebブラウザのサポート状況が確認できます。

Can I use (userAgentData)
https://caniuse.com/?search=userAgentData



2024年3月現在は、ChromeやEdgeなどChromiumベースのブラウザではuserAgentDataオブジェクトは参照できますが、SafariやFirefoxなどはまだ活用できません。
Android端末はChromeやEdgeで有効となります。
iOSやiPadOSのブラウザはChromeやEdgeを含むすべて無効ですので、今後Safariがサポートされるようになるのかが気になるところです。

User-Agent Client HintsがサポートされていなければuserAgentで実装する必要がありますし、userAgentが廃止となれば情報が取得できなくなるので、どちらにも対応できるようにしておくことが望ましいでしょう。

ここでは、userAgent(UA)とUser-Agent Client Hints(UA-CH)の両方に対応した判別方法についてご紹介します。

これまでのuserAgentでの判別


まずは基本知識として、これまでのuserAgentを使った方法を確認しておきましょう。

navigator.userAgentでユーザーエージェントを取得します。
小文字に変換された文字列の値を返すtoLowerCase()メソッドを使っています。
includes()メソッドは文字列に含まれるとtrue、含まれない場合はfalseを返します。if文の条件分岐でmobileの文字列があればスマートフォンやタブレット端末の処理、なければPCの処理とします。
iPadのSafariについては、ipadを含めmobileの文字列が含まれないので、macintoshの文字列やタッチ可能なデバイスなのかを条件とします。

JavaScript

const ua = navigator.userAgent.toLowerCase();
if (ua.includes("mobile")) {
  // Mobile (iPhone、iPad「Chrome、Edge」、Android)
} else if (ua.indexOf("ipad") > -1 || (ua.indexOf("macintosh") > -1 && "ontouchend" in document)) {
  // Mobile (iPad「Safari」)
} else {
  // PC
}



細かくデバイスを確認していく際は、indexOf()メソッドを使って、文字列または配列に特定の値が含まれるか検索して判別していきます。対象の文字列がマッチしたインデックスを返し、含まれなかった場合は-1が返されます。

様々なデバイスやOSで判別する場合は、以下のようなプログラムになります。
端末によってiPhoneやiPad、Android、PCではmacintoshやwindowsといった文字列が含まれます。

JavaScript

const ua = navigator.userAgent.toLowerCase();
if (ua.includes("mobile")) {
  // Mobile
  if (ua.indexOf("iphone") > -1) {
    // iPhone
  } else if (ua.indexOf("ipad") > -1) {
    // iPad (Chrome、Edge)
  } else if (ua.indexOf("android") > -1) {
    // Android
  }
} else if (ua.indexOf("ipad") > -1 || (ua.indexOf("macintosh") > -1 && "ontouchend" in document)) {
  // iPad (Safari)
} else {
  // PC
  if (ua.indexOf("macintosh") > 0) {
    // macOS
  } else if (ua.indexOf("windows") > 0) {
    // Windows
  } else {
    // Other
  }
}



userAgentが廃止となった場合は、上記のプログラムで正確に情報が取得できなくなるので、今後、移行されると考えられるUser-Agent Client HintsのuserAgentDataオブジェクトのデータを活用した方法でも実装する必要があります。

userAgentDataの利用


userAgentDataオブジェクトのデータは「navigator.userAgentData」で取得します。
以下のサンプルで、どのような情報が取得できるか確認してみましょう。

JavaScript

const ua = navigator.userAgentData;
console.log(ua);
console.log('Mobile : ' + ua.mobile);
console.log('Platform : ' + ua.platform);



userAgentDataオブジェクトから取得したデータをWebブラウザのコンソールで確認しますと、brandsやmobile、platformなどの情報が参照できます。
コンソールにてuserAgentDataオブジェクトから、MobileやPlatformの情報が取得できることも確認できます。
mobileの情報はモバイル端末であればtrue、モバイル端末でなければfalseを返します。
また、brandsの配列オブジェクトを展開すると、Webブラウザの情報も確認できます。

userAgentDataオブジェクトのデータの参照



前述したとおり、これまでのuserAgentが廃止に向かうことも考えて、userAgentDataが利用できるブラウザはuserAgentDataで判別、userAgentDataが利用できないブラウザはこれまでのuserAgentで判別するようにプログラムを実装する必要があります。

userAgentとuserAgentDataを併用した判別


まずは正しく実装できているのか、確認用のプログラムで見ていきます。
まとめたプログラムは後述します。

ここでは実装の確認として、ユーザーエージェントの情報や利用しているデバイスがわかるように、出力用のHTMLを用意しておきます。

HTML(確認用)

<p id="ua_check"></p>



続いてはJavaScript。
userAgentDataの利用の可否を確認してプログラムを実装していきます。
HTMLでの確認も含めたプログラムになります。
PCではconsole.log()で、Webブラウザのコンソールで情報を確認できるようにしています。

JavaScript(確認用)

if (window.navigator.userAgentData) {
  const ua = navigator.userAgentData;
  const element = document.querySelector("#ua_check");
  if (ua.mobile) {
    element.innerHTML = "userAgentData - " + ua.platform;
    if (ua.platform === "Android") {
      element.insertAdjacentHTML("beforeend","<p>Android</p>");
    }
    // if (ua.platform === 'iOS') {
    //   element.insertAdjacentHTML("beforeend","<p>iOS</p>");
    // }
    // if (ua.platform === 'iPad') {
    //   element.insertAdjacentHTML("beforeend","<p>iPad</p>");
    // }
  } else {
    console.log(ua);
    console.log("Mobile : " + ua.mobile);
    console.log("Platform : " + ua.platform);
    element.innerHTML = "userAgentData - " + ua.platform;
    if (ua.platform === "macOS") {
      element.insertAdjacentHTML("beforeend","<p>macOS</p>");
    } else if (ua.platform === "Windows") {
      element.insertAdjacentHTML("beforeend","<p>Windows</p>");
    } else {
      // Other
    }
  }
} else {
  const ua = navigator.userAgent.toLowerCase();
  const element = document.querySelector("#ua_check");
  element.innerHTML = ua;
  if (ua.includes("mobile")) {
    if (ua.indexOf("iphone") > -1) {
      element.insertAdjacentHTML("beforeend","<p>userAgent - iPhone</p>");
    } else if (ua.indexOf("ipad") > -1) { // iPad (Chrome、Edge)
      element.insertAdjacentHTML("beforeend","<p>userAgent - iPad</p>");
    } else if (ua.indexOf("android") > -1) {
      element.insertAdjacentHTML("beforeend","<p>userAgent - Android</p>");
    }
  } else if (ua.indexOf("ipad") > -1 || (ua.indexOf("macintosh") > -1 && "ontouchend" in document)) {
    element.insertAdjacentHTML("beforeend","<p>userAgent - iPad</p>");
  } else {
    console.log(ua);
    console.log("userAgent - PC");
    if (ua.indexOf("macintosh") > 0) {
      element.insertAdjacentHTML("beforeend","<p>userAgent - macOS</p>");
    } else if (ua.indexOf("windows") > 0) {
      element.insertAdjacentHTML("beforeend","<p>userAgent - Windows</p>");
    } else {
      // Other
    }
  }
}


まずは、ユーザーがアクセスしたWebブラウザでuserAgentDataが利用できるかを確認する必要があります。
if文にて「window.navigator.userAgentData」を条件として、true(userAgentDataが利用可能)であればuserAgentDataを利用したプログラムを。falseであればelse文でこれまでのuserAgentでのプログラムで処理するように条件分岐させます。

userAgentDataの利用の可否で条件分岐ができれば、あとはこれまでにお話してきたように、変数にユーザーエージェント情報を格納して、userAgentDataであればモバイルかどうかの判別やOSや端末の情報の判別を、これまでのuserAgentであれば文字列を含むかどうかで判別をしていきます。
モバイル端末のOSごとの判別では、iPhoneやiPadはまだサポートされていませんので、想定としてコメントで入れております。

ここまでをまとめると、以下のプログラムでデバイスを判別していくことができます。

JavaScript

if (window.navigator.userAgentData) {
  const ua = navigator.userAgentData;
  if (ua.mobile) {
    // Mobile
  } else {
    // PC
  }
} else {
  const ua = navigator.userAgent.toLowerCase();
  if (ua.includes("mobile")) {
    // Mobile (iPhone、iPad「Chrome、Edge」、Android)
  } else if (ua.indexOf("ipad") > -1 || (ua.indexOf("macintosh") > -1 && "ontouchend" in document)) {
    // Mobile (iPad「Safari」)
  } else {
    // PC
  }
}



また、様々なデバイスやOSで判別が必要な場合は、以下のようなプログラムになります。

JavaScript

if (window.navigator.userAgentData) {
  const ua = navigator.userAgentData;
  if (ua.mobile) {
    // Mobile
    if (ua.platform === "Android") {
      // Android
    }
  } else {
    // PC
    if (ua.platform === "macOS") {
      // macOS
    } else if (ua.platform === "Windows") {
      // Windows
    } else {
      // Other
    }
  }
} else {
  const ua = navigator.userAgent.toLowerCase();
  if (ua.includes("mobile")) {
    // Mobile
    if (ua.indexOf("iphone") > -1) {
      // iPhone
    } else if (ua.indexOf("ipad") > -1) {
      // iPad (Chrome、Edge)
    } else if (ua.indexOf("android") > -1) {
      // Android
    }
  } else if (ua.indexOf("ipad") > -1 || (ua.indexOf("macintosh") > -1 && "ontouchend" in document)) {
    // iPad (Safari)
  } else {
    // PC
    if (ua.indexOf("macintosh") > 0) {
      // macOS
    } else if (ua.indexOf("windows") > 0) {
      // Windows
    } else {
      // Other
    }
  }
}



実際に利用する際は、必要になる判別のプログラムを参考にして実装してみてください。

余談


ここでは、デバイスや様々な端末の判別方法を見てきましたが、Webブラウザで判別していくこともあるでしょう。
userAgent(UA)やUser-Agent Client Hints(UA-CH)でユーザーが利用しているWebブラウザの判別については、以下の記事内でご紹介しています。


userAgentDataでは、配列オブジェクトからbrand情報を取得する流れとなります。
ぜひ参考にしてください。