mcpField
S
search-autocomplete

search-autocomplete

github.com/finsilabs开发6083 次安装6 天前更新
代码仓库

关于 search-autocomplete

用于在电商店面实现输入即搜的技能,面向为现有或定制店面添加搜索建议的开发者。内容结合请求防抖、模糊匹配、商品推广规则和结构化下拉列表。

主要功能

  1. 01搜索请求防抖
  2. 02模糊匹配与错字处理
  3. 03商品和类别建议
  4. 04同义词与商品推广规则
  5. 05无障碍下拉列表模式

适用场景

  1. 01为店面添加输入即搜
  2. 02帮助买家通过错字找到商品
  3. 03在建议中推广指定商品
  4. 04支持多语言搜索同义词

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/finsilabs/awesome-ecommerce-skills --skill search-autocomplete

安装后在 Claude Code 中输入/search-autocomplete确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

tile.json
evals/algolia-index-configuration-and-merchand/
criteria.json
task.md
evals/backend-autocomplete-endpoint/
criteria.json
task.md
evals/frontend-autocomplete-component/
criteria.json
task.md

详细介绍

搜索自动补全

概述

实现一种即输即搜体验,让商品建议、类别和内容随着购物者输入而显示。结合客户端防抖与服务器端模糊匹配,应用商品推广规则(加权、置顶、同义词),并呈现结构化下拉列表,以带来可衡量的转化率提升。

何时使用此技能

  • 购物者仅通过浏览导航难以找到商品时
  • 站内搜索点击率低于搜索次数的 30% 时
  • 为现有搜索端点添加即输即搜体验时
  • 集成第三方搜索服务(Algolia、Elasticsearch、Typesense)时
  • 实施商品推广规则,以便在结果中提升推广商品的排名时
  • 为需要同义词和语音匹配的多语言店面提供支持时

核心说明

第 1 步:确定商家的平台并选择合适的方案
平台推荐方案原因
Shopify安装 Search & Discovery 应用(免费,由 Shopify 提供)来配置同义词和加权,再安装 Searchie 或 Boost Commerce 应用以使用完整的自动补全下拉列表Search & Discovery 通过同义词和商品加权改进 Shopify 内置搜索;Boost Commerce(每月 19 美元)可添加样式完整的自动补全下拉列表,包含类别结果和商品推广规则
WooCommerce安装 FiboSearch – AJAX Search for WooCommerce(免费/付费),或安装 SearchWP 并搭配 SearchWP Live Search 扩展FiboSearch 可为 WooCommerce 搜索栏添加即时 AJAX 自动补全下拉列表,显示商品图片、价格和类别结果,无需自定义代码
BigCommerce在 Storefront → Search 设置中启用 Search Suggestions,并安装 Klevu Smart Search 或 Searchspring 以获得高级自动补全BigCommerce 的原生搜索仅提供基础自动补全;Klevu(每月 449 美元起)和 Searchspring 可添加 AI 驱动的自动补全、同义词管理和商品推广规则
自定义/无头架构使用 Algolia InstantSearch.js(推荐)或可自托管的 Typesense 构建;实现防抖输入、用于处理竞态条件的 AbortController,以及 ARIA combobox 模式Algolia 提供出色的开发者体验,并设有慷慨的免费套餐(每月 10K 次搜索);Typesense 是可自托管的替代方案
第 2 步:在平台上配置搜索自动补全

Shopify

Search & Discovery 应用(必备基础配置 — 免费):

  1. 从 Shopify App Store 安装 Search & Discovery
  2. 前往 Apps → Search & Discovery → Synonyms,添加业务同义词:
    • 双向:「sneakers」↔「trainers」↔「shoes」
    • 单向:「tv」→「television」、「flat screen」
  3. 在 Boosts 下,将高优先级商品或系列置顶,使其针对特定查询优先显示
  4. 在 Filter settings 下,配置与搜索结果一同显示的筛选属性
  5. 此应用可改进 Shopify 原生的预测搜索 API,该 API 被所有 OS2.0 主题搜索栏使用

Boost Commerce 应用(完整自动补全下拉列表):

  1. 从 Shopify App Store 安装 Boost Commerce – Product Filter & Search
  2. 在应用控制面板中配置 Instant Search 弹出窗口:
    • 启用建议中的商品图片和价格
    • 添加类别/系列建议
    • 配置商品结果数量(建议为 5–8 个)
  3. 在应用中设置 Merchandising rules:提升新品的排名、将畅销商品置顶,并在建议中排除缺货商品
  4. 在 Design 设置中自定义弹出窗口的外观,使其与主题配色相匹配

WooCommerce

FiboSearch(推荐 — 提供免费套餐):

  1. 从 WordPress.org 安装 FiboSearch – AJAX Search for WooCommerce
  2. 前往 FiboSearch → Settings → General
  3. 配置建议中显示的内容:
    • Products:名称、SKU、标签(全部启用可获得最佳效果)
    • Categories:启用以显示分类建议
    • Pages/Posts:如果有博客内容,请启用
  4. 将 Fuzzy Search 设置为 On — 这可以处理诸如 “adids” → “Adidas” 的拼写错误
  5. 在 Appearance 下配置下拉菜单布局:产品图片 + 名称 + 价格,或仅显示精简文本
  6. FiboSearch 会替换 WooCommerce 默认搜索小工具 — 它适用于标准搜索输入框、Elementor 搜索小工具和大多数主题搜索栏

SearchWP + Live Search 扩展:

  1. 安装 SearchWP(付费,$99/年起),以便高级控制索引
  2. 安装 SearchWP Live Search 扩展,实现实时自动补全
  3. 在 SearchWP 管理后台配置要索引的产品字段及其权重(名称 > SKU > 描述)
  4. 在索引中启用自定义字段和产品属性,以便按规格搜索

BigCommerce
  1. 在 BigCommerce 控制面板中前往 Storefront → Search
  2. 在 Search Suggestions 下,将 Products、Categories 和 Brands 启用为建议类型
  3. 设置要显示的建议数量(产品建议设为 5–8 条)
  4. 配置 Search as you type,使其在输入 2 个字符后开始

Klevu Smart Search(高级自动补全):

  1. 从 BigCommerce App Marketplace 安装
  2. 在 Klevu 控制面板中配置同义词组和加权规则
  3. Klevu 的自动补全下拉菜单会自动显示产品图片、价格、分类和热门搜索
  4. 为特定查询在搜索下拉菜单中添加自定义横幅(例如,有人搜索 “dress” 时显示 “Summer Sale” 横幅)

自定义 / Headless

使用 AbortController 的防抖输入钩子(防止竞态条件):

// useSearchAutocomplete.js
import { useState, useEffect, useRef, useCallback } from 'react';

function debounce(fn, delay) {
  let timer;
  return (...args) => { clearTimeout(timer); timer = setTimeout(() => fn(...args), delay); };
}

export function useSearchAutocomplete(minChars = 2) {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState({ products: [], categories: [], suggestions: [] });
  const [loading, setLoading] = useState(false);
  const abortRef = useRef(null);

  const fetchSuggestions = useCallback(
    debounce(async (q) => {
      if (q.length < minChars) { setResults({ products: [], categories: [], suggestions: [] }); return; }
      if (abortRef.current) abortRef.current.abort();
      abortRef.current = new AbortController();
      setLoading(true);
      try {
        const res = await fetch(`/api/search/autocomplete?q=${encodeURIComponent(q)}&limit=5`,
          { signal: abortRef.current.signal });
        setResults(await res.json());
      } catch (err) { if (err.name !== 'AbortError') console.error(err); }
      finally { setLoading(false); }
    }, 250),
    [minChars]
  );

  useEffect(() => { fetchSuggestions(query); }, [query, fetchSuggestions]);
  return { query, setQuery, results, loading };
}

无障碍组合框下拉菜单(ARIA combobox + listbox 模式):

// SearchAutocomplete.jsx
import DOMPurify from 'dompurify'; // sanitize server-provided highlight HTML

export function SearchAutocomplete() {
  const { query, setQuery, results, loading } = useSearchAutocomplete();
  const [activeIndex, setActiveIndex] = useState(-1);
  const inputRef = useRef(null);
  const allItems = [...results.categories, ...results.products];
  const isOpen = query.length >= 2 && allItems.length > 0;

  function handleKeyDown(e) {
    if (e.key === 'ArrowDown') { e.preventDefault(); setActiveIndex(i => Math.min(i + 1, allItems.length - 1)); }
    if (e.key === 'ArrowUp') { e.preventDefault(); setActiveIndex(i => Math.max(i - 1, -1)); }
    if (e.key === 'Enter' && activeIndex >= 0) window.location.href = allItems[activeIndex].url;
    if (e.key === 'Escape') { inputRef.current.blur(); setActiveIndex(-1); }
  }

  return (
    <div role="combobox" aria-expanded={isOpen} aria-haspopup="listbox" aria-owns="autocomplete-list">
      <input ref={inputRef} type="search" value={query}
        onChange={e => { setQuery(e.target.value); setActiveIndex(-1); }}
        onKeyDown={handleKeyDown}
        aria-autocomplete="list" aria-controls="autocomplete-list"
        aria-activedescendant={activeIndex >= 0 ? `item-${activeIndex}` : undefined}
        placeholder="Search products..." />
      {loading && <span aria-live="polite" className="sr-only">Loading suggestions</span>}
      {isOpen && (
        <ul id="autocomplete-list" role="listbox" className="autocomplete-dropdown">
          {results.categories.map((cat, i) => (
            <li key={cat.url} id={`item-${i}`} role="option" aria-selected={activeIndex === i}>
              <a href={cat.url}>Category: {cat.name} ({cat.product_count})</a>
            </li>
          ))}
          {results.products.map((product, i) => {
            const idx = i + results.categories.length;
            const highlighted = DOMPurify.sanitize(product._highlightResult?.name?.value ?? product.name);
            return (
              <li key={product.objectID} id={`item-${idx}`} role="option" aria-selected={activeIndex === idx}>
                <a href={product.url} className="product-suggestion">
                  <img src={product.image} alt="" width="40" height="40" />
                  <span dangerouslySetInnerHTML={{ __html: highlighted }} />
                  <span>${product.price}</span>
                </a>
              </li>
            );
          })}
          <li><a href={`/search?q=${encodeURIComponent(query)}`}>View all results for "{query}"</a></li>
        </ul>
      )}
    </div>
  );
}

Algolia 索引配置(拼写容错 + 同义词 + 商品推广):

await searchClient.setSettings({
  indexName: 'products',
  indexSettings: {
    searchableAttributes: ['name', 'brand', 'category', 'description'],
    customRanking: ['desc(popularity_score)', 'desc(conversion_rate)'],
    typoTolerance: 'min',
    minWordSizefor1Typo: 5,
    synonyms: [
      { objectID: 'shoes', type: 'synonym', synonyms: ['shoes', 'sneakers', 'footwear', 'trainers'] },
    ],
    optionalFilters: ['is_featured:true<score=2>', 'in_stock:true<score=1>'],
  },
});

最佳实践

  • 防抖设为 200–300 ms — 兼顾响应速度和服务器负载;不要低于 150 ms
  • 取消正在执行的请求 — 使用 AbortController,避免用户快速输入时出现竞态条件
  • 突出显示匹配词 — 用 <mark> 包裹匹配的子字符串,让购物者了解结果出现的原因;渲染前先清理服务器提供的 HTML
  • 显示“查看所有结果”链接 — 始终提供跳转到完整搜索结果页的选项
  • 缓存常用查询 — 大多数商店的高频查询数量较少;LRU 缓存可以显著降低后端负载
  • 跟踪无结果的查询 — 记录返回零结果的查询;这些查询直接表明存在同义词缺失或目录空缺
  • 将 minChars 设为 2 — 单字符查询会产生噪声,且无法带来转化价值

常见问题

问题解决方案
用户快速输入时结果过时使用 AbortController 在发出新请求前取消上一个请求
下拉菜单显示在粘性页眉后面在下拉菜单上显式设置 z-index;如果位于 overflow:hidden 祖先元素内,请使用 portal
重新渲染后键盘导航焦点丢失在组件状态中跟踪 activeIndex,而不是 DOM 焦点;每次渲染时重新应用 aria-activedescendant
模糊匹配返回无关结果在 Algolia 中配置 minWordSizefor1Typo: 5,或在 Elasticsearch 中配置 prefix_length: 2,要求模糊匹配开始前先有足够可靠的词干
商品推广规则未生效查询与条件模式匹配时才会触发规则 — 对于部分匹配,请使用 anchoring: 'contains',而不是 is

相关技能

  • @faceted-navigation
  • @product-page-design
  • @accessibility-commerce
  • @storefront-theming

评论

支持 Markdown