{"product_id":"2026-09-27","title":"【Horizon】Shopifyで複数のブログがある場合に特定のブログの記事だけを検索できるようにする設定例","description":"\u003cp\u003eShopifyのストアフロント検索は \u003ccode\u003e\/search?q=キーワード\u0026amp;type=article\u003c\/code\u003e で記事に絞り込めますが、\u003cstrong\u003eストア内の全ブログを横断してしまい、ブログを限定する指定がありません\u003c\/strong\u003e。ブログを複数設置していると、他のブログの記事が検索結果に混ざります。このTIPSでは、特定のブログの記事だけを対象にした検索を、ベンダーファイルを一切変更せずに実装する方法を紹介します。\u003c\/p\u003e\n\n\u003cp\u003e\u003cimg alt=\"ブログ一覧の検索フォームと絞り込み済みの結果ページ\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0733\/0381\/8491\/files\/2026-09-27_1.png?v=1790491927\" class=\"zoomable-image\" style=\"max-width:100%;height:auto;\"\u003e\u003c\/p\u003e\n\n\u003cp\u003eブログ一覧ページに検索フォームを置き、その送信先として「そのブログの記事だけが並ぶ結果ページ」を用意します。ブログが複数あっても、それぞれのブログに専用の検索を持たせられます。\u003c\/p\u003e\n\n\u003cp\u003e\u003cstrong style=\"color:#e0301e;\"\u003e【既存TIPSとの関係】\u003c\/strong\u003e 以前公開した\u003ca href=\"\/products\/2025-06-08\"\u003eDawnのブログに記事検索を設置する設定例\u003c\/a\u003eは、この制約のため「ブログを1つだけ設置しているストア向け」という条件付きでした。今回はその続編にあたり、複数ブログのストアでも使える形にしています。考え方は\u003ca href=\"\/products\/2024-02-06\"\u003e「よくあるご質問」のページだけを対象に検索する方法\u003c\/a\u003eと近く、URLを手がかりに絞り込みます。\u003c\/p\u003e\n\n\u003ch3\u003e通常の検索で起きること\u003c\/h3\u003e\n\n\u003cp\u003e\u003ccode\u003etype=article\u003c\/code\u003e を付けても、Shopifyはストア内の全ブログの記事を返します。下は News ブログと Journal ブログを置いたストアで「Horizon」を検索した結果で、赤枠の3件が Journal ブログの記事です。\u003c\/p\u003e\n\n\u003cp\u003e\u003cimg alt=\"通常の検索は全ブログを横断する\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0733\/0381\/8491\/files\/2026-09-27_2.png?v=1790491927\" class=\"zoomable-image\" style=\"max-width:100%;height:auto;\"\u003e\u003c\/p\u003e\n\n\u003ch3\u003e仕組み（3つの組み合わせ）\u003c\/h3\u003e\n\n\u003cp\u003e\u003cimg alt=\"検索はShopifyに任せ、結果だけを絞り込む\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0733\/0381\/8491\/files\/2026-09-27_3.png?v=1790491927\" class=\"zoomable-image\" style=\"max-width:100%;height:auto;\"\u003e\u003c\/p\u003e\n\n\u003cp\u003e\u003cstrong\u003e① 代替テンプレート（\u003ccode\u003e?view=\u003c\/code\u003e）で専用の結果ページを用意する\u003c\/strong\u003e\u003cbr\u003e\nShopifyはURLに \u003ccode\u003eview\u003c\/code\u003e パラメータを付けると \u003ccode\u003etemplates\/search.{識別名}.json\u003c\/code\u003e を使います。通常の \u003ccode\u003e\/search\u003c\/code\u003e は従来どおりに保ったまま、ブログ専用の検索結果画面を追加できます。\u003c\/p\u003e\n\n\u003cp\u003e\u003cstrong\u003e② 記事のURLを見て絞り込む\u003c\/strong\u003e\u003cbr\u003e\n検索そのものはShopifyに任せ、返ってきた \u003ccode\u003esearch.results\u003c\/code\u003e を1件ずつ見て、対象ブログ以外の記事を捨てます。判定には記事のURLを使います。対象ブログの記事URLは必ず \u003ccode\u003e\/blogs\/\u0026lt;ブログのハンドル\u0026gt;\/\u003c\/code\u003e を含むため、確実に判定できます。\u003c\/p\u003e\n\n\u003cp\u003e\u003cstrong\u003e③ どちらもテーマブロックとして作る\u003c\/strong\u003e\u003cbr\u003e\n入口のフォームと結果の一覧を、それぞれ独立したテーマブロックにします。セクションを1つ占有せず、テーマエディタの「ブロックを追加」から置けます。フォームは \u003ccode\u003etype=article\u003c\/code\u003e と \u003ccode\u003eview={識別名}\u003c\/code\u003e を hidden で渡すので、利用者はキーワードを入れるだけで済みます。\u003c\/p\u003e\n\n\u003ch3\u003eファイル構成\u003c\/h3\u003e\n\n\u003cp\u003e新規3ファイルのみで、既存ファイルの変更はありません。\u003c\/p\u003e\n\n\u003cp\u003e\u003cimg alt=\"追加する3ファイル（コードエディタ）\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0733\/0381\/8491\/files\/2026-09-27_4_65cd92ea-1068-4184-9d21-04fab7dfa87e.png?v=1790491927\" class=\"zoomable-image\" style=\"max-width:100%;height:auto;\"\u003e\u003c\/p\u003e\n\n\u003cul\u003e\n\u003cli\u003e\n\u003ccode\u003eblocks\/blog-search-form.liquid\u003c\/code\u003e（新規）— ブログ一覧に置く検索フォーム\u003c\/li\u003e\n\u003cli\u003e\n\u003ccode\u003eblocks\/blog-search-results.liquid\u003c\/code\u003e（新規）— 結果ページ。フォーム＋対象ブログで絞った記事一覧\u003c\/li\u003e\n\u003cli\u003e\n\u003ccode\u003etemplates\/search.blog-search.json\u003c\/code\u003e（新規）— 上の2つ目のブロックを Horizon 標準の「セクション」に載せた結果ページのテンプレート\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003cp\u003eブログ一覧側（\u003ccode\u003esections\/main-blog.liquid\u003c\/code\u003e）はテーマエディタでブロックを追加するだけで、コードは触りません。\u003ccode\u003etemplates\/blog.json\u003c\/code\u003e もテーマエディタ側が書き換えるので、手書きしないでください。\u003c\/p\u003e\n\n\u003cp\u003e\u003ccode\u003etemplates\/search.blog-search.json\u003c\/code\u003e は「Horizon標準の『セクション』を1つ置き、その中に結果ブロックを入れる」だけの内容です。書いていない設定は既定値が使われるため、これで足ります。\u003c\/p\u003e\n\n\u003cp\u003e\u003cstrong style=\"color:#e0301e;\"\u003eブロックのファイル名に \u003ccode\u003e_\u003c\/code\u003e を付けないでください。\u003c\/strong\u003e \u003ccode\u003e_\u003c\/code\u003e 始まりだとブログ一覧に追加できず、ベンダーファイルの修正が必要になります。\u003c\/p\u003e\n\n\u003ch3\u003eテーマエディタでの設定（手順）\u003c\/h3\u003e\n\n\u003cp\u003eどちらの画面も「ブロックを追加」から置きます。ただし\u003cstrong\u003e結果ページの方は、テーマエディタのページ切替メニューに出てきません。\u003c\/strong\u003e 検索は「検索」が1つあるだけで、代替テンプレートは一覧に並ばないためです。URLを直接組み立てて開きます。\u003c\/p\u003e\n\n\u003cp\u003e\u003cstrong style=\"color:#e0301e;\"\u003e① ブログ一覧に検索フォームを置く\u003c\/strong\u003e\u003c\/p\u003e\n\n\u003cp\u003eオンラインストア → テーマ → カスタマイズ でエディタを開き、左上のページ切替から対象のブログを選びます。左サイドバーの Template にある「ブログ記事」の下の \u003cstrong\u003eブロックを追加\u003c\/strong\u003e → カテゴリ「フォーム」 → \u003cstrong\u003eブログ内検索フォーム\u003c\/strong\u003e。\u003cbr\u003e\n追加したら \u003ccode\u003e送信先テンプレートの識別名（view）\u003c\/code\u003e に \u003ccode\u003eblog-search\u003c\/code\u003e と入れて保存します。\u003c\/p\u003e\n\n\u003cp\u003e\u003cimg alt=\"手順① ブログ一覧に検索フォームを置く\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0733\/0381\/8491\/files\/2026-09-27_5.png?v=1790491927\" class=\"zoomable-image\" style=\"max-width:100%;height:auto;\"\u003e\u003c\/p\u003e\n\n\u003cp\u003e\u003cstrong style=\"color:#e0301e;\"\u003e② 結果ページをURLで開く\u003c\/strong\u003e\u003c\/p\u003e\n\n\u003cp\u003eいま開いているエディタのURLは次の形になっています。\u003c\/p\u003e\n\n\u003cp\u003e\u003ccode\u003ehttps:\/\/admin.shopify.com\/store\/\u003cstrong\u003e{ストア名}\u003c\/strong\u003e\/themes\/\u003cstrong\u003e{テーマID}\u003c\/strong\u003e\/editor?previewPath=...\u003c\/code\u003e\u003c\/p\u003e\n\n\u003cp\u003e\u003ccode\u003e\/editor\u003c\/code\u003e までをそのまま使い、\u003ccode\u003e?\u003c\/code\u003e 以降を次に差し替えてアクセスします。\u003c\/p\u003e\n\n\u003cp\u003e\u003ccode\u003e?previewPath=%2Fsearch%3Fq%3Dtest%26type%3Darticle%26view%3Dblog-search\u003c\/code\u003e\u003c\/p\u003e\n\n\u003cp\u003eこれはURLエンコードされた \u003ccode\u003e\/search?q=test\u0026amp;type=article\u0026amp;view=blog-search\u003c\/code\u003e です。\u003ccode\u003eq\u003c\/code\u003e には結果が出るキーワードを入れておくと確認しやすくなります。\u003ccode\u003eview\u003c\/code\u003e の値は \u003ccode\u003etemplates\/search.{識別名}.json\u003c\/code\u003e のファイル名と一致させます。\u003c\/p\u003e\n\n\u003cp\u003e\u003cstrong\u003eストア名とテーマIDを入れると、開くべきURLがそのまま出ます。\u003c\/strong\u003e どちらも、いま開いているエディタのURL \u003ccode\u003e...\/store\/\u003cstrong\u003eここ\u003c\/strong\u003e\/themes\/\u003cstrong\u003eここ\u003c\/strong\u003e\/editor...\u003c\/code\u003e から読み取れます。\u003c\/p\u003e\n\n\u003cdiv class=\"bs-urlgen\" style=\"border:1px solid #dcdfe3;border-radius:10px;padding:18px;margin:18px 0;background:#f7f8fa;\"\u003e\n\u003cdiv style=\"display:flex;gap:14px;flex-wrap:wrap;margin-bottom:14px;\"\u003e\n\u003clabel style=\"font-size:13px;font-weight:700;\"\u003eストアのハンドル（.myshopify.com の前）\u003cbr\u003e\u003cinput class=\"bs-shop\" type=\"text\" value=\"your-store\" style=\"margin-top:4px;padding:7px 10px;border:1px solid #c9ced4;border-radius:6px;font:inherit;font-size:14px;min-width:220px;\"\u003e\u003c\/label\u003e\n\u003clabel style=\"font-size:13px;font-weight:700;\"\u003eテーマID\u003cbr\u003e\u003cinput class=\"bs-theme\" type=\"text\" value=\"000000000\" style=\"margin-top:4px;padding:7px 10px;border:1px solid #c9ced4;border-radius:6px;font:inherit;font-size:14px;min-width:160px;\"\u003e\u003c\/label\u003e\n\u003clabel style=\"font-size:13px;font-weight:700;\"\u003e識別名（view）\u003cbr\u003e\u003cinput class=\"bs-view\" type=\"text\" value=\"blog-search\" style=\"margin-top:4px;padding:7px 10px;border:1px solid #c9ced4;border-radius:6px;font:inherit;font-size:14px;min-width:160px;\"\u003e\u003c\/label\u003e\n\u003c\/div\u003e\n\u003ctextarea class=\"bs-out\" readonly rows=\"3\" style=\"width:100%;padding:10px;border:1px solid #c9ced4;border-radius:6px;font-family:SFMono-Regular,Menlo,monospace;font-size:13px;line-height:1.6;background:#fff;resize:vertical;\"\u003e\u003c\/textarea\u003e\n\u003cbutton class=\"bs-copy\" type=\"button\" style=\"margin-top:10px;padding:8px 18px;border:0;border-radius:999px;background:#1a1a1a;color:#fff;font:inherit;font-size:14px;font-weight:700;cursor:pointer;\"\u003eURLをコピー\u003c\/button\u003e\n\u003cspan class=\"bs-msg\" style=\"margin-left:10px;font-size:13px;color:#2e7d32;\"\u003e\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cscript\u003e\n(function(){\n  var roots = document.querySelectorAll('.bs-urlgen');\n  Array.prototype.forEach.call(roots, function(r){\n    if (r.dataset.ready) return;\n    r.dataset.ready = '1';\n    var shop = r.querySelector('.bs-shop'), theme = r.querySelector('.bs-theme'),\n        view = r.querySelector('.bs-view'), out = r.querySelector('.bs-out'),\n        btn = r.querySelector('.bs-copy'), msg = r.querySelector('.bs-msg');\n    function build(){\n      var p = '\/search?q=test\u0026type=article\u0026view=' + (view.value || 'blog-search');\n      out.value = 'https:\/\/admin.shopify.com\/store\/' + (shop.value || 'your-store')\n        + '\/themes\/' + (theme.value || '000000000')\n        + '\/editor?previewPath=' + encodeURIComponent(p);\n    }\n    [shop, theme, view].forEach(function(i){ i.addEventListener('input', build); });\n    btn.addEventListener('click', function(){\n      out.select(); out.setSelectionRange(0, 99999);\n      var ok = false;\n      try { ok = document.execCommand('copy'); } catch (e) {}\n      if (!ok \u0026\u0026 navigator.clipboard) { navigator.clipboard.writeText(out.value); ok = true; }\n      msg.textContent = ok ? 'コピーしました' : '';\n      setTimeout(function(){ msg.textContent = ''; }, 2000);\n    });\n    build();\n  });\n})();\n\u003c\/script\u003e\n\n\u003cp\u003e正しく開けていれば、エディタ左上のテンプレート名が \u003cstrong\u003esearch.blog-search\u003c\/strong\u003e に変わります。ここが「検索」のままなら、既定の検索テンプレートを開いています。\u003c\/p\u003e\n\n\u003cp\u003e\u003cstrong style=\"color:#e0301e;\"\u003e③ 結果ページにブロックを置く\u003c\/strong\u003e\u003c\/p\u003e\n\n\u003cp\u003e左サイドバーの Template にある「セクション」の下の \u003cstrong\u003eブロックを追加\u003c\/strong\u003e → カテゴリ「フォーム」 → \u003cstrong\u003eブログ内検索の結果\u003c\/strong\u003e。追加したら \u003ccode\u003e検索対象のブログ\u003c\/code\u003e で対象ブログを選び、\u003ccode\u003e1ページの取得件数\u003c\/code\u003e を設定して保存します。\u003cstrong\u003e識別名はここでは入力しません。\u003c\/strong\u003e 自分が置かれているテンプレートから自動で決まります。\u003c\/p\u003e\n\n\u003cp\u003e\u003cimg alt=\"手順② 結果ページをURLで開いて結果ブロックを置く\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0733\/0381\/8491\/files\/2026-09-27_6.png?v=1790491927\" class=\"zoomable-image\" style=\"max-width:100%;height:auto;\"\u003e\u003c\/p\u003e\n\n\u003cp\u003e\u003cstrong style=\"color:#e0301e;\"\u003e【注意】識別名のタイプミスは静かに失敗します。\u003c\/strong\u003e 存在しない \u003ccode\u003eview\u003c\/code\u003e を指定すると、エラーにはならず既定の \u003ccode\u003etemplates\/search.json\u003c\/code\u003e（通常の検索結果）が描画されます。\u003cstrong\u003eフォーム側の識別名とテンプレートのファイル名\u003c\/strong\u003eが一致しているか確認してください。\u003c\/p\u003e\n\n\u003ch3\u003eブログを複数にする場合\u003c\/h3\u003e\n\n\u003cp\u003e\u003cstrong\u003eテンプレートはブログごとに2つ必要です。\u003c\/strong\u003e 検索結果用だけでなく、\u003cstrong\u003eブログ一覧側も分ける\u003c\/strong\u003eのを忘れないでください。識別名はフォームブロックの設定として \u003ccode\u003etemplates\/blog.json\u003c\/code\u003e に保存されるため、複数のブログが同じ \u003ccode\u003eblog.json\u003c\/code\u003e を使っていると全ブログが同じ識別名を送り、どこから検索しても同じブログの結果が出ます。\u003c\/p\u003e\n\n\u003cp\u003eブログを1つ増やすときの手順です。\u003c\/p\u003e\n\n\u003col\u003e\n\u003cli\u003e\n\u003ccode\u003etemplates\/blog.{識別名}.json\u003c\/code\u003e を作り、\u003cstrong\u003eブログの設定画面（コンテンツ → ブログ記事 → ブログを管理 → 対象のブログ）でテーマテンプレートとして割り当てる\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003cli\u003eそのブログ一覧をテーマエディタで開き、フォームブロックを追加して \u003ccode\u003e送信先テンプレートの識別名（view）\u003c\/code\u003e に新しい識別名を入れる\u003c\/li\u003e\n\u003cli\u003e\n\u003ccode\u003etemplates\/search.{識別名}.json\u003c\/code\u003e を同じ識別名で作る（中身は既存のコピーでよい）\u003c\/li\u003e\n\u003cli\u003e手順②のURLの \u003ccode\u003eview\u003c\/code\u003e を新しい識別名に変えて開き、結果ブロックの \u003ccode\u003e検索対象のブログ\u003c\/code\u003e を新しいブログに設定する\u003c\/li\u003e\n\u003c\/ol\u003e\n\n\u003cp\u003e増えるのはテンプレートJSONだけで、\u003ccode\u003eblocks\/\u003c\/code\u003e の2ファイルは全ブログで共用します。\u003c\/p\u003e\n\n\u003cp\u003e\u003cimg alt=\"ブログごとに結果ページのテンプレートを用意する\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0733\/0381\/8491\/files\/2026-09-27_7.png?v=1790491928\" class=\"zoomable-image\" style=\"max-width:100%;height:auto;\"\u003e\u003c\/p\u003e\n\n\u003ch3\u003e注意点：ページングは絞り込み前の件数にかかる\u003c\/h3\u003e\n\n\u003cp\u003e\u003cstrong\u003eページ数はShopifyが返した全ブログ横断の件数で決まり、そこから他ブログ分を除いて表示します。\u003c\/strong\u003e このため、ページごとの表示件数が指定値に満たないことがあります。他ブログの記事が最終ページに集中すると、最後のページが0件になることもあります。\u003c\/p\u003e\n\n\u003cp\u003e実測例（対象ブログの記事1,672件・他ブログ46件のストアで「Flow」を検索）:\u003c\/p\u003e\n\n\u003cul\u003e\n\u003cli\u003eShopifyの検索ヒット総数: 171件\u003c\/li\u003e\n\u003cli\u003e対象ブログとして表示: 156件\u003c\/li\u003e\n\u003cli\u003e他ブログ分として除外: 15件\u003c\/li\u003e\n\u003cli\u003eページ毎の表示件数: 20, 20, 20, 20, 20, 20, 20, 16, 0\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003cp\u003e\u003cstrong\u003e緩和策:\u003c\/strong\u003e \u003ccode\u003e{% paginate %}\u003c\/code\u003e の件数を増やします（上限250件。超えると250に丸められます）。ページ数が減るぶん、空ページや極端に少ないページが出にくくなります。50件程度が実用的で、ブロックの設定から変更できます。\u003c\/p\u003e\n\n\u003cp\u003e\u003cimg alt=\"ページ数は絞り込む前の件数で決まる\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0733\/0381\/8491\/files\/2026-09-27_8.png?v=1790491927\" class=\"zoomable-image\" style=\"max-width:100%;height:auto;\"\u003e\u003c\/p\u003e\n\n\u003cp\u003e\u003cstrong style=\"color:#e0301e;\"\u003eやってはいけないこと:\u003c\/strong\u003e 「50件取得して先頭20件だけ表示」のような実装にすると、21件目以降がどのページにも出てこず、結果が欠落します。絞り込み後の全件をそのまま表示してください。\u003c\/p\u003e\n\n\u003ch3\u003e補足\u003c\/h3\u003e\n\n\u003cul\u003e\n\u003cli\u003e\n\u003cstrong\u003eなぜ \u003ccode\u003eview\u003c\/code\u003e を使うのか\u003c\/strong\u003e：Liquid は任意のクエリパラメータを読めません。\u003ccode\u003erequest\u003c\/code\u003e オブジェクトが持つのは \u003ccode\u003edesign_mode\u003c\/code\u003e \/ \u003ccode\u003evisual_preview_mode\u003c\/code\u003e \/ \u003ccode\u003epage_type\u003c\/code\u003e \/ \u003ccode\u003ehost\u003c\/code\u003e \/ \u003ccode\u003eorigin\u003c\/code\u003e \/ \u003ccode\u003epath\u003c\/code\u003e \/ \u003ccode\u003elocale\u003c\/code\u003e だけで、クエリ文字列は含まれません。\u003ccode\u003e\/search?blog=news\u003c\/code\u003e のような独自パラメータを送っても受け取る口がないため、Shopify 自身がテンプレート選択に使う \u003ccode\u003eview\u003c\/code\u003e を経由しています\u003c\/li\u003e\n\u003cli\u003e検索対象は記事の本文・タイトル・タグです。タグに年月などを入れておけば、それでも検索できます\u003c\/li\u003e\n\u003cli\u003eShopifyアプリ「Search \u0026amp; Discovery」の絞り込みフィルターは商品専用で、ブログ記事には使えません\u003c\/li\u003e\n\u003cli\u003e結果ページ側のフォームは設定で非表示にできます。既定では表示しており、結果画面からそのまま再検索できます\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003ch3\u003eサンプルコード\u003c\/h3\u003e\n\n\u003cp\u003e3ファイルの全文を収録しています。購入後にご確認いただけます。\u003c\/p\u003e\n","brand":"STORE DOJO","offers":[{"title":"Default Title","offer_id":50529036271867,"sku":null,"price":0.0,"currency_code":"JPY","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0733\/0381\/8491\/files\/2026-09-27.png?v=1790433056","url":"https:\/\/store-dojo.com\/products\/2026-09-27","provider":"STORE DOJO","version":"1.0","type":"link"}