Search
What you're building: a text input that queries Algolia as someone types, rendering matches into a card you designed in Webflow.
Search starts empty and reacts to typing. If you want a page that already shows results when it loads, you want Browse instead.
What you need
- Applies toYour text input
Marks the box people type into.
- Applies toA Div that holds results
Where matches are rendered.
- Applies toOne card inside the results Div
Cloned once per result. Design it once.
Build it
1. Mark the input. Add to your Webflow Input.
2. Add a results container. A Div where matches will appear, carrying .
3. Design one card. Inside the results Div, build a single result the way you want it to look, and mark it . It is cloned once per hit and cleared before each render.
4. Bind the fields. Inside the card, point elements at record fields:
<h3 wf-algolia-text="title"></h3>
<p wf-algolia-text="excerpt"></p>
<img wf-algolia-image="thumbnail" wf-algolia-alt="title" />
<a wf-algolia-link="slug" wf-algolia-link-prefix="/blog/"></a>
5. Publish.
wf-algolia-text="Title" and wf-algolia-text="title" are different fields. A
mismatch fails silently on that one binding while the rest of the card renders,
which makes it look like the field is empty rather than misspelled.
Formatting values
A bound field renders exactly what Algolia stores, which is rarely what you want to show for a price, a rating or a year. Three attributes sit on the binding element itself.
transforms the value:
| Value | Renders |
|---|---|
number | Thousands grouping for the visitor's locale: 1,299 |
year | A four-digit year, from a date or a year |
date | The visitor's locale date: 4/28/2026 |
rating | ★ 4.5, always to one decimal place |
year and date read ISO text or a Unix timestamp in seconds or
milliseconds, so they keep working on a date field synced as a timestamp.
and wrap the result, and forces a fixed number of decimal places:
<div wf-algolia-text="price" wf-algolia-format="number" wf-algolia-prefix="$" wf-algolia-decimals="2"></div>
<div wf-algolia-text="area" wf-algolia-format="number" wf-algolia-suffix=" m²"></div>
That renders $1,299.00 and 450 m².
Prefix and suffix work on any binding, not only formatted numbers. A plain
wf-algolia-text with no format is wrapped too, and so is a highlighted search
match. Neither is rendered when the field is empty or missing, so an absent price
leaves the element blank rather than showing a lone $.
number plus a prefix, not currencyis deprecated. It hardcoded a dollar sign and two decimals, which no other currency could use. It still works and warns once. See Deprecations.
The same three attributes work on a facet stat tile, with the same meanings.
Array fields
A field holding several values, like genres or tags, renders as one
comma-joined string by default:
<div wf-algolia-text="genres_name"></div>
<!-- action film, comedy film, space opera -->
Change the glue with :
<div wf-algolia-text="genres_name" wf-algolia-separator=" · "></div>
<!-- action film · comedy film · space opera -->
One element per value
For styled tags or pills you want a real element per value, not one string. Design one item, mark it , and it is copied once per entry:
<ul role="list" wf-algolia-element="array-wrapper" class="tag-list">
<li wf-algolia-element="array-item" wf-algolia-text="genres_name" class="tag">Genre</li>
</ul>
For genres_name: ["action film", "comedy film"] that renders:
<ul role="list" wf-algolia-element="array-wrapper" class="tag-list">
<li wf-algolia-element="array-item" wf-algolia-text="genres_name" class="tag" style="display: none">Genre</li>
<li wf-algolia-text="genres_name" class="tag wf-algolia-injected">action film</li>
<li wf-algolia-text="genres_name" class="tag wf-algolia-injected">comedy film</li>
</ul>
The item you designed stays in the DOM but hidden. It is the template for the
next render, so do not delete it. Copies carry wf-algolia-injected and are
cleared and rebuilt every time the results change.
Your class keeps control of layout: nothing sets an inline display on the
copies, so .tag { display: block } or a flex parent behaves normally. If you
do need a specific display, put on the
item you designed and the copies inherit it.
is optional. It
names where the copies go, which matters when the item sits inside extra
styling Divs. Without it, copies land in the item's own parent. Put it on the
<ul> and the <li> copies stay direct children, which is what list semantics
and most CSS expect.
Both render through the same code. Earlier versions only expanded arrays on
detail pages, so a tag list inside a result card showed the joined string
instead. If you see action film,comedy film crammed into one tag, your site is
on an older script version.
Empty values are skipped, so a ragged array never renders a blank tag. An empty array renders no copies at all and leaves your wrapper in place, still styled.
Which index
A search input uses, in order: its own wf-algolia-index, an index inherited
from an ancestor, then data-index on the script tag. Most sites set it once on
the script tag and never think about it again.
Highlighting matches
Use instead of wf-algolia-text to wrap
matched words in a <mark>. Style mark in Webflow to control how it looks;
change the element itself with data-highlight-tag on the script tag.
wf-algolia-snippet does the same but truncates to a window around the match —
better for long body copy.
Empty and loading states
Mark a Div and it is shown only when a query returns nothing. Design it like any other element; the script only toggles visibility.
Searching several indices at once
A federated dropdown searches more than one index and groups the results. See Autocomplete.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Typing does nothing | The input has no wf-algolia-element="search-input" | Add it to the Input, not its wrapper |
| Results never appear | No element marked results, or no template inside it | Both are required |
| Cards render but are blank | Field names do not match your records | Open a record in Algolia and copy the keys exactly |
| Only one result ever shows | The template was placed outside the results container | Move it inside |
| Nothing at all, console silent | The script did not load | Verify your setup |
Related
- Browse — for pages that load with results
- Filters
- Search or browse