Algolia ×
Webflow Filters
A drop-in filtering solution for Webflow using Algolia. No 100-item CMS limit, full-text search, faceted filtering, pagination, and URL state sync — all driven by HTML data-* attributes.
Real-time data sync
Three parts, one solution
The library ships as three independent pieces. Each can be reused across projects with isolated configuration.
Next.js on Webflow Cloud
Sync App
Reads all CMS items via the Webflow API, resolves references and option fields to human-readable values, and pushes everything to Algolia. Handles full paginated syncs.
Cloudflare Worker
Webhook Worker
Listens for Webflow webhooks and keeps Algolia in sync incrementally — per-item changes on create/edit/delete, and triggers a full re-sync on site publish.
Vanilla JS via jsDelivr
Client Library
A single <script> tag loaded in Webflow. Reads HTML data-* attributes, queries Algolia, renders results, and handles filtering, searching, pagination, and active tags.
Get running in 11 steps
Follow these steps in order. Each one builds on the previous. The whole setup takes about 30 minutes.
Prerequisites
Go to github.com/felixeallan/algolia-webflow-filter and click "Use this template" → "Create a new repository". Name it (e.g. my-site-algolia) and make it public (required so jsDelivr can serve the script). Done — you have your own copy.
Sign up at algolia.com and create an application. Decide a name for your index (e.g. products, blog-posts, cars) — Algolia will create it automatically when the first sync runs, you do not need to create it manually.
Go to Settings → API Keys and copy these three values:
- Application ID → ALGOLIA_APP_ID
- Search API Key → used later in the script tag (safe to expose)
- Write API Key → ALGOLIA_ADMIN_API_KEY (keep secret, only used server-side)
Screenshot placeholder
API token
Webflow → Site Settings → Apps & Integrations → API Access → Generate API Token. Permissions: CMS: Read (read-only is enough — the sync never writes back). Copy the token → WEBFLOW_API_TOKEN.
Collection ID
In Webflow → CMS → click your collection → Settings → copy the Collection ID → WEBFLOW_COLLECTION_ID.
Screenshot placeholder
In your Webflow site → Site Settings → Webflow Cloud. Click "Install GitHub app" if needed, then "New app".
Configure:
- Name: anything (e.g. algolia-sync)
- Repository: your project repo from Step 1
- Directory path: apps/sync
- GitHub branch: main
- Path: /api (this becomes the URL prefix, e.g. yoursite.com/api/sync)
Once the environment is created, go to Environment Variables and add all 6 below. Click "Deploy latest commit". Wait for the deployment to go live.
The endpoint health check should return {"ok":true}:
| Variable | Type |
|---|---|
| WEBFLOW_API_TOKEN | Secret |
| WEBFLOW_COLLECTION_ID | Text |
| ALGOLIA_APP_ID | Text |
| ALGOLIA_ADMIN_API_KEY | Secret — this is the Write API Key |
| ALGOLIA_INDEX_NAME | Text — the name you chose, e.g. "products" |
| SYNC_SECRET | Secret — generate with: openssl rand -hex 32 |
curl https://YOUR_SITE.webflow.io/api/syncScreenshot placeholder
Trigger the first sync by hitting the endpoint with your secret. Check the Algolia dashboard → your index → Browse — all your CMS items should be there.
curl -X POST https://YOUR_SITE.webflow.io/api/sync \
-H "Authorization: Bearer YOUR_SYNC_SECRET"{ "success": true, "synced": 1234 }The sync app handles the initial bulk sync. The webhook worker keeps Algolia in sync as users publish/edit/delete individual CMS items. Webflow does not allow webhooks pointing to *.webflow.io domains, so we need an external worker.
- Go to dash.cloudflare.com → Workers & Pages → Create → Create Worker → Hello World
- Name it (e.g.
algolia-webflow-webhook) → Deploy - Click "Edit code", delete everything, and paste the contents of
apps/webhook-worker/src/index.js→ Deploy - Go to Settings → Variables and Secrets and add the variables below
- Note your worker URL — looks like
https://algolia-webflow-webhook.YOUR-USERNAME.workers.dev
| Variable | Type |
|---|---|
| ALGOLIA_APP_ID | Text |
| ALGOLIA_ADMIN_API_KEY | Secret — the Write API Key |
| ALGOLIA_INDEX_NAME | Text |
| WEBFLOW_COLLECTION_ID | Text — so webhooks from other collections get ignored |
| SYNC_ENDPOINT | Text — https://YOUR_SITE.webflow.io/api/sync |
| SYNC_SECRET | Secret — same as Webflow Cloud |
Screenshot placeholder
Webflow → Site Settings → Apps & Integrations → Webhooks → Add Webhook for each event below. The URL is the worker URL from Step 6. You do not need a webhook secret — leave that field blank.
| Event | Purpose |
|---|---|
| collection_item_created | New items appear instantly in Algolia |
| collection_item_changed | Edits sync instantly |
| collection_item_deleted | Deletes remove from Algolia |
| collection_item_unpublished | Unpublished items removed from Algolia |
| site_publish | Triggers a full re-sync (for schema changes, new fields, reference updates) |
Screenshot placeholder
In Algolia → your index → Configuration:
Facets — fields you want to filter by:
- Add every attribute that will be used as a filter (e.g. category, brand, color, year)
- Reference fields show up as the referenced item's name automatically (e.g. car-brand: "Quasar")
Searchable Attributes — fields used by the search input:
- Set to Ordered mode
- Top of the list = higher relevance
- Add fields like name, title, description
Click "Review and Save settings".
Screenshot placeholder
Sorting in Algolia works through replica indexes — pre-sorted copies of the main index. Each user-facing sort option = one replica. Algolia keeps replicas in sync automatically.
9.1 — Create one replica per sort option
In Algolia → your main index → Configuration → Replicas → Create Replica. Choose Virtual replica (free, no extra storage). Name it using the format INDEX_FIELD_DIRECTION:
9.2 — Configure each replica's Sort-by rule
For each replica, click its name to open it → Configuration → Relevant sort → add exactly one Sort-by rule matching the replica's name → click Review and Save settings.
**Important:** Each replica must have **exactly one** Sort-by rule. Multiple rules turn additional ones into tiebreakers. One replica = one dropdown option.
9.3 — Add the sort dropdown to your page
Use a native <select> element (not Webflow's navigation "Dropdown" component — that's a div-based menu and won't fire change events).
9.4 — Caveat: sorting numbers stored as strings
For sorting to behave numerically, the field must be a number in Algolia. Use a Webflow Number field (not a Plain text field formatted to look like a number) for any field you plan to sort numerically.
| Sort option | Replica name |
|---|---|
| Name A → Z | cars_name_asc |
| Name Z → A | cars_name_desc |
| Price ↑ | cars_price_asc |
| Price ↓ | cars_price_desc |
| Year newest | cars_year_desc |
| Year oldest | cars_year_asc |
<select data-algolia-sort>
<option value="">Default (relevance)</option>
<option value="cars_name_asc">Name: A → Z</option>
<option value="cars_name_desc">Name: Z → A</option>
<option value="cars_price_asc">Price: Low → High</option>
<option value="cars_price_desc">Price: High → Low</option>
<option value="cars_year_desc">Year: Newest first</option>
<option value="cars_year_asc">Year: Oldest first</option>
</select>Screenshot placeholder
In Webflow → Site Settings → Custom Code → Footer, add the script tag below.
Always pin to a version tag (e.g. @v0.8.2). Do not use @main — jsDelivr aggressively caches branch URLs.
<script src="https://cdn.jsdelivr.net/gh/felixeallan/algolia-webflow-filter@v0.8.2/packages/library/dist/algolia-webflow.min.js"></script>Add the wrapper div with your Algolia credentials, then place filter inputs, result list, and pagination inside it. See the HTML Structure and Data Attribute Reference sections below for the complete reference.
<div data-algolia data-algolia-app-id="YOUR_APP_ID" data-algolia-api-key="YOUR_SEARCH_ONLY_KEY" data-algolia-index="cars" data-algolia-hits-per-page="12" data-algolia-url-state
>
<!-- Search input -->
<input data-algolia-search type="text" placeholder="Search...">
<!-- Filters: checkbox = multi-select (OR within group, AND between groups) -->
<label data-algolia-filter="car-brand" data-algolia-value="Quasar">
<input type="checkbox"><span>Quasar</span>
</label>
<!-- Filters: radio = single-select within the group -->
<label data-algolia-filter="color-theme" data-algolia-value="White">
<input type="radio" name="color"><span>White</span>
</label>
<!-- Dropdown filter -->
<select data-algolia-filter-select="year">
<option value="">All years</option>
<option value="2024">2024</option>
<option value="2023">2023</option>
</select>
<!-- Sort dropdown (uses Algolia index replicas) -->
<select data-algolia-sort>
<option value="">Relevance</option>
<option value="cars_price_asc">Price ↑</option>
<option value="cars_price_desc">Price ↓</option>
</select>
<!-- Clear buttons -->
<button data-algolia-clear>Clear all</button>
<button data-algolia-clear="car-brand">Clear brands</button>
<!-- Active filter tags -->
<div data-algolia-tags>
<div data-algolia-tag-template class="tag">
<span data-algolia-tag-label></span>
<span data-algolia-tag-remove>×</span>
</div>
</div>
<!-- Result list with template -->
<div data-algolia-list>
<div data-algolia-template class="card">
<img data-algolia-bind="image.url" data-algolia-attr="src">
<h3 data-algolia-bind="name"></h3>
<p data-algolia-bind="car-brand"></p>
<img data-algolia-bind="car-brand__logo.url" data-algolia-attr="src">
<p data-algolia-bind="price"></p>
<p data-algolia-bind="year"></p>
<!-- Repeat for array/multi-reference fields -->
<div data-algolia-hide-empty="authors" data-algolia-repeat="authors">
<span data-algolia-repeat-item class="author-tag"></span>
</div>
<a data-algolia-bind="slug" data-algolia-attr="href">View</a>
</div>
</div>
<!-- Stats -->
<p><span data-algolia-count></span> results</p>
<!-- Empty state -->
<div data-algolia-empty style="display:none">No results found.</div>
<!-- Pagination -->
<button data-algolia-prev>← Previous</button>
<span data-algolia-page-info></span>
<button data-algolia-next>Next →</button>
</div>Webflow Setup
Everything here is configured directly in Webflow — no code required. Add these data-* attributes to your Webflow elements to connect them to Algolia.
Don't set up attributes manually — clone the Webflow template
All attributes below are already configured in the template. Pick from 4 examples: Standard Filter, Custom Pagination, Load More, or Range Slider Auto Bounds.
Required Setup
These three groups are the minimum needed for filtering to work.
Wrapper
| Attribute | On | Description |
|---|---|---|
data-algoliaRequired | any (wrapper div) | Marks the root. Everything else must be inside. |
data-algolia-app-id="..."Required | wrapper | Algolia Application ID |
data-algolia-api-key="..."Required | wrapper | Algolia Search-Only API key (safe to expose) |
data-algolia-index="..."Required | wrapper | Algolia index name |
data-algolia-hits-per-page="12" | wrapper | Number of results per page (default 12) |
data-algolia-url-state | wrapper | (optional) Sync filters/search/page to URL params for shareable links |
data-algolia-match-mode="or" | wrapper | (optional) Cross-group matching. Default = AND (item must match every group). "or" = OR (item matches any group). Ranges always stay AND with facets. |
data-algolia-debounce="300" | wrapper | (optional) Debounce delay in ms for search/range inputs. Default 300. |
data-algolia-stagger="50" | wrapper | (optional) Entrance animation delay in ms between result items. Default 0. |
Filters & Search
| Attribute | On | Description |
|---|---|---|
data-algolia-searchRequired | <input type="text"> | Full-text search input. Debounced 300ms by default. Results update as the user types. |
data-algolia-filter="attr" + data-algolia-value="val" | <label> + <input type="checkbox"> | Checkbox multi-select filter. Multiple checked values in the same attr are OR; across different attrs they are AND. |
data-algolia-filter="attr" + data-algolia-value="val" | <label> + <input type="radio"> | Radio single-select filter. Only one value per attr group can be active. All radios in the group must share the same name attribute. |
data-algolia-filter-all="attr" | <label> + <input type="radio"> | "All" option for a radio group. Auto-activates on load and whenever no specific value is selected in that group. |
data-algolia-filter-select="attr" | <select> | Dropdown (select) filter. An option with value="" resets the filter for that attr. |
Result List
| Attribute | On | Description |
|---|---|---|
data-algolia-listRequired | container | Where result items get injected. |
data-algolia-templateRequired | <div> or <template> | Cloned once per result, then injected into the list. A regular <div> is fine — it's hidden automatically. |
data-algolia-bind="field"Required | any (inside template) | Sets element text content from the Algolia hit field. Supports dot notation: image.url, car-brand__logo.url. |
data-algolia-bind="field" + data-algolia-attr="name" | any (inside template) | Sets an HTML attribute (src, href, alt, etc.) instead of text content. |
data-algolia-hide-empty="field" | any (inside template) | Hides this element when the bound field is empty, null, or an empty array. |
Optional
Add any of these to extend your filter UI.
Pagination
Load More
A single button that appends the next page of results to the existing list. Auto-hides when there are no more pages.
| Attribute | On | Description |
|---|---|---|
data-algolia-load-more | any | Append next page to existing results. Auto-hides when no more pages. |
Prev / Next
Replaces the current results with the previous or next page. Standard navigation-style pagination.
| Attribute | On | Description |
|---|---|---|
data-algolia-prev | any | Go to previous page. Auto-disabled on the first page. |
data-algolia-next | any | Go to next page. Auto-disabled on the last page. |
Page counter
Displays "Page X of Y". Optional companion to Prev / Next.
| Attribute | On | Description |
|---|---|---|
data-algolia-page-info | any | Shows the current page and total page count, e.g. "Page 2 of 12". |
Numbered pages
Renders a row of clickable page-number buttons. Can be combined with Prev / Next and Page counter.
| Attribute | On | Description |
|---|---|---|
data-algolia-pages | container | Where numbered page buttons are injected. |
data-algolia-page-button-template | child of pages container | Cloned for each visible page number. Active page receives data-active="" for styling. |
data-algolia-page-dots-template | child of pages container | (Optional) Cloned to render the "…" separator when page numbers are skipped. |
data-algolia-page-siblings="2,1,1,0" | pages container | Pages shown on each side of the current page. Comma-separated per Webflow breakpoint (Desktop, Tablet, Landscape, Portrait). Default 1. |
data-algolia-page-boundaries="1,1,1,0" | pages container | Pages always shown at the start and end of the list. Same breakpoint syntax. Default 1. |
Sort
| Attribute | On | Description |
|---|---|---|
data-algolia-sort | <select> | Each option's value must be an Algolia index replica name (e.g. cars_price_asc). Must be a native <select> — Webflow's "Dropdown" nav component is div-based and will not work. |
Clear Buttons
| Attribute | On | Description |
|---|---|---|
data-algolia-clear | any | Clears ALL filters, search query, and sort selection. |
data-algolia-clear="attr" | any | Clears only the specified filter group (e.g. data-algolia-clear="car-brand"). |
Empty State
| Attribute | On | Description |
|---|---|---|
data-algolia-empty | any | Shown only when the current query returns zero results. Hidden otherwise. |
Scroll Anchor
| Attribute | On | Description |
|---|---|---|
data-algolia-scroll-anchor | any | Scrolls smoothly to this element on every filter, search, sort, or pagination change. Can be inside or outside the [data-algolia] wrapper. Skipped on initial page load. |
Stats
| Attribute | On | Description |
|---|---|---|
data-algolia-count | any | Displays the total number of results matching the current query (e.g. 1,786). Updates on every filter change. |
Range Filters & Slider
| Attribute | On | Description |
|---|---|---|
data-algolia-range-min="attr"Required | <input type="number"> | Lower bound input of a numeric range filter. The attr must be a number field in Algolia. |
data-algolia-range-max="attr"Required | <input type="number"> | Upper bound input of a numeric range filter. |
data-algolia-range-label="Price" | range input | (optional) Custom label prefix for the active filter tag (e.g. "Price: Any – 2000"). Add to either min or max input. |
data-algolia-range-slider="attr"Required | wrapper div | Binds the slider to the same attr as the number inputs. |
data-algolia-range-slider-min="0"Required | slider wrapper | Static lower bound of the slider scale. Required unless using auto-bounds. |
data-algolia-range-slider-max="100000"Required | slider wrapper | Static upper bound. Required unless using auto-bounds. |
data-algolia-range-slider-auto-bounds | slider wrapper | (optional) Fetch the real min/max from Algolia facet stats on init. Replaces -slider-min/-slider-max. |
data-algolia-range-slider-step="100" | slider wrapper | (optional) Snap increment. Default 1. |
data-algolia-range-slider-format | slider wrapper | (optional) Format display spans using browser locale. Add a BCP 47 tag to force a locale (e.g. "fr-FR"). |
data-algolia-range-slider-trackRequired | child of slider wrapper | The track bar element. |
data-algolia-range-slider-fill | child of track | (optional) The highlighted fill between the two handles. |
data-algolia-range-slider-handle="min"Required | child of track | The lower drag handle. |
data-algolia-range-slider-handle="max"Required | child of track | The upper drag handle. |
data-algolia-range-slider-display="min" | any | Live text element showing the current lower value. |
data-algolia-range-slider-display="max" | any | Live text element showing the current upper value. |
Code examples
<div class="filter_block">
<!-- Number inputs the library reads. Keep visible for typing, or hide with display:none -->
<input type="number" data-algolia-range-min="price-number-2" data-algolia-range-label="Price" placeholder="min">
<input type="number" data-algolia-range-max="price-number-2" placeholder="max">
<div class="rangeslider_wrapper" data-algolia-range-slider="price-number-2" data-algolia-range-slider-min="0" data-algolia-range-slider-max="100000" data-algolia-range-slider-step="100" data-algolia-range-slider-format="en-US">
<div class="rangeslider_track" data-algolia-range-slider-track>
<div class="rangeslider_handle" data-algolia-range-slider-handle="min"></div>
<div class="rangeslider_handle" data-algolia-range-slider-handle="max"></div>
<div class="rangeslider_fill" data-algolia-range-slider-fill></div>
</div>
<div class="range_values">
<div>$<span data-algolia-range-slider-display="min">0</span></div>
<div>$<span data-algolia-range-slider-display="max">100,000</span></div>
</div>
</div>
</div>Active Filter Styling
| Attribute | On | Description |
|---|---|---|
[data-algolia-filter][data-active] | CSS selector | When a filter is selected, the library adds data-active="" to the label. Target this in Webflow's custom CSS to style the active state. |
w--redirected-checked | CSS class | For Webflow's native checkbox/radio components, the library also toggles this class for visual styling compatibility. |
/* Style active filter labels */
[data-algolia-filter][data-active] {
background: var(--blue-pale);
border-color: var(--blue);
color: var(--blue);
}
/* Style active page in numbered pagination */
[data-algolia-page-item][data-active] {
background: #2B4EF0;
color: white;
}Nested List
Render array / multi-reference fields as repeated child elements inside a result card.
Nested List (Repeat)
| Attribute | On | Description |
|---|---|---|
data-algolia-repeat="field" | container | Renders one child element per value in an array field (multi-reference, Option multi-select, etc.). |
data-algolia-repeat-item | child (inside repeat container) | Template element cloned for each array value. Its text content is set to each value in turn. |
Common patterns
Practical recipes for the most common implementation tasks.
The Webflow API returns field slugs (lowercase, hyphenated), not display names. Use these slugs in data-algolia-bind, data-algolia-filter, etc.
| Webflow Designer (display name) | API slug (Algolia field) |
|---|---|
| Product Name | name |
| Car Make | car-make |
| Featured? | featured |
The sync resolves single Reference fields to the referenced item's name automatically. It also stores all sub-fields as field__subfield. Multi-references become arrays.
<!-- Brand logo from the referenced "Car Brand" collection -->
<img data-algolia-bind="car-brand__logo.url" data-algolia-attr="src">
<!-- Brand name string -->
<p data-algolia-bind="car-brand"></p>Option fields are stored as the option's name (e.g. "White"), not its internal ID. Use the name in your filter values.
<label data-algolia-filter="color-theme" data-algolia-value="White">
<input type="checkbox"><span>White</span>
</label>Webflow "Switch" fields are stored as real booleans in Algolia (true / false). Use the string "true" or "false" as the filter value.
<label data-algolia-filter="featured" data-algolia-value="true">
<input type="checkbox">
<span>Featured only</span>
</label>Image fields are stored as objects with a url property. Use dot notation to bind the URL to a src attribute.
<img data-algolia-bind="image.url" data-algolia-attr="src">For arrays / multi-reference fields where each value should render as a separate element, use data-algolia-repeat. Use data-algolia-hide-empty to hide the wrapper when the field is empty.
<div data-algolia-hide-empty="authors" data-algolia-repeat="authors">
<span data-algolia-repeat-item class="author-tag"></span>
</div>data-algolia-hide-empty hides the element when the bound field is empty, null, or an empty array — useful for optional fields in cards.
<div data-algolia-hide-empty="authors" data-algolia-repeat="authors">
<span data-algolia-repeat-item></span>
</div>Use data-algolia-filter-all for a radio "All" option (auto-activates when nothing is selected). Or add checked to a specific input to set a default. URL state always takes priority.
<!-- Default to "All" -->
<label data-algolia-filter-all="car-brand">
<input type="radio" name="brand">
<span>All brands</span>
</label>
<!-- Default to a specific value -->
<label data-algolia-filter="car-brand" data-algolia-value="Quasar">
<input type="radio" name="brand" checked>
<span>Quasar</span>
</label>Add data-algolia-url-state to the wrapper to sync filters, search, and page number to URL params. Users can copy the URL to share their filtered view.
<div data-algolia data-algolia-app-id="YOUR_APP_ID" data-algolia-api-key="YOUR_KEY" data-algolia-index="cars" data-algolia-url-state
>
<!-- filter elements -->
</div>Add data-algolia-scroll-anchor to any element above the results. The page scrolls to it on every filter, search, sort, or pagination change.
<div data-algolia-scroll-anchor></div>
<div data-algolia-list>
<!-- results -->
</div>Each project only needs its own Algolia index, Webflow Cloud app, and Cloudflare Worker with isolated env vars. Fork only if you need to modify the sync logic or pin a different version per project.
# Per-project resources — always create fresh:
# - A dedicated Algolia index
# - A dedicated Webflow Cloud app (with its own env vars)
# - A dedicated Cloudflare Worker (with its own env vars)
# - Webflow webhooks pointing at that project's Cloudflare Worker URL
# Shared across projects (no duplication needed):
# - The client <script> tag (same jsDelivr URL)
# - The webhook worker code (apps/webhook-worker/src/index.js)
# - The sync app code (apps/sync)Built-in Inspector
The library ships with an Inspector that audits your page for configuration mistakes. It only loads on staging (*.webflow.io) and local development hosts, and only when you explicitly opt in.
Activate it
Append ?algolia-debug to your staging URL:
https://your-site.webflow.io/cars?algolia-debugYou will see a floating Algolia Inspector badge in the bottom-right corner. A red or yellow dot indicates issues; green means clean. All elements with data-algolia* attributes get a cyan outline and tooltip. Click the badge to open the diagnostic panel.
Controls
| Action | Result |
|---|---|
| ?algolia-debug in URL | Loads the Inspector for this page |
| Remove the param (or refresh without it) | Inspector unloads |
| Click the floating badge | Opens / closes the diagnostic panel |
| Toggle "Outline" checkbox in the panel | Shows / hides the cyan outlines + tooltips |
| Shift + ? keyboard shortcut | Same as toggling outline |
| Click any issue in the panel | Smoothly scrolls to the offending element and pulses an outline around it |
What it checks
Wrapper
[data-algolia] exists; required data-algolia-app-id, data-algolia-api-key, data-algolia-index present; data-algolia-match-mode is "and" or "or"
Templates
[data-algolia-list] and [data-algolia-template] both exist; template contains at least one data-algolia-bind; data-algolia-attr always paired with data-algolia-bind; data-algolia-bind / -hide-empty not left with empty values; data-algolia-repeat-item lives inside a data-algolia-repeat
Filters
data-algolia-filter paired with data-algolia-value; orphan data-algolia-value flagged; radio groups consistent — if any radio is wired up, every radio in that name group must be too; radios in the same filter share a name; non-empty values for -filter-select / -filter-all
Range
Every data-algolia-range-min="attr" has a matching data-algolia-range-max="attr" (and vice versa)
Range Slider
Has either static min/max OR auto-bounds; track + both handles present; matching number inputs in the wrapper
Pagination
Load More not combined with numbered Pages; [data-algolia-pages] has a button template; page templates live inside [data-algolia-pages]
Tags
[data-algolia-tags] has a [data-algolia-tag-template] child; tag children (-tag-label, -tag-remove) live inside the template
The Inspector never runs in production. Even with ?algolia-debug on a custom-domain site, nothing happens. Safe to ship.
Runbook
Common maintenance tasks after your initial deployment.
After adding new fields, new collections, or modifying references in Webflow, run a full sync. Publishing the site also triggers this automatically via the site_publish webhook.
curl -X POST https://YOUR_SITE.webflow.io/api/sync \
-H "Authorization: Bearer YOUR_SYNC_SECRET"In Algolia → your index → Manage index → Clear index → type CLEAR. Then re-run the sync.
# After clearing in the Algolia dashboard, re-sync:
curl -X POST https://YOUR_SITE.webflow.io/api/sync \
-H "Authorization: Bearer YOUR_SYNC_SECRET"When a new version is released, update the version tag in the script URL. Then hard refresh (Cmd/Ctrl+Shift+R) to bypass the browser cache.
<script src="https://cdn.jsdelivr.net/gh/felixeallan/algolia-webflow-filter@v0.8.2/packages/library/dist/algolia-webflow.min.js"></script>Fetch a single record from your Algolia index to verify field names and values after a sync.
curl -s "https://YOUR_APP_ID-dsn.algolia.net/1/indexes/YOUR_INDEX?hitsPerPage=1" \
-H "X-Algolia-Application-Id: YOUR_APP_ID" \
-H "X-Algolia-API-Key: YOUR_SEARCH_KEY"Use the PUT endpoint to return the raw Webflow collection schema — useful for debugging field types and resolving reference issues.
curl -X PUT https://YOUR_SITE.webflow.io/api/sync \
-H "Authorization: Bearer YOUR_SYNC_SECRET"Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Page shows wrong filter values, only ~100 items | Old version of @main cached by jsDelivr | Always pin to a @v0.x.x tag, not @main |
| New library changes not appearing | Browser cache | Hard refresh (Cmd/Ctrl+Shift+R) |
| Webhook URL rejected: "Invalid hostname" | Webflow blocks *.webflow.io webhooks | Use the Cloudflare Worker URL instead |
| Items from other collections appear in Algolia | Webhook fires for all collections | Set WEBFLOW_COLLECTION_ID in the Cloudflare Worker |
| Reference field shows an ID instead of name | Old sync, or new reference field | Re-run sync (or publish the site) |
| Webflow Cloud deploy fails (Cannot find package esbuild) | Webflow Cloud installs with --omit=dev | All build-time deps must be regular dependencies (already configured in the template) |
| Webflow Cloud deploy succeeds but routes 500 | Next.js 16.2+ Turbopack output crashes on Workers | Already pinned to ~16.1 with next build --webpack |
Ready to build?
Clone the Webflow template, follow the 11 steps, and have Algolia-powered filtering live on your Webflow site today.