Skip to main content

How to Add Algolia Search to Your Site 2026

·APIScout Team
Share:

Algolia delivers search results in under 50ms. This guide covers the full integration: indexing your data, building a search UI with InstantSearch, adding filters and facets, and tracking search analytics.

What You'll Build

  • Full-text search with typo tolerance and highlighting
  • Faceted filtering (category, price range, tags)
  • Search-as-you-type with instant results
  • Search analytics (what users search for, no-result queries)

Prerequisites: React 18+ or Next.js 14+, Algolia account (free: 10K searches/month).

1. Setup

Install

npm install algoliasearch react-instantsearch

Get Your Credentials

From the Algolia Dashboard:

  • Application ID — identifies your app
  • Search-Only API Key — safe for client-side (read-only)
  • Admin API Key — for indexing (server-side only)

Environment Variables

# .env.local
NEXT_PUBLIC_ALGOLIA_APP_ID=YOUR_APP_ID
NEXT_PUBLIC_ALGOLIA_SEARCH_KEY=your_search_only_key
ALGOLIA_ADMIN_KEY=your_admin_key  # Server-side only

2. Index Your Data

Push Data to Algolia

// scripts/index-data.ts
import algoliasearch from 'algoliasearch';

const client = algoliasearch(
  process.env.NEXT_PUBLIC_ALGOLIA_APP_ID!,
  process.env.ALGOLIA_ADMIN_KEY!
);

const index = client.initIndex('products');

const products = [
  {
    objectID: '1',
    name: 'React Query',
    description: 'Powerful data fetching for React',
    category: 'Data Fetching',
    stars: 38000,
    tags: ['react', 'data', 'cache'],
  },
  {
    objectID: '2',
    name: 'Zustand',
    description: 'Small, fast state management',
    category: 'State Management',
    stars: 42000,
    tags: ['react', 'state', 'lightweight'],
  },
  // ... more records
];

// Push records to Algolia
await index.saveObjects(products);
console.log('Indexed', products.length, 'records');

Configure Index Settings

await index.setSettings({
  // Which fields to search
  searchableAttributes: ['name', 'description', 'tags'],

  // Which fields to use as filters
  attributesForFaceting: ['category', 'tags', 'filterOnly(stars)'],

  // Custom ranking (Algolia handles relevance, you add business logic)
  customRanking: ['desc(stars)'],

  // Highlighting
  highlightPreTag: '<mark>',
  highlightPostTag: '</mark>',
});

Keep Data in Sync

For real-time sync, update Algolia when your database changes:

// When a product is created/updated
await index.saveObject({
  objectID: product.id,
  name: product.name,
  description: product.description,
  category: product.category,
  stars: product.stars,
  tags: product.tags,
});

// When a product is deleted
await index.deleteObject(product.id);

3. Basic Search UI

InstantSearch Provider

// components/SearchProvider.tsx
'use client';
import algoliasearch from 'algoliasearch/lite';
import { InstantSearch } from 'react-instantsearch';

const searchClient = algoliasearch(
  process.env.NEXT_PUBLIC_ALGOLIA_APP_ID!,
  process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY!
);

export function SearchProvider({ children }: { children: React.ReactNode }) {
  return (
    <InstantSearch searchClient={searchClient} indexName="products">
      {children}
    </InstantSearch>
  );
}

Search Box + Results

// components/Search.tsx
'use client';
import {
  SearchBox,
  Hits,
  Highlight,
  Stats,
  Pagination,
} from 'react-instantsearch';

function HitComponent({ hit }: { hit: any }) {
  return (
    <article>
      <h3>
        <Highlight attribute="name" hit={hit} />
      </h3>
      <p>
        <Highlight attribute="description" hit={hit} />
      </p>
      <span className="category">{hit.category}</span>
      <span className="stars">⭐ {hit.stars.toLocaleString()}</span>
    </article>
  );
}

export function Search() {
  return (
    <div>
      <SearchBox
        placeholder="Search APIs..."
        classNames={{
          input: 'search-input',
          submit: 'search-submit',
        }}
      />
      <Stats />
      <Hits hitComponent={HitComponent} />
      <Pagination />
    </div>
  );
}

Full Page

// app/search/page.tsx
import { SearchProvider } from '@/components/SearchProvider';
import { Search } from '@/components/Search';

export default function SearchPage() {
  return (
    <SearchProvider>
      <h1>Search APIs</h1>
      <Search />
    </SearchProvider>
  );
}

4. Faceted Filtering

Add sidebar filters for categories, tags, and numeric ranges:

// components/SearchWithFilters.tsx
'use client';
import {
  SearchBox,
  Hits,
  RefinementList,
  RangeInput,
  ClearRefinements,
  CurrentRefinements,
  Highlight,
  Pagination,
} from 'react-instantsearch';

export function SearchWithFilters() {
  return (
    <div className="search-layout">
      <aside className="filters">
        <ClearRefinements />
        <CurrentRefinements />

        <h3>Category</h3>
        <RefinementList attribute="category" />

        <h3>Tags</h3>
        <RefinementList
          attribute="tags"
          limit={10}
          showMore
          searchable
          searchablePlaceholder="Search tags..."
        />

        <h3>Minimum Stars</h3>
        <RangeInput attribute="stars" />
      </aside>

      <main className="results">
        <SearchBox placeholder="Search..." />
        <Hits hitComponent={HitComponent} />
        <Pagination />
      </main>
    </div>
  );
}

5. Autocomplete / Search-as-You-Type

For a dropdown autocomplete experience:

'use client';
import { useState, useEffect } from 'react';
import algoliasearch from 'algoliasearch/lite';

const searchClient = algoliasearch(
  process.env.NEXT_PUBLIC_ALGOLIA_APP_ID!,
  process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY!
);
const index = searchClient.initIndex('products');

export function Autocomplete() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState<any[]>([]);

  useEffect(() => {
    if (query.length < 2) {
      setResults([]);
      return;
    }

    const search = async () => {
      const { hits } = await index.search(query, {
        hitsPerPage: 5,
        attributesToRetrieve: ['name', 'category'],
      });
      setResults(hits);
    };

    const debounce = setTimeout(search, 200);
    return () => clearTimeout(debounce);
  }, [query]);

  return (
    <div className="autocomplete">
      <input
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Search APIs..."
      />
      {results.length > 0 && (
        <ul className="suggestions">
          {results.map((hit) => (
            <li key={hit.objectID}>
              <a href={`/api/${hit.objectID}`}>
                {hit.name} <span className="category">{hit.category}</span>
              </a>
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

6. Search Analytics

Track what users search for and improve results:

Enable Analytics

await index.setSettings({
  enableAnalytics: true,
});

Click Analytics

Track which results users click:

import { createInsightsMiddleware } from 'instantsearch.js/es/middlewares';
import { Hits, Configure } from 'react-instantsearch';

// In your InstantSearch component
<Configure clickAnalytics />

// In your hit component, send click events
function HitComponent({ hit, sendEvent }: { hit: any; sendEvent: Function }) {
  return (
    <article onClick={() => sendEvent('click', hit, 'Product Clicked')}>
      <h3>{hit.name}</h3>
    </article>
  );
}

Dashboard Metrics

Algolia's dashboard shows:

  • Top searches — what users search for most
  • No-result searches — queries that return nothing (add synonyms or content)
  • Click-through rate — are users finding what they need?
  • Click position — do users click result #1 or scroll to #10?

Pricing

TierSearches/MonthRecordsPrice
Free10,00010,000$0
Build10,000100,000$0 (included)
Grow10,000100,000From $0 (usage-based)
PremiumCustomUnlimitedCustom

Overage: $1 per additional 1,000 search requests.

Common Mistakes

MistakeImpactFix
Indexing too many fieldsSlow search, higher costsOnly index searchable fields
Not configuring searchable attributesPoor relevanceSet searchableAttributes with priority order
Exposing admin key to clientData can be deletedUse search-only key in browser
Not handling empty statesUsers see blank pageShow "No results" with suggestions
Stale index dataSearch shows deleted/outdated itemsSync on create/update/delete

AI-Powered Search: Algolia NeuralSearch

Traditional keyword search — the approach covered throughout this guide — requires users to use the right words. A search for "fast JavaScript framework" won't find a record tagged as "performant JS library" even though they describe the same thing. This is the fundamental limitation of keyword matching: relevance depends on vocabulary alignment between the query and the indexed content.

Algolia launched NeuralSearch in 2023 to address this. NeuralSearch combines keyword search with vector search — it understands semantic meaning rather than just matching tokens. A query for "fast JavaScript framework" can find records about "performant JS libraries" because the underlying vector representations are close in meaning, even without shared keywords. In 2026, NeuralSearch is available on all paid plans.

Enabling it requires two settings changes:

// Enable NeuralSearch in index settings
await index.setSettings({
  enableReRanking: true,  // Use AI to re-rank results
  reRankingApplyFilter: 'afterDistinct',
});

// Query with NeuralSearch
const { hits } = await index.search('fast framework for building UIs', {
  enableReRanking: true,
  hitsPerPage: 10,
});

The enableReRanking flag tells Algolia to apply its AI model as a second-pass re-ranking step after the initial keyword retrieval. Results that keyword search would rank 8th can jump to 2nd if the semantic model considers them more relevant to the query intent. The reRankingApplyFilter setting controls whether re-ranking happens before or after deduplication logic.

The main trade-off is cost. NeuralSearch queries consume more compute than standard keyword queries, which is reflected in per-query pricing. For a search page on a low-traffic content site, the cost increase is negligible. For a high-traffic e-commerce site running tens of millions of searches per month, model your expected query volume against Algolia's current pricing before enabling it in production. The pricing details are on Algolia's plans page and change periodically, so check there rather than relying on any guide's numbers.

For use cases where users tend to type natural language queries — documentation search, customer support knowledge bases, product discovery — NeuralSearch meaningfully improves result quality. For structured data with consistent terminology (product SKU search, user lookup by name), keyword search is already excellent and NeuralSearch adds cost without much benefit.


Performance Optimization

Algolia's infrastructure returns results in under 50ms from its edge network, but your integration can add latency on top of that. The main performance considerations are about reducing unnecessary work on both the client and the network.

Debouncing search input is the most basic optimization and is already shown in the autocomplete example above. A 200-300ms debounce delay means you're not firing a query on every keystroke — a user typing "react" fires one query when they pause, not four queries for "r", "re", "rea", "react". The autocomplete component in this guide already handles this with setTimeout, but the InstantSearch SearchBox component has a queryHook prop if you need custom debounce logic in the full InstantSearch setup.

The attributesToRetrieve setting limits what fields come back in each search result. If your hit component only displays name, category, and objectID, there's no reason to retrieve a description field that might be hundreds of words long. Smaller payloads mean faster network transfers and less parsing work in the browser.

Client-side caching is enabled by default in algoliasearch/lite — the lightweight search client used in browser environments. Identical queries within a two-minute window return cached results instantly without a network request. This is particularly valuable for common queries that many users run. The full algoliasearch client (the one you use server-side for indexing) has caching disabled by default, which is intentional — you want fresh results when re-indexing.

For Next.js App Router specifically: InstantSearch and its related components are client components that rely on browser APIs and React state. If you put InstantSearch in a Server Component, you'll get a build error about missing 'use client' directives. The clean pattern is a SearchProvider wrapper component (marked 'use client') that contains the InstantSearch provider, which you then import into your Server Component page. Everything inside SearchProvider can be a client component.

One additional technique worth considering: lazy initialization. If search is a secondary feature on a page — a header search bar that's collapsed by default, for example — you can defer rendering InstantSearch until the user clicks to open the search input. This avoids loading the search client and its associated JavaScript until it's actually needed, reducing initial page weight.


Algolia vs. The Alternatives

Algolia is not the only managed search service in 2026, and understanding where it fits in the landscape helps you make the right choice for your use case.

Typesense is the most direct competitor. It's open source (you can self-host it) and has a managed cloud offering. The API is deliberately similar to Algolia's, and the react-instantsearch components work with Typesense via an adapter package. Typesense is generally cheaper at scale — if you self-host, the only costs are your infrastructure. The managed cloud offering is priced more aggressively than Algolia. The trade-offs are a smaller company, a less mature analytics product, and fewer enterprise features like A/B testing and personalization.

Meilisearch is another open-source option with a strong developer experience. It's excellent for self-hosted use cases where you want full data control — common in regulated industries or for teams with strict data residency requirements. The cloud offering (Meilisearch Cloud) is available but less feature-complete than Algolia's.

Elasticsearch (and its cloud offering, Elastic Cloud) is considerably more powerful but also considerably more operationally complex. It's the right choice when you need full-text search capabilities combined with log analytics, security monitoring, or other Elastic Stack features. For straightforward product or content search, the operational overhead of Elasticsearch is rarely worth it.

PostgreSQL full-text search using pg_trgm and tsvector is worth considering for simpler use cases. If your data is already in Postgres and your search requirements are modest — basic keyword matching, simple filtering — adding a separate search service may be unnecessary complexity. The limitations show up with typo tolerance (Postgres pg_trgm handles trigram similarity but it's not as forgiving as Algolia's built-in typo handling) and relevance tuning.

For most projects under one million records and ten thousand daily searches, Algolia's free tier covers the use case entirely. When you outgrow the free tier, the upgrade path is straightforward, the documentation quality is genuinely excellent, and the InstantSearch component library is the most mature in the managed search space.

For teams on Next.js specifically, Algolia's first-class App Router support and the react-instantsearch hooks API make the integration feel native rather than bolted on. The resulting search experience — sub-20ms responses, typo tolerance, and real-time filtering — is consistently the smoothest achievable without significant custom engineering investment.


Adding search to your app? Compare Algolia vs Meilisearch vs Typesense on APIScout — pricing, performance, and ease of integration.

Related: How to Add Full-Text Search with Meilisearch, Algolia vs Elasticsearch: Search API Showdown, Algolia vs Meilisearch: Search-as-a-Service Compared

The API Integration Checklist (Free PDF)

Step-by-step checklist: auth setup, rate limit handling, error codes, SDK evaluation, and pricing comparison for 50+ APIs. Used by 200+ developers.

Join 200+ developers. Unsubscribe in one click.