需求背景
网站的搜索框是用户和网站交互的一种途径。用户使用搜索框的时候往往是带有目的性的。比如想买春天的裙子,比如想买带花纹的上衣。这种带有明确目的的流量是十分珍贵的。如果加以正确的引流,往往可能会带来转化。除此之外,这里还是站长对网站进行营销的另外一个入口。比如现在网站想强烈推荐某个风格或者季节的衣服,那么直接可以在这里开入口,将站内的引流灵活运用。至于行业热搜词等,因站而异。可以参考竞品网站或者从google trending里面去找。
现存的原生的shopify搜索框比较素,功能也比较单一如何能够将上面的想法融入到我们的shopify网站是当下应该考虑的问题。
1. 代码更新
由于不同主题的搜索框实现原理都不一样,重口难调。所以博主这边只对原生的Dawn主题进行优化,大家自行去进行改版即可。原理就是,在加载搜索数据的地方给它塞进去我们设定好的关键热搜词。
predictive-search.js
class PredictiveSearch extends HTMLElement {constructor() {super();this.cachedResults = {};this.input = this.querySelector('input[type="search"]');this.predictiveSearchResults = this.querySelector('[data-predictive-search]');this.isOpen = false;this.setupEventListeners();}setupEventListeners() {const form = this.querySelector('form.search');form.addEventListener('submit', this.onFormSubmit.bind(this));this.input.addEventListener('input', debounce((event) => {this.onChange(event);}, 300).bind(this));this.input.addEventListener('focus', this.onFocus.bind(this));this.addEventListener('focusout', this.onFocusOut.bind(this));this.addEventListener('keyup', this.onKeyup.bind(this));this.addEventListener('keydown', this.onKeydown.bind(this));}getQuery() {return this.input.value.trim();}onChange() {const searchTerm = this.getQuery();if (!searchTerm.length) {this.close(true);return;}this.getSearchResults(searchTerm);}onFormSubmit(event) {if (!this.getQuery().length || this.querySelector('[aria-selected="true"] a')) event.preventDefault();}onFocus() {const searchTerm = this.getQuery();this.open();if (!searchTerm.length) return;if (this.getAttribute('results') === 'true') {this.open();} else {this.getSearchResults(searchTerm);}}onFocusOut() {setTimeout(() => {if (!this.contains(document.activeElement)) this.close();})}onKeyup(event) {if (!this.getQuery().length) this.close(true);event.preventDefault();switch (event.code) {case 'ArrowUp':this.switchOption('up')break;case 'ArrowDown':this.switchOption('down');break;case 'Enter':this.selectOption();break;}}onKeydown(event) {// Prevent the cursor from moving in the input when using the up and down arrow keysif (event.code === 'ArrowUp' ||event.code === 'ArrowDown') {event.preventDefault();}}switchOption(direction) {if (!this.getAttribute('open')) return;const moveUp = direction === 'up';const selectedElement = this.querySelector('[aria-selected="true"]');const allElements = this.querySelectorAll('li');let activeElement = this.querySelector('li');if (moveUp && !selectedElement) return;this.statusElement.textContent = '';if (!moveUp && selectedElement) {activeElement = selectedElement.nextElementSibling || allElements[0];} else if (moveUp) {activeElement = selectedElement.previousElementSibling || allElements[allElements.length - 1];}if (activeElement === selectedElement) return;activeElement.setAttribute('aria-selected', true);if (selectedElement) selectedElement.setAttribute('aria-selected', false);this.setLiveRegionText(activeElement.textContent);this.input.setAttribute('aria-activedescendant', activeElement.id);}selectOption() {const selectedProduct = this.querySelector('[aria-selected="true"] a, [aria-selected="true"] button');if (selectedProduct) selectedProduct.click();}getSearchResults(searchTerm) {const queryKey = searchTerm.replace(" ", "-").toLowerCase();this.setLiveRegionLoadingState();if (this.cachedResults[queryKey]) {this.renderSearchResults(this.cachedResults[queryKey]);return;}fetch(`${routes.predictive_search_url}?q=${encodeURIComponent(searchTerm)}&${encodeURIComponent('resources[type]')}=product&${encodeURIComponent('resources[limit]')}=4§ion_id=predictive-search`).then((response) => {if (!response.ok) {var error = new Error(response.status);this.close();throw error;}return response.text();}).then((text) => {const resultsMarkup = new DOMParser().parseFromString(text, 'text/html').querySelector('#shopify-section-predictive-search').innerHTML;this.cachedResults[queryKey] = resultsMarkup;this.renderSearchResults(resultsMarkup);}).catch((error) => {this.close();throw error;});}setLiveRegionLoadingState() {this.statusElement = this.statusElement || this.querySelector('.predictive-search-status');this.loadingText = this.loadingText || this.getAttribute('data-loading-text');this.setLiveRegionText(this.loadingText);this.setAttribute('loading', true);}setLiveRegionText(statusText) {this.statusElement.setAttribute('aria-hidden', 'false');this.statusElement.textContent = statusText;setTimeout(() => {this.statusElement.setAttribute('aria-hidden', 'true');}, 1000);}renderSearchResults(resultsMarkup) {this.predictiveSearchResults.querySelector('.predictive-search__keywords').classList.add('hide');this.predictiveSearchResults.querySelector('.predictive-search__results').innerHTML = resultsMarkup;this.setAttribute('results', true);this.setLiveRegionResults();this.open();}setLiveRegionResults() {this.removeAttribute('loading');this.setLiveRegionText(this.querySelector('[data-predictive-search-live-region-count-value]').textContent);}getResultsMaxHeight() {this.resultsMaxHeight = window.innerHeight - document.getElementById('shopify-section-header').getBoundingClientRect().bottom;return this.resultsMaxHeight;}open() {this.predictiveSearchResults.style.maxHeight = this.resultsMaxHeight || `${this.getResultsMaxHeight()}px`;this.setAttribute('open', true);this.input.setAttribute('aria-expanded', true);this.isOpen = true;}close(clearSearchTerm = false) {if (clearSearchTerm) {this.input.value = '';this.removeAttribute('results');}const selected = this.querySelector('[aria-selected="true"]');if (selected) selected.setAttribute('aria-selected', false);this.input.setAttribute('aria-activedescendant', '');this.removeAttribute('open');this.input.setAttribute('aria-expanded', false);this.resultsMaxHeight = falsethis.predictiveSearchResults.removeAttribute('style');this.isOpen = false;}}customElements.define('predictive-search', PredictiveSearch);
header.liquid
在style里面添加样式
ul.keywords_list {list-style: none;display: inline-table;padding: 0 20px;width: 100%;}ul.keywords_list a {text-decoration: none;}ul.keywords_list .keywords_item {float: left;width: 50%;margin: 5px 0;}
搜索 predictive-search predictive-search—header 将div标签内的内容更新为
<div class="predictive-search predictive-search--header" tabindex="-1" data-predictive-search><div class="predictive-search__keywords"><h2 class="predictive-search__heading text-body caption-with-letter-spacing">HOT SEARCH<svg aria-hidden="true" focusable="false" role="presentation" class="spinner" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg"><circle class="path" fill="none" stroke-width="6" cx="33" cy="33" r="30"></circle></svg></h2><ul class="keywords_list">{%- for block in section.blocks -%}<li class="keywords_item"><a href="{{ block.settings.collection.url }}"><span style="color: {{ block.settings.keyword_color }};">{{ block.settings.keyword }}</span></a></li>{%- endfor -%}</ul></div><div class="predictive-search__results"><div class="predictive-search__loading-state"><svg aria-hidden="true" focusable="false" role="presentation" class="spinner" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg"><circle class="path" fill="none" stroke-width="6" cx="33" cy="33" r="30"></circle></svg></div></div></div>
在schema中添加block配置
"blocks": [{"type": "keyword","name": "关键词配置","settings": [{"type": "header","content": "关键词配置项"},{"type": "collection","id": "collection","label": "关键词collection链接"},{"type": "text","id": "keyword","label": "显示的关键词"},{"type": "color","id": "keyword_color","label": "关键词颜色"}]}]
3. 效果展示
店铺地址: https://asen-practice.myshopify.com/ 密码:test
Tips: 如有引用请标注源文章地址
关注我的【小红书】,第一时间掌握更新动态
你的鼓励就是我创作的动力!
