TECH JOURNAL

eBay Browse API の検索精度を、パラメータ設計で高める

ShareXB!
eBay Browse API の検索精度を、パラメータ設計で高める
目次

はじめに

eBay の Browse API(/buy/browse/v1/item_summary/search)は、出品検索・商品詳細取得の中心となる API だ。越境 EC で日本向けに eBay 出品を運用するとき、検索パラメータの設計次第で一覧に出てくる商品の質が大きく変わる。

よくある課題はこういったものだ。

  • キーワード検索だけだと関連度の低い商品が混ざり、顧客体験が落ちる
  • コンディション・配送地域を絞り込まないと、日本に届かない出品や中古品が混入する
  • カテゴリ横断でヒットしすぎて、本当に比較すべき商品群が見えにくい

これらをまとめて対処するのが filter / aspect_filter / sort / fieldgroups の組み合わせ設計だ。

検索精度を決める 3 要素

Browse API の検索精度は次の 3 層で制御する。

  • q × category_ids — キーワードとカテゴリ ID の併用で母集団を絞る。カテゴリを指定しないと全カテゴリが対象になり、ノイズが増える
  • filter — 価格帯・コンディション・配送先を制御して、明らかに対象外のものを除く
  • aspect_filter — カテゴリ固有の属性(ブランド・サイズ・素材など)で商品属性を絞る

3 層を順に適用し、母集団を小さくしてから sort で並べ替えるのが基本の流れだ。

実装パターン 1: 基本リクエストの組み立て

まず q と category_ids だけのシンプルな検索から始める。

const BASE_URL = "https://api.ebay.com/buy/browse/v1/item_summary/search"
 
async function searchItems(params: URLSearchParams, token: string) {
  const res = await fetch(`${BASE_URL}?${params}`, {
    headers: {
      Authorization: `Bearer ${token}`,
      "X-EBAY-C-MARKETPLACE-ID": "EBAY_US", // 対象マーケットプレイス
      "X-EBAY-C-ENDUSERCTX": "contextualLocation=country=JP", // エンドユーザーのロケーション
    },
  })
  if (!res.ok) throw new Error(`Browse API error: ${res.status}`)
  return res.json()
}
 
const params = new URLSearchParams({
  q: "vintage denim jacket",
  category_ids: "3002", // Men's Clothing
  limit: "50",
  offset: "0",
})
const result = await searchItems(params, accessToken)

X-EBAY-C-ENDUSERCTX ヘッダに country=JP を渡すと、配送可否の文脈が日本基準になる。省略するとデフォルト(EBAY_US の場合は米国)が使われるため、日本向け開発では必ず指定したい。

実装パターン 2: filter 構文で除外条件を積む

filter は複数条件をカンマ区切りで並べ、AND 条件として機能する。

// price:[10..50] — 価格帯(ドル)
// conditions:{NEW|LIKE_NEW} — コンディション
// deliveryCountry:JP — 日本への配送あり
// itemLocationCountry:JP — 出品者が日本にいる(越境 EC では外す場合も)
const params = new URLSearchParams({
  q: "vintage denim jacket",
  category_ids: "3002",
  filter: [
    "price:[10..50]",
    "conditions:{NEW|LIKE_NEW}",
    "deliveryCountry:JP",
  ].join(","),
  priceCurrency: "USD",
  limit: "50",
  offset: "0",
})

条件の構文はフィールドごとに異なる。主なパターンを整理しておく。

filter 条件書き方の例備考
価格帯price:[10..50]priceCurrency と併用
上限なしprice:[10..]ピリオド 2 つで範囲の片方を省略
コンディションconditions:{NEW} または {NEW|LIKE_NEW}| で OR
配送先deliveryCountry:JPISO 3166-1 alpha-2
出品者所在国itemLocationCountry:JP日本出品者に絞る場合
送料無料maxDeliveryCost:00 を指定で無料のみ

実装パターン 3: aspect_filter でカテゴリ属性を絞る

aspect_filter はカテゴリ固有の属性(アスペクト)で絞り込む。どのアスペクト名・値が使えるかは category_id によって異なるため、事前に /buy/browse/v1/item_aspect_for_category エンドポイントで取得しておく必要がある。

// aspect_filter の書き方: aspectName:{value1|value2}
// 複数のアスペクトはカンマ区切り(AND)
const params = new URLSearchParams({
  q: "denim jacket",
  category_ids: "3002",
  filter: "conditions:{NEW|LIKE_NEW},deliveryCountry:JP",
  aspect_filter: [
    "Brand:{Levi's|Wrangler}",
    "Size:{M|L|XL}",
    "Color:{Blue|Dark Blue}",
  ].join(","),
  limit: "50",
  offset: "0",
})

aspect_filter の値は 大文字・小文字・スペースを含むカテゴリ定義のままの文字列でなければヒットしない。Levi's を levis と書くと 0 件になる。アスペクト値の一覧も /item_aspect_for_category から取得して、そのまま使うのが安全だ。

実装パターン 4: sort と fieldgroups の最適化

sort は母集団を絞った後で効かせる。デフォルトは sort=BEST_MATCH(関連度順)で、価格・新着・距離などに切り替えられる。

// sort の主な選択肢
// BEST_MATCH (デフォルト) — eBay アルゴリズムによる関連度
// PRICE — 価格昇順
// -PRICE — 価格降順
// NEWLY_LISTED — 新着順
// ENDING_SOONEST — 終了間近 (オークション形式)
const params = new URLSearchParams({
  q: "denim jacket",
  category_ids: "3002",
  filter: "conditions:{NEW},deliveryCountry:JP",
  sort: "PRICE",
  fieldgroups: "MATCHING_ITEMS,ASPECT_REFINEMENTS",
  limit: "50",
  offset: "0",
})

fieldgroups はレスポンスに含めるフィールドグループを指定する。デフォルトの MATCHING_ITEMS に加えて ASPECT_REFINEMENTS を追加すると、絞り込み候補のアスペクト一覧をフロント側に返せる。ファセット検索 UI を作る場合に使う。不要なフィールドグループを外せばレスポンスサイズが小さくなり、レイテンシも改善する。

実装パターン 5: ページネーションと上限管理

Browse API の search エンドポイントは offset + limit 方式でページネーションを行う。

async function* paginateSearch(
  baseParams: URLSearchParams,
  token: string,
  pageSize = 50,
) {
  const ABSOLUTE_LIMIT = 10_000 // offset + limit の合計上限
  let offset = 0
 
  while (offset < ABSOLUTE_LIMIT) {
    const params = new URLSearchParams(baseParams)
    params.set("limit", String(pageSize))
    params.set("offset", String(offset))
 
    const data = await searchItems(params, token)
    const items: unknown[] = data.itemSummaries ?? []
 
    if (items.length === 0) break
    yield items
 
    offset += items.length
 
    // total が取得済み件数以下なら終了
    if (data.total <= offset) break
  }
}
 
// 使い方
for await (const page of paginateSearch(baseParams, accessToken)) {
  for (const item of page) {
    // 商品を処理
  }
}

注意点は 2 つある。まず limit の最大値は 200(/item_summary/search の場合)。201 以上を指定するとエラーになる。もう一つは offset + limit の合計が 10,000 を超えるリクエストは拒否される仕様だ。10,000 件を超える結果セットが必要なときは、filter や category_ids でさらに母集団を分割して並列検索するアプローチが現実的だ。

実装パターン 6: 検索ログからの継続改善

実運用では、検索パラメータを固定するのではなく ログを分析して継続的に改善するサイクルを回すのが効果的だ。

type SearchLog = {
  query: string
  filter: string
  aspectFilter: string
  total: number
  firstPageItemCount: number
  searchedAt: Date
}
 
async function searchWithLogging(
  params: URLSearchParams,
  token: string,
): Promise<{ data: unknown; log: SearchLog }> {
  const start = Date.now()
  const data = await searchItems(params, token)
 
  const log: SearchLog = {
    query: params.get("q") ?? "",
    filter: params.get("filter") ?? "",
    aspectFilter: params.get("aspect_filter") ?? "",
    total: data.total ?? 0,
    firstPageItemCount: (data.itemSummaries ?? []).length,
    searchedAt: new Date(start),
  }
 
  // total が 0 のクエリや firstPageItemCount が極端に少ない場合はアラート対象
  if (log.total === 0 || log.firstPageItemCount < 5) {
    console.warn("low-yield search", log)
  }
 
  return { data, log }
}

total === 0 のクエリは aspect_filter の値ミスマッチか、filter の組み合わせが厳しすぎることが多い。ログを集めて、total の分布とよく使われるアスペクト値を定期的に確認する習慣をつけておくと、パラメータ設計を段階的に改善できる。

まとめ

課題対策
関連度の低い商品が混入するq × category_ids で母集団を絞る
日本に届かない出品が出るfilter=deliveryCountry:JP を必ず付ける
コンディション混在filter=conditions:{NEW|LIKE_NEW} で制限
カテゴリ属性の絞り込みが効かないaspect_filter の値はカテゴリ定義のまま使う
レスポンスが重いfieldgroups で不要グループを外す
10,000 件超の全件取得が詰まるfilter で母集団を分割して並列検索
パラメータを改善する根拠がないtotal / firstPageItemCount を記録してログ分析
ShareXB!

この記事を書いた人

渡部 誠也

執行役員 / CTO

独立系 SIer で Web・組み込み・基幹システムの開発を経験し、2017 年に illustrious へ。CTO としてシステム開発事業を立ち上げ、要件定義からコーディングまで一貫して担う。EC に特化した Web アプリケーションを数多く手がける。

ECの業務やシステムについて、
ご相談ください。

いまの運用で困っていること、実現したいことから、一緒に整理します。