よくある質問
統合でつまずきやすい順に並べています。
契約・権限
契約しているのに 403 と plan_required が返ります
contract=v1 は Pro プラン以上でご利用いただけます。Basic・Free では 403 になります。
プランを上げた直後であれば、Shopify 側の課金承認が完了しているかご確認ください。 承認前は前のプランのままです。
なお contract=v1 を外すと 403 にはなりませんが、返るのはアプリ内部のレスポンスで、 予告なく形が変わります。仕様として使わないでください。
一時的なエラーと契約切れを区別したい
区別できるように分けてあります。
| 状況 | ステータス | 目印 |
|---|---|---|
| 契約が足りない | 403 | {"code": "plan_required"} |
| 障害・準備中 | 503 / 200 | degraded: true(通常の形で返る) |
plan_required を受けたら「検索できません」ではなく、契約の問題として扱ってください。 買い物客にエラーを見せるより、テーマ標準の検索へ寄せるほうが実害が小さい場面が多いはずです。
一方 degraded は一時的なものなので、時間をおけば戻ります。
呼び出し
自社のサーバや Hydrogen から呼べますか
できません。 このエンドポイントは Shopify App Proxy 経由で、ストア自身のドメイン上でのみ 動作します。CORS ヘッダを付けていないため、他ドメインのページからは応答を読めません。
curl などサーバ側からは到達しますが、ストア外での利用は現在サポートしていません。 ご要望があればお知らせください。
curl では返るのに、ブラウザだと読めません
上記のとおり CORS です。そのストアのページ上の JavaScript から呼んでください。 ローカル開発でストアと別のオリジンからテストしている場合も同じ理由で読めません。
contract=v1 を type=suggest に付けたら 400 になります
v1 が定めるのは確定検索(type=search)のみです。入力補完のレスポンス形は 仕様として書いていないため、契約としては返しません(unsupported_contract_type)。
入力補完は contract なしで呼べますが、その形は予告なく変わります。 必要であればお知らせください。
レスポンス
導入直後、total: 0 で何も返りません
degraded を確認してください。新規ストアは導入初日に必ずこの経路を通ります。
{
"degraded": true,
"degraded_reason": "paid_sync_pending",
"total": 0,
"results": []
}初回の商品同期が終わるまでの状態です。degraded を見ていない実装は 「入れた直後は動かない」ように見えます。
管理画面の検索分析が空のままです
原因は2つのどちらかです。どちらも検索自体は正常に動くため気づきにくい箇所です。
① session_id を送っていない。 検索リクエストに session_id が無いと、 買い物客の検索ではないと判断して分析に計上しません。
② Shopify.analytics.publish を実装していない。 まるっと検索は商品カードを描画 しないため、クリック率・検索経由売上はこのイベントでしか取得できません。 measurement_proof を含めて publish してください。
詳しくは仕様の7章をご覧ください。
?variant= を付けても、バリエーションが選択されません
variants[].id は 数値の ID("44001")です。GID を渡すと Shopify は エラーにせず黙って無視します。
// ✅
`/products/${item.handle}?variant=${variant.id}`;
// ❌ GID は無視される
`/products/${item.handle}?variant=gid://shopify/ProductVariant/44001`;カート追加(Cart AJAX API)も同じく数値です。GID が必要な場合は "gid://shopify/ProductVariant/" + variant.id で組み立ててください。
価格が、買い物客の見ている通貨と違います
price_min / price_max はショップの基準通貨です。Shopify Markets で多通貨展開 されている場合、表示通貨とは一致しません。
御社側で換算していただくか、価格の描画のみ Shopify の Storefront API から取得して ください。多通貨対応のご要望があればお知らせください。
仕様に無いフィールドが欲しいです
追加は v1 のまま安全に行えます(既存の実装は影響を受けません)。必要なものが あればお知らせください。
変えられないのは、公開済みフィールドの名前・型・意味の変更と削除です。
絞り込み
filter_metafield が効かず、全件返ります
管理画面で「絞り込みに使う」を有効にしていないメタフィールドは、エラーにならず 無視されます(設定を切り替えたあとも古いURLが共有され続けるための仕様です)。
開発中はキー名の打ち間違いでも同じ症状になります。まずレスポンスの facets.metafields[].name と一致しているかご確認ください。
q=* でタグやバリエーションのファセットが返りません
全件ブラウズは商品テーブルだけを読む別経路のため、facets.tags / content_types / variant_options は常に空になります(キーは存在します)。
同じ理由で filter_content_type=article も常に0件です。記事・ページを一覧したい 場合は、検索語を伴う type=search をご利用ください。
その他の絞り込み(ベンダー・価格・メタフィールド等)は q=* でも効きます。
ページング・負荷
「もっと見る」が消えず、同じ商品が増え続けます
offset には 2,000 の上限があり、超えた指定は 2,000 に丸められます。 next < data.total だけで判定していると、上限に達したあとも同じページを 取得し続けます。
const MAX_OFFSET = 2000;
if (next < data.total && next < MAX_OFFSET) {
/* 次を取得 */
}429 が返ります
10秒あたりのリクエスト数に上限があります。入力補完をデバウンスなしで呼ぶと、 訪問者単位の上限(40/10秒)に容易に達します。250〜300ms のデバウンスを推奨します。
なお全ストア合計の上限もあるため、自社のリクエスト数だけからは予測できない 429 が理論上あり得ます(実運用で到達したことはありません)。負荷試験の予定がある場合は 事前にご連絡ください。
入力が速いと、古い検索結果が表示されます
レスポンスの query / offset / limit / sort はリクエスト値のエコーバック です。いま表示すべき条件と一致しないレスポンスは破棄してください。
レスポンスが遅く感じます
レスポンスヘッダの Server-Timing: marutto;dur=◯◯ が、**まるっと検索側の処理時間 (ミリ秒)**です。全体の所要時間と比べて、どこが遅いかを切り分けられます。
dur が小さいのに全体が遅い場合、原因はネットワーク経路です。
開発
本番前に試したい
開発ストアにインストールし、Pro プランを適用してお試しください。 本番ストアと同じ URL・同じ形で応答します。
まず動くものが見たい
参照実装をそのままテーマに置けば動きます。 描画は御社のデザインに書き換える前提ですが、書き換えないでいただきたい箇所が3つ あります(contract=v1・degraded・Shopify.analytics.publish の2つ)。
その他
webサイトのフォーム、またはメールにてお問い合わせください。