What are the limitations of ua-parser for SEO purposes?
UA解析ツール: SEOにおけるua-parserの限界 - 究極の権威あるガイド
執筆者: [あなたの名前/ペンネーム], テックジャーナリスト
公開日: 2023年10月27日
エグゼクティブサマリー
ウェブサイトのパフォーマンスと検索エンジンランキングの最適化において、ユーザーエージェント(UA)文字列の解析は不可欠な要素です。ua-parserは、この分野で広く利用されているライブラリですが、SEO(検索エンジン最適化)の観点から見ると、その能力にはいくつかの重要な限界が存在します。本ガイドは、テックジャーナリストの視点から、ua-parserの技術的な詳細、SEOへの影響、実用的なシナリオ、グローバルな業界標準、多言語対応、そして将来の展望までを網羅し、UA解析ツールがSEO戦略にどのように影響するかを包括的に解説します。ua-parserはブラウザ、OS、デバイスの識別においては強力ですが、SEOの複雑な要件、特にユーザーインテントの理解や検索エンジンのクロール動作のシミュレーションといった高度な側面では、その限界が明らかになります。
UA解析ツールの役割とua-parserの概要
ウェブサイト運営者やSEO担当者にとって、訪問者の使用するブラウザ、オペレーティングシステム(OS)、デバイスの種類を正確に把握することは、コンテンツ配信、UI/UXデザイン、そしてパフォーマンス最適化の基盤となります。ユーザーエージェント(UA)文字列は、ウェブブラウザやその他のクライアントアプリケーションがサーバーに送信するHTTPヘッダーの一部であり、この情報を含んでいます。
ua-parserは、このようなUA文字列を解析し、ブラウザ名、バージョン、OSファミリー、バージョン、デバイスメーカー、モデルといった構造化されたデータに分解するために設計された、オープンソースのライブラリです。Python、Java、JavaScript、PHPなど、多くのプログラミング言語で利用可能であり、その普及率の高さから、多くのウェブアプリケーションや分析ツールで採用されています。
しかし、SEOという文脈においてua-parserの能力を評価する際には、その本来の目的とSEOの要求との間に存在するギャップを理解することが重要です。ua-parserは「UA文字列を正確に解析する」ことに特化しており、「検索エンジンのランキング要因を理解し、最適化する」というSEOの目的とは直接的に結びついていません。
ua-parserのSEOにおける限界:ディープテクニカル分析
1. 検索エンジンのクロール動作の不完全なシミュレーション
SEOの最も基本的な側面の一つは、検索エンジン(Googlebot, Bingbotなど)がどのようにウェブサイトをクロールし、インデックスするかを理解することです。検索エンジンボットは、一般的なブラウザとは異なるUA文字列を使用します。ua-parserは、これらのボットのUA文字列を解析することは可能ですが、それだけではSEO戦略に直結する洞察を得るには不十分です。
- ボットの多様性: 検索エンジンは、デスクトップ、モバイル、画像検索、ニュース検索など、様々な目的のために複数のボットを運用しています。
ua-parserはこれらのボットを識別できますが、各ボットがウェブサイトのどの部分に、どのような優先順位でアクセスするか、あるいはどのコンテンツを重視するかといった、より詳細なクロール戦略を直接的に示唆するわけではありません。 - UAスプーフィングの考慮不足:
ua-parserは、一般的にUA文字列に偽装(スプーフィング)がないことを前提としています。しかし、一部のウェブサイトやボットは、意図的に異なるUA文字列を送信することがあります。ua-parserは、このような偽装されたUA文字列を「本物」として解析してしまう可能性があり、誤った分析結果につながるリスクがあります。SEO担当者は、ボットのUAを正確に識別し、それに基づいてクロール予算やレンダリング戦略を調整する必要がありますが、ua-parser単体ではその識別精度に限界があります。 - robots.txtとの連携:
ua-parserは、robots.txtファイルの内容を解釈したり、特定のボットがrobots.txtによってアクセスを拒否されているかどうかを判断したりする機能を持っていません。SEOにおいてrobots.txtは非常に重要であり、ボットのクロールを制御する上で不可欠な要素です。
2. ユーザーインテントの推測の限界
現代のSEOは、単にキーワードを最適化するだけでなく、ユーザーが検索クエリを通じて達成しようとしている「意図(インテント)」を理解することに重点を置いています。UA文字列は、ユーザーのデバイスやブラウザの種類を示唆しますが、その「意図」を直接的に把握することはできません。
- デバイスと意図の相関: 例えば、モバイルユーザーは「場所に基づいた情報検索」や「迅速な情報取得」を意図している可能性が高いと推測できます。デスクトップユーザーは「詳細な情報収集」や「購入プロセス」を意図しているかもしれません。
ua-parserはデバイスタイプを特定できますが、その背後にあるユーザーの具体的な行動や目的を推測するための十分な情報を提供しません。 - ブラウザ機能とユーザー行動: 特定のブラウザ(例:JavaScript機能が豊富な最新ブラウザ)を使用しているユーザーが、よりインタラクティブなコンテンツや高度な機能を求めている可能性はありますが、これもあくまで推測の域を出ません。
ua-parserはブラウザのバージョンを特定できても、そのユーザーがどのようなコンテンツを求めているかを直接的に示すものではありません。 - コンテキストの欠如: UA文字列は、ユーザーがウェブサイトを訪れた「コンテキスト」(例:ソーシャルメディアからの流入、広告からの流入、直接訪問など)を全く含んでいません。SEO戦略は、これらのコンテキストを考慮して、ユーザー体験を最適化する必要があります。
ua-parserは、この重要なコンテキスト情報を欠落しています。
3. パフォーマンス最適化における限定的な示唆
ウェブサイトのパフォーマンスは、SEOの重要なランキング要因です。特にモバイルデバイスでの高速な読み込みは、ユーザー体験と検索順位の両方に影響します。
- デバイスの性能限界:
ua-parserはデバイスのモデルを特定できますが、そのデバイスの実際の処理能力、ネットワーク帯域幅、画面解像度などの詳細なパフォーマンス特性を直接的に把握することはできません。例えば、古い低スペックなモバイルデバイスでは、リッチなJavaScriptや高解像度の画像は読み込みに時間がかかり、ユーザー体験を損なう可能性があります。ua-parserはデバイスの種類を特定できても、そのデバイス固有のパフォーマンスボトルネックを特定するには、追加の計測が必要です。 - ブラウザレンダリングエンジンの違い: Chrome (Blink), Firefox (Gecko), Safari (WebKit) など、ブラウザごとにレンダリングエンジンが異なります。これらのエンジンの違いは、CSSの解釈やJavaScriptの実行速度に影響を与える可能性があります。
ua-parserはブラウザ名とバージョンを特定できますが、レンダリングエンジンの詳細な違いや、それによるパフォーマンスへの影響を直接的に評価する機能は持ち合わせていません。
4. ターゲットオーディエンスの深掘り不足
SEO戦略は、ターゲットオーディエンスを深く理解することから始まります。ua-parserは、技術的な属性(ブラウザ、OS、デバイス)を提供しますが、ユーザーのデモグラフィック情報、興味関心、購買行動などの「人間的な」側面についての洞察は一切提供しません。
- 地理的情報の欠如:
ua-parserは、ユーザーがどの地域からアクセスしているかを知ることはできません。SEOでは、地域ターゲティングやローカライズが重要な戦略となることが多いため、この情報の欠如は大きな制約となります。 - 言語設定の限界: UA文字列には、ユーザーの言語設定が含まれている場合もありますが、
ua-parserがそれを常に正確かつ包括的に抽出できるとは限りません。多言語サイトのSEOでは、ユーザーの言語設定を理解し、適切な言語バージョンのコンテンツを提供することが不可欠です。
5. ua-parserのデータソースと更新頻度
ua-parserは、その解析能力を維持するために、定期的に更新されるUAデータベースに依存しています。
- データベースの遅延: 新しいブラウザバージョン、デバイス、OSがリリースされると、それらを正確に認識するためには
ua-parserのデータベースも更新される必要があります。しかし、この更新プロセスにはタイムラグが生じることがあります。最新のデバイスやブラウザを正確に識別できない場合、分析結果の信頼性が低下する可能性があります。 - 未知のUAへの対応: 常に新しいデバイスやカスタムUAが登場するため、
ua-parserのデータベースでも全てを網羅することは不可能です。未知のUA文字列に対しては、ua-parserは不完全な解析結果を返すか、あるいは汎用的なカテゴリに分類するしかありません。SEO担当者は、これらの未知のUAがどのようなユーザー層を代表しているのかを独自に調査する必要があります。
6. SEOツールエコシステムにおける位置づけ
ua-parserは、単体のライブラリとして非常に有用ですが、SEOの複雑なエコシステム全体で見ると、それはあくまで「部品」の一つです。
- 他のSEOツールとの統合: Google Analytics, Search Console, SEMrush, Ahrefsなどの主要なSEOツールは、UA解析機能を含んでいますが、それらはUA解析だけでなく、トラフィック分析、キーワードリサーチ、競合分析、リンクプロファイリングなど、より広範なSEO機能を提供しています。
ua-parserは、これらのツールのUA解析機能の基盤となっている可能性はありますが、それ自体が包括的なSEOソリューションではありません。 - リアルタイム性への課題:
ua-parserは、サーバーサイドでリクエストごとにUA文字列を解析するのに適していますが、リアルタイムのユーザー行動追跡やA/Bテストなどの動的なSEO最適化においては、より高速でリアルタイム性の高いJavaScriptベースの解析ツールや、より高度な分析プラットフォームが必要となる場合があります。
ua-parserの限界を克服するための5+ 実用的なシナリオ
ua-parserの限界を理解した上で、その強みを活かしつつ、SEOの目的を達成するためには、他のツールや手法と組み合わせて活用することが不可欠です。以下に、具体的なシナリオとそのアプローチを示します。
シナリオ1: モバイルファーストインデックス(MFI)への対応強化
Googleはモバイルファーストインデックスを推進しており、モバイル版のコンテンツをクロール・評価するだけでなく、モバイルユーザー体験がランキングに大きく影響します。
ua-parserの活用:ua-parserを使用して、サイトへのアクセス者のうち、モバイルデバイス(スマートフォン、タブレット)からの割合を特定します。- 限界と追加アクション:
ua-parserはデバイスの「種類」は特定できますが、そのデバイスの「性能」や「ネットワーク環境」までは把握できません。- 追加アクション:
- Google Search Consoleの「モバイルユーザビリティ」レポートを確認する。
- PageSpeed InsightsやLighthouseなどのツールで、モバイルデバイスでのパフォーマンスをテストする。
- Google Analyticsの「モバイル」セグメントで、モバイルユーザーの行動(滞在時間、離脱率、コンバージョン率)を詳細に分析する。
robots.txtがモバイルボット(例: Googlebot-Mobile)のアクセスを妨げていないか確認する。
- 追加アクション:
シナリオ2: クロスブラウザ互換性とパフォーマンスの最適化
異なるブラウザ間での表示崩れやJavaScriptエラーは、ユーザー体験を損ない、SEOに悪影響を与えます。
ua-parserの活用:ua-parserで、サイトにアクセスしたユーザーが使用しているブラウザ(Chrome, Firefox, Safari, Edgeなど)とそのバージョンを把握します。- 限界と追加アクション:
ua-parserはブラウザ名を特定できても、そのレンダリングエンジンの挙動やJavaScript実行速度の微妙な違い、あるいは特定のブラウザバージョンで発生するバグまでは特定できません。- 追加アクション:
- BrowserStack, Sauce Labsなどのクロスブラウザテストプラットフォームを活用し、主要なブラウザ・OSの組み合わせでサイトの表示と機能をテストする。
- ブラウザの開発者ツール(Consoleタブ)でJavaScriptエラーがないか定期的にチェックする。
- Google Analyticsで、ブラウザごとのページビュー数、平均セッション時間、コンバージョン率などを比較分析し、パフォーマンスの低いブラウザを特定する。
- 追加アクション:
シナリオ3: 検索エンジンボットのクロール行動の理解と最適化
検索エンジンがサイトを効率的にクロールし、インデックスできるようにすることは、SEOの基本です。
ua-parserの活用:ua-parserは、ログファイルからGooglebotやBingbotなどのUA文字列を抽出し、それらがサイトにアクセスしていることを確認できます。- 限界と追加アクション:
ua-parserはボットのUAを識別できても、そのクロール頻度、クロール深度、クロール予算の配分、またはrobots.txtの遵守状況までは把握できません。- 追加アクション:
- Google Search Consoleの「クロール統計情報」レポートを確認し、ボットのアクセス頻度、レスポンス時間、エラーなどを監視する。
robots.txtファイルを定期的にレビューし、意図しないページへのクロールをブロックしていないか、あるいは重要なページへのアクセスを妨げていないかを確認する。- ウェブサイトのログファイルを分析し、ボットのアクセスパターン、特に404エラーや5xxエラーが発生しているURLを特定し、修正する。
- サイトマップ(XML Sitemaps)を最新の状態に保ち、検索エンジンにサイトの構造を正確に伝える。
- 追加アクション:
シナリオ4: ユーザーインテントに基づいたコンテンツ戦略の立案
ユーザーが何を求めているのかを理解し、それに応えるコンテンツを提供することが、SEOの成功には不可欠です。
ua-parserの活用:ua-parserで、例えば「デスクトップ」ユーザーの割合が高い場合、彼らがより詳細な情報や複雑なタスクを求めている可能性を推測する手がかりとします。逆に「モバイル」ユーザーが多い場合は、簡潔で要点を押さえた情報や、ローカル検索に関連するコンテンツが求められていると仮定します。- 限界と追加アクション: UA文字列だけでは、ユーザーの具体的な検索意図やニーズを正確に知ることはできません。
- 追加アクション:
- Google Analyticsの「ランディングページ」レポートや「行動フロー」レポートで、ユーザーがどのようなページからアクセスし、どのようにサイト内を移動しているかを分析する。
- Google Search Consoleの「検索クエリ」レポートで、ユーザーがどのようなキーワードでサイトに流入しているかを確認し、その検索意図を推測する。
- キーワードリサーチツール(例: Google Keyword Planner, SEMrush, Ahrefs)を使用して、ターゲットキーワードの検索ボリューム、関連キーワード、および検索意図(情報収集、ナビゲーション、取引など)を調査する。
- ユーザーアンケートやフィードバックフォームを実施し、直接的なニーズや課題を把握する。
- 追加アクション:
シナリオ5: 多言語サイトのローカライズ戦略の補助
グローバルなターゲットを持つサイトでは、ユーザーの言語設定に合わせたコンテンツ提供が重要です。
ua-parserの活用: UA文字列に言語情報が含まれている場合(例:Accept-Languageヘッダー)、ua-parserでそれを抽出し、ユーザーの言語設定を推測する補助情報として利用できます。- 限界と追加アクション: UA文字列に含まれる言語情報は、必ずしも網羅的・正確ではなく、また
ua-parserがそれを常に正確に抽出できるとは限りません。- 追加アクション:
- ウェブサイトで「言語選択」メニューを明確に提供し、ユーザー自身が言語を選択できるようにする。
- Google Analyticsで、言語設定別のトラフィックやコンバージョン率を分析する。
hreflangタグを適切に実装し、検索エンジンに異なる言語バージョン間の関連性を示す。- IPアドレスによる地理位置情報サービスを利用して、ユーザーの居住地域を特定し、それに基づいて言語を推奨する。
- 追加アクション:
シナリオ6: 広告ターゲティングとSEOの連携
SEOと広告(例: Google Ads)を連携させることで、より効果的なアプローチが可能になります。
ua-parserの活用:ua-parserで、特定のデバイス(例: タブレット)からのアクセスが多い場合、そのデバイス向けの広告キャンペーンを強化する、あるいはそのデバイスに最適化されたLPを用意する、といった判断の材料とします。- 限界と追加アクション: UA文字列は、ユーザーの購買意欲や広告への反応性を直接示すものではありません。
- 追加アクション:
- Google Adsの「デモグラフィック」や「オーディエンス」レポートを活用し、ターゲット層をより詳細に把握する。
- Google Analyticsの「コンバージョン」レポートで、どのチャネル(SEO, 広告など)からのコンバージョンが多いか、またどのデバイスからのコンバージョンが多いかを分析する。
- 広告キャンペーンのパフォーマンスデータとSEOのパフォーマンスデータを照合し、全体的なROIを最大化するための戦略を調整する。
- 追加アクション:
グローバル産業標準とua-parserの位置づけ
UA解析に関連するグローバルな産業標準は、主にW3C(World Wide Web Consortium)やIETF(Internet Engineering Task Force)といった標準化団体によって定義されています。しかし、これらの標準は「UA文字列のフォーマット」や「HTTPプロトコルの仕様」に関するものであり、ua-parserのようなライブラリの「SEOにおける限界」を直接的に規定するものではありません。
UA文字列のフォーマット自体は、RFC 2616(HTTP/1.1)やRFC 7231(HTTP/1.1: Semantics and Content)などで定義されていますが、その内容は非常に柔軟であり、ベンダーが自由に情報を追加・変更できる余地があります。これが、ua-parserのようなパーサーが常に最新のUAに対応する必要がある理由の一つです。
SEOの観点からは、GoogleやBingといった検索エンジンが、自社のボットのUA文字列の解釈や、ウェブサイトのランキング要因としてUA情報をどのように利用するか(あるいは利用しないか)が、事実上の「標準」となります。
| 標準/ガイドライン | 内容 | ua-parserとの関連性 |
|---|---|---|
| RFC 2616 / RFC 7231 (HTTP/1.1) | HTTPプロトコルの仕様、User-Agentヘッダーの定義 | UA文字列の基本的なフォーマットと送信方法を定義。ua-parserはこのフォーマットを解析の基盤とする。 |
| Google Search Central (旧Webmaster Central) | GoogleのSEOに関する公式ガイドライン、クロール、インデックス作成、モバイルフレンドリーなどの情報を提供 | ua-parserで特定される情報(デバイスタイプ、ブラウザ)が、Googleのランキング要因(モバイルファースト、ページエクスペリエンス)とどう関連するかを理解する上で参照される。 |
| Bing Webmaster Guidelines | BingのSEOに関する公式ガイドライン | Googleと同様、Bingのランキング要因とUA情報との関連性を理解するための参照。 |
| W3C Mobile Web Best Practices | モバイルウェブサイト構築のためのベストプラクティス | ua-parserによるデバイスタイプの特定は、モバイル最適化戦略の初期段階で役立つ。 |
ua-parserは、これらの標準に準拠したUA文字列を「解析」することに長けていますが、SEOの「戦略」や「最適化」といった、より高次の概念においては、これらの標準を直接的に満たすものではありません。SEO担当者は、ua-parserの解析結果を、これらのグローバルなガイドラインや検索エンジンの推奨事項と照らし合わせながら、解釈・活用する必要があります。
多言語コード・ボキャブラリー・ボルト
ua-parserは、その性質上、特定の言語に依存するものではありません。しかし、多言語サイトのSEOや、グローバルなユーザーベースを分析する際には、UA文字列に含まれる言語関連情報(Accept-Languageヘッダーなど)の扱いや、解析結果を多言語で表示・分析する際の考慮が必要です。
以下は、ua-parserの概念を多言語環境でどのように適用できるかを示すための、概念的なコードスニペットと説明です。実際のua-parserライブラリは、各言語で提供されています。
Python Example (Conceptual)
Pythonでua-parserを使用し、UA文字列からブラウザ、OS、デバイス情報を抽出する基本的な例です。
from ua_parser import user_agent_parser
user_agent_string = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
parsed_ua = user_agent_parser.Parse(user_agent_string)
print("Browser:", parsed_ua['user_agent']['family'], parsed_ua['user_agent']['major'])
print("OS:", parsed_ua['os']['family'], parsed_ua['os']['major'])
print("Device:", parsed_ua['device']['family'])
# 概念的なAccept-Languageヘッダーの解析(ua-parser自体が直接サポートするわけではない)
# 実際のHTTPリクエストから取得したヘッダーをパースする必要がある
accept_language_header = "ja,en-US;q=0.9,en;q=0.8"
# ここで言語コードと優先度を抽出するロジックを実装
# 多言語表示のための辞書(例)
language_names = {
"ja": "日本語",
"en-US": "英語 (米国)",
"en": "英語"
}
# 抽出した言語コードに基づいて表示
# ... (言語コード抽出ロジック)
# print("Preferred Language:", language_names.get(primary_lang_code, primary_lang_code))
JavaScript Example (Conceptual)
Node.js環境などでua-parser-jsライブラリを使用する例です。
// npm install ua-parser-js
const UAParser = require('ua-parser-js');
const uaString = "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1";
const parser = new UAParser();
const result = parser.setUA(uaString).getResult();
console.log("Browser:", result.browser.name, result.browser.version);
console.log("OS:", result.os.name, result.os.version);
console.log("Device:", result.device.vendor, result.device.model);
// Accept-Languageヘッダーの処理は、サーバーサイドまたはAPIゲートウェイで行うのが一般的
// 例:Next.jsのAPIルートやExpress.jsミドルウェアで処理
// 多言語コンテンツの提供ロジック(概念)
// function getLocalizedContent(languageCode, pageKey) { ... }
多言語SEOにおける考慮事項:
Accept-Languageヘッダー: クライアントがHTTPリクエストで送信するAccept-Languageヘッダーは、ユーザーの優先言語設定を示す最も一般的な方法です。ua-parser自体はこのヘッダーを直接解析しませんが、サーバーサイドで取得し、別途解析する必要があります。- IPアドレスによる地域推定: ユーザーのIPアドレスから、おおよその地理的位置と、それに伴う言語を推定することも可能です。これは、
Accept-Languageヘッダーが不足している場合や、ユーザーが意図的に設定を変更している場合に役立ちます。 hreflangタグ: 検索エンジンに対して、異なる言語バージョンや地域バージョンのURLを正確に伝えるための標準的な方法です。ua-parserの解析結果とhreflangタグの関連性は直接的ではありませんが、多言語SEO戦略全体の一部として考慮されます。- コンテンツのローカライズ:
ua-parserは、どの言語のユーザーが多いかを分析するのに役立ちますが、最終的には、その言語圏の文化、習慣、表現に合わせたコンテンツの作成と提供が不可欠です。
将来展望とua-parserの進化
ウェブ技術は常に進化しており、ユーザーエージェント文字列の役割や、それを解析するツールの未来も変化していくでしょう。
- プライバシーへの配慮とUAクライアントヒント: 近年、ブラウザベンダーは、ユーザーのプライバシー保護を強化する動きを見せています。その一環として、従来のUA文字列に含まれる情報量が徐々に削減され、代わりに「クライアントヒント(Client Hints)」という、より限定的で、ユーザーが明示的に許可した場合にのみ送信される新しいヘッダーによる情報交換が推進されています。
- 影響: クライアントヒントが普及すると、
ua-parserが従来のUA文字列から得られる情報が限定的になり、その解析能力も影響を受ける可能性があります。SEO担当者は、クライアントヒントに対応した新しい解析ツールや手法に移行する必要が出てくるでしょう。
- 影響: クライアントヒントが普及すると、
- AIと機械学習の活用: 将来的には、AIや機械学習を活用して、より高度なユーザー行動分析やインテント推定が行われるようになるかもしれません。UA文字列の解析だけでなく、ユーザーの行動パターン、サイト内でのインタラクション、過去の履歴などを総合的に分析することで、より精緻なSEO戦略が可能になるでしょう。
ua-parserのような従来のパーサーは、これらの高度な分析のための「初期データ」を提供する役割を担う可能性があります。 - WebAssembly (Wasm) の利用: パフォーマンスが重視される場面では、JavaScriptよりも高速なWebAssemblyを利用したUA解析ライブラリが登場する可能性があります。これにより、クライアントサイドでのUA解析のリアルタイム性が向上し、より動的なSEO施策に貢献することが期待されます。
- SEOツールの統合進化: UA解析機能は、個別のライブラリとしてではなく、より包括的なSEOプラットフォームやアナリティクスツールの一部として、さらに高度に統合されていくでしょう。これらのツールは、UA情報だけでなく、ユーザーのコンテキスト、行動、検索意図を組み合わせた、より包括的な洞察を提供するようになると考えられます。
ua-parserは、そのシンプルさと汎用性から、今後も一定の役割を果たし続けるでしょう。しかし、SEOの進化に合わせて、より高度なプライバシー保護機能や、AI/MLを活用した分析能力を持つ新しいツールや手法への適応が、SEO担当者には求められます。
© 2023 [あなたの名前/ペンネーム]. All rights reserved.