サイト内検索
サイト内検索とは
サイト内検索は名前の通り、ウェブサイト内のコンテンツを自由なテキスト入力で検索する機能です。代表的なものにGoogle カスタム検索がありますが、それぞれのCMSで独自にサイト内検索機能が提供されていたりもします。
HubSpotにおいてもこの機能は提供されており、試しに下記検索ボックスに検索語句を入れると、
- 検索語句の入力中に候補が表示される
- 検索語句を入れEnterを押すと、検索結果ページへ遷移する
などの挙動が確認できます。
このHubSpotのサイト内検索の仕様や挙動、カスタマイズについて解説します。
関連する公式ドキュメントは以下の通りです。本ページに記載の情報は執筆時段階のものですので、実際の挙動と乖離がある場合は必ず公式ドキュメントを確認してください。
検索できるコンテンツ
まず始めに、HubSpotのサイト内検索で検索できるコンテンツと、設定できる条件に関して大まかに示します。
- コンテンツタイプ
- ウェブサイトページ
- ランディングページ
- ブログ記事
- ブログトップ
- ナレッジベース
- HubDB動的生成ページ
- 対象ドメイン
- 自由に指定が可能
- 言語(多言語機能利用の場合)
- 自由に設定が可能
- 公開状態
- 公開済みで、かつHubSpotのクローラーが認知できる必要あり
- 例えば
<meta name="robots" content="noindex">
などを設定していると、HubSpotのクローラーが認知できないため検索対象となりません - 開発時は、[設定] → [ウェブサイト] → [ページ] → [SEOおよびクローラー] のRobots.txtを次のようにすると一般的なクローラーをブロックしつつ、サイト内検索の検証ができます。
# 全てのクローラーをブロックする User-agent: * Disallow: / # HubSpotのサイト内検索クローラーのみ許可する User-agent: HubSpotContentSearchBot Allow: /
また注意点として、
- JavaScriptによりページに動的に差し込まれるコンテンツ
- hubspotpagebuilderドメインで公開しているページ
は検索対象になりません。
検索結果として取得できる要素
- ページタイプ(
SITE_PAGE
、BLOG_POST
など) - ページのドメイン
- タイトル
- 検索語句と完全一致している語句は
<span class="hs-search-highlight hs-highlight-title">
で括られます(ので、検索結果画面で太字表示などができる)
- 検索語句と完全一致している語句は
- URL
- サムネイル画像
- 説明文
- 検索語句と完全一致している語句は
<span class="hs-search-highlight hs-highlight-html">
で括られます
- 検索語句と完全一致している語句は
- ページの言語
- 執筆者名(ブログ記事の場合)
- タグ(ブログ記事の場合)
- 公開日(ブログ記事の場合)
実際のレスポンスのJSONは次の通りです。
{ "total": 32, "offset": 0, "limit": 10, "results": [ { "id": 51724179823, "score": 0.18574764, "type": "BLOG_POST", "domain": "hubspot.pensees.co.jp", "url": "https://hubspot.pensees.co.jp/tips/cms-hub-starter", "featuredImageUrl": "https://hubspot.pensees.co.jp/hubfs/how-to-hubspot/tips/img/cms-hub-starter.png", "language": "ja-jp", "title": "ついにきた黒船。<span class=\"hs-search-highlight hs-highlight-title\">HubSpot</span> CMS Hub Starterプラン", "description": "BASICS OF <span class=\"hs-search-highlight hs-highlight-html\">HUBSPOT</span>... <span class=\"hs-search-highlight hs-highlight-html\">HubSpot</span> CMS HubにStarterプランが登場しました。¥3,000/月 とあり得ない価格です。本記事ではStarterプランでできることのまとめはもちろん、他のプランとの比較や、そもそもCMS Hubとはどんなものか、というところまで棚卸しして解説します。...", "authorFullName": "半田 惇志", "tags": ["CMS", "ブログ"], "publishedDate": 1628039348000 } ], "cacheKey": "...", "searchTerm": "hubspot", "page": 0 }
※取得できるコンテンツについては、HubSpotの公式ドキュメントとAPIのレスポンスに食い違いがあり、実際のAPIのレスポンスでより多くのデータを取得できることを確認しています。利用中に違和感がある場合は、APIのレスポンスデータを直接確認することを推奨します。
APIのエンドポイント:https://api.hubapi.com/contentsearch/v2/search?portalId=ポータルIDが入ります&term=検索語句が入ります
サイト内検索の実装方法
仕組みとしては、先で挙げたSearch for Content APIが一般利用できるエンドポイントとして提供されているため、このAPIのレスポンスのJSONをパースできれば理論上はどのようなページでも検索の仕組みを実装することは可能です。
ただし入力欄と検索結果画面のカスタムモジュールをHubSpotがそれぞれ標準で用意してくれていますので、これらを活用するのが無難です。
検索結果ページのテンプレートの選択
まずは検索結果ページとして表示させるテンプレートを指定します。[設定] → [ウェブサイト] → [ページ] → [システムページ] の最下部にて、任意のテンプレートを選択します。ここに選択肢として表示されるのは、テンプレートファイル内のコメントにてtemplateType: search_results_page
の設定がされているものです。なおこの設定画面では、検索結果ページのURLを変えることもできます。
またHubSpot標準テーマのテンプレートを見てもわかるように、検索結果テンプレートには実際に検索結果を表示させるためのカスタムモジュールを埋め込む必要があります。標準のカスタムモジュールは下記のように記述することで埋め込めます。
{% module "search_results" path="@hubspot/search_results", label="検索結果" %}
HubSpotのUIから新たに検索結果テンプレートを作成するには、下記ナレッジベースを参考にしてください。
入力欄の実装
標準モジュールを利用して検索入力欄を設けるには、 “サイト検索入力” カスタムモジュールを利用します。ここで入力した検索語句が、先ほど設定した検索結果ページ(テンプレート)に渡され、検索結果が表示される仕組みです。
結果表示までの必要な処理は全てカスタムモジュール内に記載されていますので、このカスタムモジュールを埋め込みさえすれば、ヘッダーでもフッターでも、どこからでも同じように検索結果画面へ遷移させられます。
UIのカスタマイズ
標準のカスタムモジュールでは見た目がそぐわないこともあるでしょう。そういった場合は、標準のカスタムモジュールを複製してカスタマイズするのが一般的です。標準のカスタムモジュールには検索結果表示のための多くのJavaScriptが既に記述されているため、このロジックを活かさない手はありません。
デザインツール上で “site search” と検索すると、標準のカスタムモジュールがヒットし、選択するとモジュール複製を勧められます。
HubSpot CLIを利用している場合は、下記のコマンドで標準のカスタムモジュールを直接ローカルに引き込むことも可能です(ただし、fetch元のアカウントに認証を通す必要があります)。
hs fetch @hubspot/search_input.module hs fetch @hubspot/search_results.module
後はそれぞれのカスタムモジュールを好きなようにカスタマイズし、テンプレートやページに埋め込むだけです。
検索挙動のカスタマイズ
標準のサイト検索入力モジュールを見てもわかるように、検索項目や対象はカスタマイズできるようになっています。繰り返しになりますが、サイト内検索は内部的にはSearch for Content APIを利用しているため、基本的にプロパティや値はこのドキュメントに従うことになります。
例えばウェブサイトページとブログ記事を対象に “hubspot” という検索をかける場合、クエリは次のようになります。
https://api.hubapi.com/contentsearch/v2/search?portalId=ポータルID&term=hubspot&type=SITE_PAGE&type=BLOG_POST
注目すべきはtype
指定がtype=SITE_PAGE, BLOG_POST
のようにカンマ区切りや配列のようになっているのではなく、type=SITE_PAGE&type=BLOG_POST
とtype
指定の数だけキーも繰り返している点です。1つのプロパティに対し複数の値を設定する場合は、このようにキーごと繰り返す形となります(割と一般的な仕様ですが)。
上記を踏まえたうえで標準のサイト検索入力モジュールを見ると、データをform
タグで渡しているのが分かります。上記と同様の検索結果を得るには、次のようにHTMLを記述します。
<form action="/hs-search-results"> <!-- ユーザーの入力がそのままtermのvalueとなる --> <input type="text" name="term"> <input type="hidden" name="type" value="SITE_PAGE"> <input type="hidden" name="type" value="BLOG_POST"> </form>
つまりinput
要素のname
にプロパティのキーが入り、value
に値が入る形です。この基本がわかれば、後はAPIに合わせてHTMLを調整するだけです。APIの必須プロパティはterm
とportalId
ですが、標準のカスタムモジュールをカスタマイズして利用する場合はportalId
は不要です(恐らくJavaScriptで “/_hcms/search
” にリクエストを送っている限り)。
ここからは、逆引きの形で各プロパティを解説していきます。
ページタイプを絞りたい:type, groupId, tableId
柔軟にカスタマイズしたい:type
- 取り得る値
-
SITE_PAGE
(ウェブサイトページ)LANDING_PAGE
(ランディングページ)BLOG_POST
(ブログ記事)LISTING_PAGE
(ブログトップ)KNOWLEDGE_ARTICLE
(ナレッジベース)
- 使用例
-
<input type="hidden" name="type" value="SITE_PAGE">
- クエリ例
- https://www.pensees.co.jp/hs-search-results?term=hubspot&type=SITE_PAGE
特定のブログ記事に絞りたい:groupId
- 取り得る値
-
- ブログID(複数のブログIDを渡すことで、検索対象ブログの追加が可能です)
- 使用例
-
<input type="hidden" name="groupId" value="9696629467">
- クエリ例
- https://www.pensees.co.jp/hs-search-results?term=hubspot&groupId=9696629467
HubDBの動的生成ページに絞りたい:tableId
- 取り得る値
-
- HubDBテーブルID(groupIdとは違い、こちらは単一のIDしか渡せません)
- 使用例
-
<input type="hidden" name="tableId" value="5208314462">
- クエリ例
- https://www.pensees.co.jp/hs-search-results?term=hubspot&tableId=1051109
またhubdbQuery
プロパティを併用することで、さらに詳細なフィルタリングができる……らしいのですが、どう検証してもhudbQuery
の投げ方がよくわかりませんでした。hudbQuery
自体は、恐らくGet table rowsのAPIドキュメント内のフィルタする際のクエリのことを指しているのだと思います。
検索対象コンテンツを絞りたい:property
- 取り得る値
-
title
description
html
author_full_name
(ブログ記事のみ)author_handle
(ブログ記事のみ)tag
(ブログ記事のみ)
- 使用例
-
<input type="hidden" name="property" value="title">
- クエリ例
- https://www.pensees.co.jp/hs-search-results?term=hubspot&property=title
「HubSpotのサイト内検索は何でもかんでも取ってきすぎる」と思っていませんか?これが原因です。デフォルトでは全ての値がセットされていますが、html
を含めると各ページ内の全てHTML要素を検索対象とします。この場合、ドキュメントには次の通りで重み付けしていると記載があります。
title
タグmeta description
h1
タグh2
タグh3
タグ- その他のタグ
とはいえ、結局「6. その他のタグ」に該当したのか検索語句と全く関係のないようなページも多くヒットしてしまいがちなため、基本的にはhtml
を外すとよいでしょう。
html
を対象としたうえで、各ページ内でコンテンツの重み付けを柔軟に制御したい場合は次のいずれかのクラスで囲みます。
hs-search-keyword
- 例えば本ページをCMS Hubという検索語句でも引っかかるようにしたい場合は、 “CMS Hub” という文字列を “
<span class="hs-search-keyword">CMS Hub</span>
” とします
- 例えば本ページをCMS Hubという検索語句でも引っかかるようにしたい場合は、 “CMS Hub” という文字列を “
hs-search-hidden
- このクラス内は検索対象から外します。ヘッダーやフッターなどの共通部分に付与すると効果的です
URLで絞りたい:domain, pathPrefix
ドメインで絞りたい:domain
- 取り得る値
-
- ドメイン
- 使用例
-
<input type="hidden" name="domain" value="www.pensees.co.jp">
- クエリ例
- https://www.pensees.co.jp/hs-search-results?term=hubspot&domain=www.pensees.co.jp
domain
が省略されている場合は、恐らくHubSpot内の同ブランドドメインのページ全てが対象となります(未検証)。
パスで絞りたい:pathPrefix
- 取り得る値
-
- パスの文字列
- 使用例
-
<input type="hidden" name="pathPrefix" value="hubspot">
- クエリ例
- https://www.pensees.co.jp/hs-search-results?term=hubspot&pathPrefix=hubspot
注意点としては、パスが「pathPrefix
の値で始まる」ページが対象となります。上記のように “hubspot” を指定した場合、www.pensees.co.jp/hubspot のパスのページは該当しますが、www.pensees.co.jp/service/hubspot のページは該当しません(例示しているだけで、このページ自体パンセのサイトには存在しません)。
また、 “hubspot” とした場合と “hubspot/” とした場合にも違いがあります。前者は値にスラッシュを含まないため www.pensees.co.jp/hubspot も www.pensees.co.jp/hubspot/pricing も該当しますが、後者は「hubspot/で始まる」という指定のため、 www.pensees.co.jp/hubspot/pricing しか該当しません。下記2つのクエリ例を表示させてみて、違いを確認してください。
- https://www.pensees.co.jp/hs-search-results?term=hubspot&pathPrefix=hubspot
- https://www.pensees.co.jp/hs-search-results?term=hubspot&pathPrefix=hubspot/
なおドキュメントには記載がありませんが、2022年5月現在、 pathPrefix
の文字数が30文字を超えるとエラーが返され検索が実行されない仕様があります(元々はエラーすら返さなかったのですが、サポートに問い合わせたところこの仕様が発覚し、エラーを返すようになりました)。
また「hubspotで始まらない」とするには、matchPrefix
を明示的にfalse
にします(デフォルトはtrue
になっています)。
- 使用例
-
<input type="hidden" name="matchPrefix" value="false">
- クエリ例
- https://www.pensees.co.jp/hs-search-results?term=hubspot&pathPrefix=hubspot&matchPrefix=false
言語で絞りたい:language
- 取り得る値
-
- ISO639-1の言語コード
- 使用例
-
<input type="hidden" name="language" value="ja">
- クエリ例
- https://www.pensees.co.jp/hs-search-results?term=hubspot&language=ja
多言語機能を利用している場合に有効なプロパティです。
検索結果のテキスト量を調整したい/検索挙動を早くしたい:length
- 取り得る値
-
LONG
またはSHORT
(デフォルトはLONG
)
- 使用例
-
<input type="hidden" name="length" value="SHORT">
- クエリ例
- https://www.pensees.co.jp/hs-search-results?term=hubspot&length=SHORT
LONG
の場合、レスポンスのdescription
に検索語句とマッチ度が高いページ内のテキストを返します。SHORT
とすると機械的にmeta description
を返しますが、その分検索処理が早くなります。
なおパンセサイトでは検索結果に説明文を表示していないため、上記クエリ例の値を変えても見た目は変わりません。LONG
とSHORT
での違いを確認するには、ご自身のポータルで下記2つのAPIへの直接リクエストを比較してみてください。
- https://api.hubapi.com/contentsearch/v2/search?portalId=ポータルID&term=hubspot
- https://api.hubapi.com/contentsearch/v2/search?portalId=ポータルID&term=hubspot&length=SHORT
1ページの表示件数を調整したい:limit
- 取り得る値
-
- 数値(デフォルトは10)
- 使用例
-
<input type="hidden" name="limit" value="20">
- クエリ例
- https://www.pensees.co.jp/hs-search-results?term=hubspot&limit=20
最大値は100です。次のoffset
も併用することで、ページャーが実装できます。
- 使用例
-
<input type="hidden" name="offset" value="20">
- クエリ例
- https://www.pensees.co.jp/hs-search-results?term=hubspot&limit=20&offset=20 (20件刻みのうち2ページ目の検索結果。下部の数値ページャーはJavaScriptをカスタマイズして独自実装しています)
ページビュー数で並び替えたい:popularityBoost
- 取り得る値
-
- 数値(デフォルトは1.0)
- 使用例
-
<input type="hidden" name="popularityBoost" value="10.0">
- クエリ例
- https://www.pensees.co.jp/hs-search-results?term=hubspot&popularityBoost=10.0
わかりやすいよう「並び替えたい」というタイトルにしていますが、厳密には「ページビュー順で並び替える」という訳ではなく、「ページビューの重み付けを調整する → 結果、検索結果に変動が生じる」という形になります。
また数値の最大値はmaxBoost
で別途管理されておりmaxBoost
のデフォルト値は5.0のようなのですが、
- https://www.pensees.co.jp/hs-search-results?term=hubspot&popularityBoost=5.0
- https://www.pensees.co.jp/hs-search-results?term=hubspot&popularityBoost=100.0
で検索結果が違う、つまりpopularityBoost=100.0
も普通に評価されているようなので、maxBoost
がどこまで有用なのかは謎です。
公開日で並び替えたい:boostRecent
- 取り得る値
-
- 数値+単位(以下)
- ms(ミリ秒)
- s(秒)
- m(分)
- h(時)
- d(日)
- 数値+単位(以下)
- 使用例
-
<input type="hidden" name="boostRecent" value="10d">
- クエリ例
- https://www.pensees.co.jp/hs-search-results?term=hubspot&boostRecent=10d
こちらも、厳密には並び替えではなく公開日の重み付けの調整です。完全に公開日順で並び替えたければ、レスポンスのJSONをJavaScriptでソートするとよいでしょう(ただしlimitで取得した件数内での並び替えになる。全検索結果に対する並び替えは非常に面倒です)。なお、このプロパティはブログ記事にのみ影響し、上記の例は「10日以内に公開されたブログ記事に重みを加える」という意味になります。
boostRecent
のみで使用するとあまり芳しくない結果となるので、ブログ記事のみを検索する場合のみの使用とした方が良さそうです(そもそも、ユーザーの検索語句に対し公開日は重要であるかどうかも一考したいところです)。
term
のみ:https://www.pensees.co.jp/hs-search-results?term=hubspotterm
+boostRecent
:https://www.pensees.co.jp/hs-search-results?term=hubspot&boostRecent=10dterm
+boostRecent
+type
:https://www.pensees.co.jp/hs-search-results?term=hubspot&boostRecent=10d&type=BLOG_POST
関連度でフィルタをかけたい:minScore
2022年6月現在、このプロパティは廃止されていることがサポートに問い合わせし発覚しています。
- 取り得る値
-
- 数値
- 使用例
-
<input type="hidden" name="minScore" value="0.25">
- クエリ例
- https://www.pensees.co.jp/hs-search-results?term=hubspot&minScore=0.25
検索結果の各ページは、検索語句と、今まで紹介した重み付けの調整を加味した最終的なスコアを持っており、検索結果はこのスコア順に表示されます。このスコアは https://api.hubapi.com/contentsearch/v2/search?portalId=ポータルID&term=hubspot のエンドポイントを直接叩くのが1番簡単に確認できます。
このスコアについて、「0.25未満のものは表示させない」のようにフィルタがかけられるのがこのプロパティです。
補足
APIドキュメントには他にanalytics
やautocomplete
のプロパティがありますが、説明文を読んでも、実際に利用してみてもイマイチ挙動が掴めないため本ページでの解説は割愛します。
まとめと余談
以上、HubSpotのサイト内検索の仕組みと挙動、カスタマイズについて解説しました。
余談ですが、このサイト内検索が提供されたのは2018年の春頃で、それまではGoogleのサイト内検索を取り入れたサイト内検索モジュールが提供されていました。そのため昔に作られたウェブサイト(CMS HubがCOSと呼ばれていた時代です)であれば、もしかすると動作はせずともまだこのモジュールが埋め込まれているかもしれません。
また、サイト内検索リリース当時は内部的にはElastic Searchを利用していると言っていました。今はどうなっているかはわかりませんが、この辺りの変遷は下記ブログ記事にまとめています。
→ INBOUND 2017で発表されたHubSpot COSの新機能まとめ