Shopifyのストアフロント検索は /search?q=キーワード&type=article で記事に絞り込めますが、ストア内の全ブログを横断してしまい、ブログを限定する指定がありません。ブログを複数設置していると、他のブログの記事が検索結果に混ざります。このTIPSでは、特定のブログの記事だけを対象にした検索を、ベンダーファイルを一切変更せずに実装する方法を紹介します。

ブログ一覧ページに検索フォームを置き、その送信先として「そのブログの記事だけが並ぶ結果ページ」を用意します。ブログが複数あっても、それぞれのブログに専用の検索を持たせられます。
【既存TIPSとの関係】 以前公開したDawnのブログに記事検索を設置する設定例は、この制約のため「ブログを1つだけ設置しているストア向け」という条件付きでした。今回はその続編にあたり、複数ブログのストアでも使える形にしています。考え方は「よくあるご質問」のページだけを対象に検索する方法と近く、URLを手がかりに絞り込みます。
通常の検索で起きること
type=article を付けても、Shopifyはストア内の全ブログの記事を返します。下は News ブログと Journal ブログを置いたストアで「Horizon」を検索した結果で、赤枠の3件が Journal ブログの記事です。

仕組み(3つの組み合わせ)

① 代替テンプレート(?view=)で専用の結果ページを用意する
ShopifyはURLに view パラメータを付けると templates/search.{識別名}.json を使います。通常の /search は従来どおりに保ったまま、ブログ専用の検索結果画面を追加できます。
② 記事のURLを見て絞り込む
検索そのものはShopifyに任せ、返ってきた search.results を1件ずつ見て、対象ブログ以外の記事を捨てます。判定には記事のURLを使います。対象ブログの記事URLは必ず /blogs/<ブログのハンドル>/ を含むため、確実に判定できます。
③ どちらもテーマブロックとして作る
入口のフォームと結果の一覧を、それぞれ独立したテーマブロックにします。セクションを1つ占有せず、テーマエディタの「ブロックを追加」から置けます。フォームは type=article と view={識別名} を hidden で渡すので、利用者はキーワードを入れるだけで済みます。
ファイル構成
新規3ファイルのみで、既存ファイルの変更はありません。

-
blocks/blog-search-form.liquid(新規)— ブログ一覧に置く検索フォーム -
blocks/blog-search-results.liquid(新規)— 結果ページ。フォーム+対象ブログで絞った記事一覧 -
templates/search.blog-search.json(新規)— 上の2つ目のブロックを Horizon 標準の「セクション」に載せた結果ページのテンプレート
ブログ一覧側(sections/main-blog.liquid)はテーマエディタでブロックを追加するだけで、コードは触りません。templates/blog.json もテーマエディタ側が書き換えるので、手書きしないでください。
templates/search.blog-search.json は「Horizon標準の『セクション』を1つ置き、その中に結果ブロックを入れる」だけの内容です。書いていない設定は既定値が使われるため、これで足ります。
ブロックのファイル名に _ を付けないでください。 _ 始まりだとブログ一覧に追加できず、ベンダーファイルの修正が必要になります。
テーマエディタでの設定(手順)
どちらの画面も「ブロックを追加」から置きます。ただし結果ページの方は、テーマエディタのページ切替メニューに出てきません。 検索は「検索」が1つあるだけで、代替テンプレートは一覧に並ばないためです。URLを直接組み立てて開きます。
① ブログ一覧に検索フォームを置く
オンラインストア → テーマ → カスタマイズ でエディタを開き、左上のページ切替から対象のブログを選びます。左サイドバーの Template にある「ブログ記事」の下の ブロックを追加 → カテゴリ「フォーム」 → ブログ内検索フォーム。
追加したら 送信先テンプレートの識別名(view) に blog-search と入れて保存します。

② 結果ページをURLで開く
いま開いているエディタのURLは次の形になっています。
https://admin.shopify.com/store/{ストア名}/themes/{テーマID}/editor?previewPath=...
/editor までをそのまま使い、? 以降を次に差し替えてアクセスします。
?previewPath=%2Fsearch%3Fq%3Dtest%26type%3Darticle%26view%3Dblog-search
これはURLエンコードされた /search?q=test&type=article&view=blog-search です。q には結果が出るキーワードを入れておくと確認しやすくなります。view の値は templates/search.{識別名}.json のファイル名と一致させます。
ストア名とテーマIDを入れると、開くべきURLがそのまま出ます。 どちらも、いま開いているエディタのURL .../store/ここ/themes/ここ/editor... から読み取れます。
正しく開けていれば、エディタ左上のテンプレート名が search.blog-search に変わります。ここが「検索」のままなら、既定の検索テンプレートを開いています。
③ 結果ページにブロックを置く
左サイドバーの Template にある「セクション」の下の ブロックを追加 → カテゴリ「フォーム」 → ブログ内検索の結果。追加したら 検索対象のブログ で対象ブログを選び、1ページの取得件数 を設定して保存します。識別名はここでは入力しません。 自分が置かれているテンプレートから自動で決まります。

【注意】識別名のタイプミスは静かに失敗します。 存在しない view を指定すると、エラーにはならず既定の templates/search.json(通常の検索結果)が描画されます。フォーム側の識別名とテンプレートのファイル名が一致しているか確認してください。
ブログを複数にする場合
テンプレートはブログごとに2つ必要です。 検索結果用だけでなく、ブログ一覧側も分けるのを忘れないでください。識別名はフォームブロックの設定として templates/blog.json に保存されるため、複数のブログが同じ blog.json を使っていると全ブログが同じ識別名を送り、どこから検索しても同じブログの結果が出ます。
ブログを1つ増やすときの手順です。
-
templates/blog.{識別名}.jsonを作り、ブログの設定画面(コンテンツ → ブログ記事 → ブログを管理 → 対象のブログ)でテーマテンプレートとして割り当てる - そのブログ一覧をテーマエディタで開き、フォームブロックを追加して
送信先テンプレートの識別名(view)に新しい識別名を入れる -
templates/search.{識別名}.jsonを同じ識別名で作る(中身は既存のコピーでよい) - 手順②のURLの
viewを新しい識別名に変えて開き、結果ブロックの検索対象のブログを新しいブログに設定する
増えるのはテンプレートJSONだけで、blocks/ の2ファイルは全ブログで共用します。

注意点:ページングは絞り込み前の件数にかかる
ページ数はShopifyが返した全ブログ横断の件数で決まり、そこから他ブログ分を除いて表示します。 このため、ページごとの表示件数が指定値に満たないことがあります。他ブログの記事が最終ページに集中すると、最後のページが0件になることもあります。
実測例(対象ブログの記事1,672件・他ブログ46件のストアで「Flow」を検索):
- Shopifyの検索ヒット総数: 171件
- 対象ブログとして表示: 156件
- 他ブログ分として除外: 15件
- ページ毎の表示件数: 20, 20, 20, 20, 20, 20, 20, 16, 0
緩和策: {% paginate %} の件数を増やします(上限250件。超えると250に丸められます)。ページ数が減るぶん、空ページや極端に少ないページが出にくくなります。50件程度が実用的で、ブロックの設定から変更できます。

やってはいけないこと: 「50件取得して先頭20件だけ表示」のような実装にすると、21件目以降がどのページにも出てこず、結果が欠落します。絞り込み後の全件をそのまま表示してください。
補足
-
なぜ
viewを使うのか:Liquid は任意のクエリパラメータを読めません。requestオブジェクトが持つのはdesign_mode/visual_preview_mode/page_type/host/origin/path/localeだけで、クエリ文字列は含まれません。/search?blog=newsのような独自パラメータを送っても受け取る口がないため、Shopify 自身がテンプレート選択に使うviewを経由しています - 検索対象は記事の本文・タイトル・タグです。タグに年月などを入れておけば、それでも検索できます
- Shopifyアプリ「Search & Discovery」の絞り込みフィルターは商品専用で、ブログ記事には使えません
- 結果ページ側のフォームは設定で非表示にできます。既定では表示しており、結果画面からそのまま再検索できます
サンプルコード
3ファイルの全文を収録しています。購入後にご確認いただけます。
