Search
Why Webflow search does not work on WCH
WCH publishes your site as static files on your own hosting. Webflow's site search runs on Webflow's servers, so a search form that worked on your .webflow.io domain returns nothing once the site is served from S3, Azure, GitHub, or SFTP.
Slater search runs against an index of your published Webflow content and returns results from its own API, so it works on any host. There is no JavaScript to write. You add data-slater-* attributes to elements in the Designer and load one script.
Before you start
- Set your site up in Slater and connect it to your Webflow site. The shared setup, including the script tag and keys, is in the Slater Data getting started guide.
- Add the script once, before the closing
</body>tag in your Webflow project settings or the page's custom code:
<script src="https://api.slater.app/embed/v1/slater-search.js" defer></script>
Slater reads your Webflow site ID from the page automatically. Your .webflow.io staging domain routes to the right index with no extra setup.
Minimal global search
Three things are required: a wrapper with a key, an input, and at least one template card.
<div data-slater-search-list="site">
<input type="text" data-slater-search="site" placeholder="Search…" />
<a data-slater-template data-slater-item-href>
<h3 data-slater-bind-text="name"></h3>
<p data-slater-bind-text="matchedContext"></p>
</a>
</div>
data-slater-search-list: goes on a plain div that wraps the block. Its value is the block's key. Pick any label; it shares a namespace with list keys, so do not reuse one.data-slater-search: goes on the input, with the same key.data-slater-template: marks the card that is cloned for each result. Templates are removed from the page at load, so a placeholder card in the Designer is fine.
The results render inside the wrapper itself unless you point data-slater-results at a separate container. Only rendered cards are ever cleared, so the input and state elements can sit right next to them.
Building the result card
Every CMS field can be bound with data-slater-bind-* attributes, plus three fields reserved for search results:
url: a ready link. The published path for a static page, or/collection-slug/item-slugfor a CMS item.collection: the result's collection slug, or the wordpagefor a static page.matchedContext: a short text snippet around the match, for display.
Link cards with data-slater-item-href (no value, it uses url) or data-slater-bind-href="url". Do not write data-slater-href="{url}"; patterns percent-encode their placeholders and that mangles the slashes.
Different cards per collection
Give data-slater-template a value to use a different card for each collection. The value page is reserved for static pages. The template with no value is the default for everything else.
<div data-slater-results="site">
<a data-slater-template data-slater-item-href> …generic card… </a>
<a data-slater-template="blog" data-slater-href="/blog/{slug}"> …blog card… </a>
<a data-slater-template="page" data-slater-item-href> …page card… </a>
</div>
Optional controls
The standard Slater controls work with the block's key: data-slater-load-more, data-slater-empty, data-slater-count, data-slater-clear, and data-slater-for for a control placed outside the wrapper.
On the wrapper you can also set:
data-slater-results: the key of an explicit results container. Default is the wrapper itself.data-slater-min-length: minimum characters before a search fires. Default 2.data-slater-page-size: results per page. Default 20.data-slater-load-more-amount: results added per Load more click. Default is the page size.data-slater-site: Webflow site ID, if the page does not carry it.
Anywhere on the page, data-slater-initial="site" marks an element shown only while the block is idle, before the visitor has typed enough characters.
How the block behaves
- Idle until typed: nothing is fetched until the input reaches the minimum length. Clearing the input returns to idle.
- Empty is not idle: the initial element and the empty element never show together. Zero results shows the empty element. A failed request shows neither and leaves the block as it was.
- Deep links:
?q=termor?query=termin the page URL runs the search on load and fills the input.?query=is what Webflow's native search form submits, so a navbar form withaction="/search"works as a site-wide search bar without changes. - Query cap: queries longer than 100 characters are truncated, not rejected.
- Pagination resets: each new query starts load-more from the first page.
- No fallback: there is no server-rendered result list. If the very first request fails, the container stays empty.
Author state elements visible
Leave the empty, initial, and load-more elements visible in the Designer. Slater shows and hides them with an inline style. If you hide one with a Webflow class set to display: none, the script cannot override the class and the element never appears.
Limits
- No filters, sorting, facets, or locale on global search. Results are relevance-ranked. A filter or sort control pointed at a search block is ignored with a console warning. For a filterable cross-collection list, use a Slater multi-collection list instead.
- The ranked window is the top 1000 results. Load more stops there.
data-slater-expandworks and expands references across every collection in the results.data-slater-search-fieldsdoes not apply to global search, because collections share no field schema. Scope a single-collection list instead.
Testing your search
- Add
?slater-debug=1to the page URL and open the browser console. Slater prints the detected block, the template, and the first result's field keys. - Publish to Webflow, then publish to WCH staging.
- Open the staging site, type a term you know exists on more than one collection, and confirm results and links.
- Promote to production once results look right.
Full reference
- Global site search: the complete attribute list and behavior notes.
- Slater Data embed: shared setup, binding attributes, keyword search over one list, filters, facets, and load more.