关于 search-autocomplete
用于在电商店面实现输入即搜的技能,面向为现有或定制店面添加搜索建议的开发者。内容结合请求防抖、模糊匹配、商品推广规则和结构化下拉列表。
主要功能
- 01搜索请求防抖
- 02模糊匹配与错字处理
- 03商品和类别建议
- 04同义词与商品推广规则
- 05无障碍下拉列表模式
适用场景
- 01为店面添加输入即搜
- 02帮助买家通过错字找到商品
- 03在建议中推广指定商品
- 04支持多语言搜索同义词
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ finsilabs/ awesome-ecommerce-skills --skill search-autocomplete安装后在 Claude Code 中输入/search-autocomplete确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
tile.jsonevals/algolia-index-configuration-and-merchand/criteria.jsontask.mdevals/backend-autocomplete-endpoint/criteria.jsontask.mdevals/frontend-autocomplete-component/criteria.jsontask.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 应用(必备基础配置 — 免费):
- 从 Shopify App Store 安装 Search & Discovery
- 前往 Apps → Search & Discovery → Synonyms,添加业务同义词:
- 双向:「sneakers」↔「trainers」↔「shoes」
- 单向:「tv」→「television」、「flat screen」
- 在 Boosts 下,将高优先级商品或系列置顶,使其针对特定查询优先显示
- 在 Filter settings 下,配置与搜索结果一同显示的筛选属性
- 此应用可改进 Shopify 原生的预测搜索 API,该 API 被所有 OS2.0 主题搜索栏使用
Boost Commerce 应用(完整自动补全下拉列表):
- 从 Shopify App Store 安装 Boost Commerce – Product Filter & Search
- 在应用控制面板中配置 Instant Search 弹出窗口:
- 启用建议中的商品图片和价格
- 添加类别/系列建议
- 配置商品结果数量(建议为 5–8 个)
- 在应用中设置 Merchandising rules:提升新品的排名、将畅销商品置顶,并在建议中排除缺货商品
- 在 Design 设置中自定义弹出窗口的外观,使其与主题配色相匹配
WooCommerce
FiboSearch(推荐 — 提供免费套餐):
- 从 WordPress.org 安装 FiboSearch – AJAX Search for WooCommerce
- 前往 FiboSearch → Settings → General
- 配置建议中显示的内容:
- Products:名称、SKU、标签(全部启用可获得最佳效果)
- Categories:启用以显示分类建议
- Pages/Posts:如果有博客内容,请启用
- 将 Fuzzy Search 设置为 On — 这可以处理诸如 “adids” → “Adidas” 的拼写错误
- 在 Appearance 下配置下拉菜单布局:产品图片 + 名称 + 价格,或仅显示精简文本
- FiboSearch 会替换 WooCommerce 默认搜索小工具 — 它适用于标准搜索输入框、Elementor 搜索小工具和大多数主题搜索栏
SearchWP + Live Search 扩展:
- 安装 SearchWP(付费,$99/年起),以便高级控制索引
- 安装 SearchWP Live Search 扩展,实现实时自动补全
- 在 SearchWP 管理后台配置要索引的产品字段及其权重(名称 > SKU > 描述)
- 在索引中启用自定义字段和产品属性,以便按规格搜索
BigCommerce
- 在 BigCommerce 控制面板中前往 Storefront → Search
- 在 Search Suggestions 下,将 Products、Categories 和 Brands 启用为建议类型
- 设置要显示的建议数量(产品建议设为 5–8 条)
- 配置 Search as you type,使其在输入 2 个字符后开始
Klevu Smart Search(高级自动补全):
- 从 BigCommerce App Marketplace 安装
- 在 Klevu 控制面板中配置同义词组和加权规则
- Klevu 的自动补全下拉菜单会自动显示产品图片、价格、分类和热门搜索
- 为特定查询在搜索下拉菜单中添加自定义横幅(例如,有人搜索 “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