Get started
Algolia-compatible API
Keep a site built on InstantSearch, Autocomplete or an Algolia search client, and point it at Findlane: searches, filters, facets, sorts, highlights, Query Suggestions, click and conversion events, searches from your server, and secured API keys, without rewriting your pages.
If your site's search runs on InstantSearch or Autocomplete, it can search Findlane without changing its pages. Findlane answers Algolia's search API, so you point the Algolia client your site already uses at Findlane, with Findlane's application ID and search key. Search boxes, refinement lists, range sliders, sort menus, highlighting, and paging keep working as they are.
Bring the index across with the import first: it keeps the Algolia index's name, its replicas' names as sorts, its facet order, and each rule's redirect and first banner, so the pages that ask for them get answers. Then switch the client.
The compatible API answers searches and the events behind your analytics. Records and settings aren't written through it: load records with the import, the server SDK or the API, and change settings in the dashboard, from your server, or with an agent.
Point your pages at Findlane
- Make the index public. On the index's Public access page, turn on public search and add your site's origins.
- Create the search key. On API keys, under Sites built on InstantSearch, create the key and choose the indexes it opens. The key is public, like a search-only key: each index it opens is held to its public search settings and the sites it allows. The application ID is your workspace ID.
- Check the names. Your site asks for indexes by their Algolia names. The index answers to its own name and to the names the import kept: the Algolia index's, and each replica's as the sort it became. Under Names… you can add others, such as your Query Suggestions index, which then answers from the index's query suggestions.
- Point the client at Findlane. Pass the application ID, the key, and Findlane's host:
// algoliasearch 5
import { liteClient as algoliasearch } from "algoliasearch/lite"
const searchClient = algoliasearch("YOUR_WORKSPACE_ID", "fsk_…", {
hosts: [{ url: "api.findlane.dev", accept: "readWrite", protocol: "https" }],
})// algoliasearch 4
import algoliasearch from "algoliasearch/lite"
const searchClient = algoliasearch("YOUR_WORKSPACE_ID", "fsk_…", {
hosts: [{ url: "api.findlane.dev" }],
})The Algolia extensions for Magento and WordPress don't let you change the host in their settings, so stores using them need a small change in their theme or a module to pass hosts.
What it answers
- Searches: one query or several at once, and searches of a facet's values, such as a searchable brand list.
- Filters:
facetFilters,numericFilters,tagFilters, andfiltersstrings. Filters combine as Algolia's do: ANDs of OR groups. Without parentheses, OR binds first, sobrand:Nike OR brand:Asics AND inStock:truekeeps either brand in stock. One OR group may mix different fields, with up to four parts. - Results: highlights and snippets with the tags you ask for, facet counts and stats, paging up to the first 1,000 results with up to 50 a page, sorts by replica name, and
aroundLatLngandinsideBoundingBoxwhen the index allows location search. - Query Suggestions indexes: answered from the index's suggestions.
- Optional filters: each
optionalFiltersentry, afield:valueor a list of them, boosts the records matching it, so records matching more come first, as Algolia adds their scores. A negated entry, such asbrand:-Puma, or one with a negative score, buries them instead. Scores count only by their sign. - Facet order:
renderingContent.facetOrderinglists the facets counted, in the order asked, so InstantSearch'sDynamicWidgetsshow them. The import keeps the Algolia index's facet order. - Rules:
ruleContextsbecome contexts, which rules with a context condition fire on. Rules' banners come inuserData, as{ banner, link, title, position }, and a rule's redirect inrenderingContent.redirect.url, where InstantSearch's widgets look. The importer carries a rule's redirect and its first banner over. - Grouping:
distinctworks on indexes that group variants: 0 orfalseshows every record, and a number that many of each group's. - Analytics: a search sent with
analytics: falseis answered, and counts toward your plan, as any other, but stays out of search analytics and query suggestions, as on Algolia.
Parameters with no counterpart here are left out, and the response's x-findlane-ignored header names them. These include typo settings sent with a search, personalization, and optional filters on fields the index doesn't have.
Click and conversion events
InstantSearch's insights (the search-insights library) sends clicks, views and conversions to Algolia's Insights API. Point it at Findlane too, and they become the index's events, which feed analytics, revenue from search and Bought together:
import aa from "search-insights"
aa("init", { appId: "YOUR_WORKSPACE_ID", apiKey: "fsk_…", host: "https://api.findlane.dev" })- Clicks keep their places, and the query they came from: with
clickAnalytics, a result'squeryIDnames its search. - Conversions count when they're add-to-carts or purchases (
eventSubtype), with each product's price and quantity fromobjectData. A purchase's order ID is made from the user token, time and products, so the same event sent twice is one order. Conversions without a subtype, and events on filters, are left out. - The user token is the visitor ID when the index takes visitor IDs and the token fits one, as Algolia's anonymous tokens do.
- Each index is held to the sites it allows, as its searches are.
A request counts as one search, however many of its queries ask for results, as Algolia counts it; the cache answering all of it makes it free. The queries InstantSearch adds only to count a refined facet's values, and searches of facet values, never count.
Search from your server
If your server searches Algolia for your pages, such as a route that keeps the key out of the browser or a server-rendered page, point its Algolia client at Findlane the same way, with a secret API key:
- Create the key. On API keys, create a key with the search scope. It searches every index in the workspace, or the one index you choose, with or without public search, and each index answers to its Algolia names as above.
- Point the client at Findlane, with the workspace ID as the application ID and the key, on your server only:
import { algoliasearch } from "algoliasearch"
const client = algoliasearch("YOUR_WORKSPACE_ID", process.env.FINDLANE_SEARCH_KEY, {
hosts: [{ url: "api.findlane.dev", accept: "readWrite", protocol: "https" }],
})- Say who's searching. Pass the shopper's address in
X-Forwarded-For, as Algolia's clients do, and their browser's User-Agent infindlane-visitor-agent, so the index's limits and bot rules apply to each shopper rather than to your server, analytics counts shoppers, and searches from verified crawlers such as Googlebot are free:
const { results } = await client.search({ requests }, {
headers: { "x-forwarded-for": shopperIp, "findlane-visitor-agent": shopperUserAgent },
})A secret key's searches return any field the request names in attributesToRetrieve, and up to 100 results a page. Name only what your pages show, as your server's code decides what reaches the browser. Without X-Forwarded-For, searches count as your server's own, held to the key's limit. A request with an Origin header, as a browser sends, is refused, so a secret key put in a page's code fails at once. Use the search key (fsk_…) in browsers.
Secured API keys
If your server makes secured API keys for logged-in visitors, such as trade customers who see their own prices, it can keep making them with generateSecuredApiKey, using a Findlane signing key as the parent key:
- Create a signing key under Search for logged-in visitors on the API keys page, for every index or chosen ones. It's shown once: keep it in your server's environment, as
FINDLANE_SIGNING_KEY, in place of the search-only key you signed with. - Sign keys with it as you do now, with a
validUntil:
// algoliasearch 5; in 4, client.generateSecuredApiKey(parentApiKey, restrictions)
const securedKey = client.generateSecuredApiKey({
parentApiKey: process.env.FINDLANE_SIGNING_KEY!,
restrictions: {
filters: `customer_group:${user.group}`,
validUntil: Math.floor(Date.now() / 1000) + 3600,
userToken: user.id,
},
})- Search with it in the browser, with the workspace ID as the application ID and Findlane's host, as above.
The key's restrictions replace the index's public settings for that person's searches, so the index needs no public search or allowed origins:
validUntilis required, at most 7 days ahead.restrictIndicesnames the indexes it searches, by their Algolia names or their own names, with*for any part. An index's own name opens its sorts too. Without it, the key searches every index its signing key signs for.filters,facetFilters,numericFiltersandtagFiltersare forced onto every search, facet counts and stats included, and the page's own filters apply as well. A forced filter onobjectIDrefuses the search.attributesToRetrievelists the only fields its results return. Leaving fields out with-fieldisn't supported: list the fields to return.userTokennames the person, so rate limits and heavy visitors count them rather than their address.restrictSourcesandrefererslimit the addresses and sites it works from.- Any other search parameter, such as
hitsPerPage, replaces the search's own.
A refused key answers 403, with a message that says why, such as This signed key has expired; Algolia's clients don't fetch a new key, so your page should when it sees that. Click and conversion events sent with the key count for the indexes it searches. Query Suggestions indexes still need the search key (fsk_…). The signed keys section covers the rest, such as revoking a signing key.
When you're ready, move to the SDK
The compatible API is there so switching doesn't have to start with a rewrite, and it's a fine place to stay while you compare. Findlane's own browser SDK and React components speak its API directly, so nothing is lost in translation, and they reach the parts Algolia's request format has no room for:
- Related results when a search's words find nothing, and did-you-mean suggestions.
- One request per search: facet counts for refined filters come with the results, not as extra queries.
- Lists, recommendations, and click and purchase events that feed Bought together and your analytics.
The React components replace InstantSearch's widgets one at a time, so you can move a page or a widget at a time.