Skip to content
Start free

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

  1. Make the index public. On the index's Public access page, turn on public search and add your site's origins.
  2. 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.
  3. 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.
  4. 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, and filters strings. Filters combine as Algolia's do: ANDs of OR groups. Without parentheses, OR binds first, so brand:Nike OR brand:Asics AND inStock:true keeps 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 aroundLatLng and insideBoundingBox when the index allows location search.
  • Query Suggestions indexes: answered from the index's suggestions.
  • Optional filters: each optionalFilters entry, a field:value or a list of them, boosts the records matching it, so records matching more come first, as Algolia adds their scores. A negated entry, such as brand:-Puma, or one with a negative score, buries them instead. Scores count only by their sign.
  • Facet order: renderingContent.facetOrdering lists the facets counted, in the order asked, so InstantSearch's DynamicWidgets show them. The import keeps the Algolia index's facet order.
  • Rules: ruleContexts become contexts, which rules with a context condition fire on. Rules' banners come in userData, as { banner, link, title, position }, and a rule's redirect in renderingContent.redirect.url, where InstantSearch's widgets look. The importer carries a rule's redirect and its first banner over.
  • Grouping: distinct works on indexes that group variants: 0 or false shows every record, and a number that many of each group's.
  • Analytics: a search sent with analytics: false is 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's queryID names its search.
  • Conversions count when they're add-to-carts or purchases (eventSubtype), with each product's price and quantity from objectData. 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:

  1. 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.
  2. 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" }],
})
  1. Say who's searching. Pass the shopper's address in X-Forwarded-For, as Algolia's clients do, and their browser's User-Agent in findlane-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:

  1. 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.
  2. 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,
  },
})
  1. 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:

  • validUntil is required, at most 7 days ahead.
  • restrictIndices names 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, numericFilters and tagFilters are forced onto every search, facet counts and stats included, and the page's own filters apply as well. A forced filter on objectID refuses the search.
  • attributesToRetrieve lists the only fields its results return. Leaving fields out with -field isn't supported: list the fields to return.
  • userToken names the person, so rate limits and heavy visitors count them rather than their address.
  • restrictSources and referers limit 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.