> ## Documentation Index
> Fetch the complete documentation index at: https://algolia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Plugins

> Plugins encapsulate and distribute custom Autocomplete behaviors.

<Tip>
  Autocomplete is also available as an experimental widget in InstantSearch,
  making it easier to integrate into your search experience.
  For more information,
  see the API reference for [InstantSearch.js](/doc/api-reference/widgets/autocomplete/js) or
  [React InstantSearch](/doc/api-reference/widgets/autocomplete/react).
</Tip>

An autocomplete can be much more than a functional combo box.
**Autocomplete lets you extend and encapsulate custom behavior with its Plugin API.**

For example, the [official Algolia Insights plugin](/doc/ui-libraries/autocomplete/api-reference/autocomplete-plugin-algolia-insights) automatically sends click and conversion events to the [Algolia Insights API](/doc/rest-api/insights) whenever a user interacts with the autocomplete.

You can use one of the existing official plugins or build your own.

[**See demo**](https://codesandbox.io/s/github/algolia/autocomplete/tree/next/examples/github-repositories-custom-plugin?file=/app.tsx)

## Use Autocomplete plugins

When using an Autocomplete plugin,
all you need to do is provide it with the `plugins` option.

For example, when using the Insights plugin,
you can instantiate the plugin,
then pass it down to your Autocomplete instance.

```js JavaScript icon=code theme={"system"}
import { liteClient as algoliasearch } from "algoliasearch/lite";
import { autocomplete } from "@algolia/autocomplete-js";
import { createAlgoliaInsightsPlugin } from "@algolia/autocomplete-plugin-algolia-insights";
import insightsClient from "search-insights";

const appId = "latency";
const apiKey = "6be0576ff61c053d5f9a3225e2a90f76";
const searchClient = algoliasearch(appId, apiKey);

insightsClient("init", { appId, apiKey });

const algoliaInsightsPlugin = createAlgoliaInsightsPlugin({ insightsClient });

autocomplete({
  // ...
  plugins: [algoliaInsightsPlugin],
});
```

<Note>
  Plugins run sequentially, in the order you define them.
</Note>

## Build your own plugin

An Autocomplete plugin is an object that implements the `AutocompletePlugin` interface.

It can [provide sources](/doc/ui-libraries/autocomplete/core-concepts/sources),
react to [state changes](/doc/ui-libraries/autocomplete/core-concepts/state),
and hook into various autocomplete lifecycle steps.
It has access to setters,
including the [Context API](/doc/ui-libraries/autocomplete/core-concepts/context),
allowing it to store and retrieve arbitrary data at any time.

The following example creates a plugin that searches into a static list of GitHub repositories.

```js JavaScript icon=code theme={"system"}
const gitHubReposPlugin = {
  getSources() {
    return [
      {
        sourceId: "githubPlugin",
        getItems({ query }) {
          return [
            { name: "algolia/autocomplete", stars: 1237 },
            { name: "algolia/algoliasearch-client-javascript", stars: 884 },
            { name: "algolia/algoliasearch-client-php", stars: 554 },
          ].filter(({ name }) =>
            name.toLowerCase().includes(query.toLowerCase()),
          );
        },
        getItemUrl({ item }) {
          return `https://github.com/${item.name}`;
        },
        templates: {
          item({ item }) {
            const stars = new Intl.NumberFormat("en-US").format(item.stars);

            return `${item.name} (${stars} stars)`;
          },
          noResults() {
            return "No results.";
          },
        },
      },
    ];
  },
};

autocomplete({
  // ...
  plugins: [gitHubReposPlugin],
});
```

If you want to package and distribute your plugin for other people to use,
you might want to expose a function instead.
For example,
you can use the [GitHub API](https://docs.github.com/en/rest/reference/search#search-repositories) to search into all repositories, and let people pass [API parameters](https://docs.github.com/en/rest/reference/search#search-repositories--parameters) as plugin options.

```js JavaScript icon=code theme={"system"}
import qs from "qs";

function debouncePromise(fn, time) {
  let timerId = undefined;

  return function (...args) {
    if (timerId) {
      clearTimeout(timerId);
    }

    return new Promise((resolve) => {
      timerId = setTimeout(() => resolve(fn(...args)), time);
    });
  };
}

const debouncedFetch = debouncePromise(fetch, 300);

const baseUrl = `https://api.github.com/search/repositories`;

export function createGitHubReposPlugin(options) {
  return {
    getSources({ query }) {
      const queryParameters = qs.stringify({ ...options, q: query });
      const endpoint = [baseUrl, queryParameters].join("?");

      return debouncedFetch(endpoint)
        .then((response) => response.json())
        .then((repositories) => {
          return [
            {
              sourceId: "githubPlugin",
              getItems() {
                return repositories.items;
              },
              getItemUrl({ item }) {
                return item.html_url;
              },
              templates: {
                item({ item }) {
                  const stars = new Intl.NumberFormat("en-US").format(
                    item.stargazers_count,
                  );

                  return `${item.full_name} (${stars} stars)`;
                },
                noResults() {
                  return "No results.";
                },
              },
            },
          ];
        });
    },
  };
}
```

```js JavaScript icon=code theme={"system"}
import { autocomplete } from "@algolia/autocomplete-js";
import { createGitHubReposPlugin } from "./createGitHubReposPlugin";

const gitHubReposPlugin = createGitHubReposPlugin({
  per_page: 5,
});

autocomplete({
  container: "#autocomplete",
  plugins: [gitHubReposPlugin],
});
```

<Note>
  The GitHub Search API is [rate limited](https://docs.github.com/en/rest/reference/search),
  which means you need to [debounce calls](/doc/ui-libraries/autocomplete/guides/debouncing-sources) to avoid 403 errors. For instant search results with no rate limiting, highlighted results, flexible custom ranking, and more, you can index repositories into [Algolia](https://www.algolia.com/) instead.
</Note>

### Subscribe to source lifecycle hooks

When building, you also get access to the [`subscribe`](#param-subscribe) method. It runs once when the autocomplete instance starts and lets you subscribe to lifecycle hooks and interact with the instance's state and context.

For example, suppose you want to build a plugin that sends events to Google Analytics when users navigate results.
You can use `subscribe` to hook into `onSelect` and `onActive` events and use the [Google Analytics API](https://developers.google.com/analytics/devguides/collection/ga4/events?client_type=gtag) there.

```js JavaScript icon=code theme={"system"}
function createGoogleAnalyticsPlugin({ trackingId, options }) {
  return {
    subscribe({ onSelect, onActive }) {
      gtag("config", "<YOUR_GOOGLE_TAG_ID>", ...options);

      onSelect(({ item }) => {
        gtag("event", "select_item", {
          item_list_name: "Autocomplete",
          items: [
            {
              item_id: item.__autocomplete_id,
              item_name: item.name,
            },
          ],
        });
      });

      onActive(({ item }) => {
        gtag("event", "active_item", {
          item_list_name: "Autocomplete",
          items: [
            {
              item_id: item.__autocomplete_id,
              item_name: item.name,
            },
          ],
        });
      });
    },
  };
}
```

## Official plugins

* [`autocomplete-plugin-recent-searches`](/doc/ui-libraries/autocomplete/api-reference/autocomplete-plugin-recent-searches)

  Displays a list of the latest searches the user made.
  It comes with a [pre-implemented version](/doc/ui-libraries/autocomplete/api-reference/autocomplete-plugin-recent-searches/createLocalStorageRecentSearchesPlugin)
  that connects with users [local storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).

* [`autocomplete-plugin-query-suggestions`](/doc/ui-libraries/autocomplete/api-reference/autocomplete-plugin-query-suggestions)

  Plugs [Algolia Query Suggestions](/doc/guides/building-search-ui/ui-and-ux-patterns/query-suggestions/js) to your autocomplete.

* [`autocomplete-plugin-algolia-insights`](/doc/ui-libraries/autocomplete/api-reference/autocomplete-plugin-algolia-insights)

  Automatically sends click and conversion events to the [Algolia Insights API](/doc/rest-api/insights) whenever a user interacts with the autocomplete.

* [`autocomplete-plugin-tags`](/doc/ui-libraries/autocomplete/api-reference/autocomplete-plugin-tags)

  Lets you manage and display tags in the autocomplete. You can use tags for a wide variety of use cases: [filtering](/doc/ui-libraries/autocomplete/guides/filtering-results), displaying refinements, representing navigation steps, and more.

* [`autocomplete-plugin-redirect-url`](/doc/ui-libraries/autocomplete/api-reference/autocomplete-plugin-redirect-url)

  Lets you redirect your autocomplete results to a specified URL. You can configure this to work for both Algolia and non-Algolia data. For more information, see [Redirecting results to a URL](/doc/ui-libraries/autocomplete/guides/redirect).

## Reference

<ParamField path="name" type="string | undefined">
  A name to identify the plugin.
</ParamField>

<ParamField path="subscribe" type="function">
  ```ts Type definition theme={"system"}
  (params: {
    onSelect: (fn: params: TParams) => void, 
    onActive: (fn: params: TParams) => void,
    ...setters: AutocompleteSetters 
  }) => void
  ```

  The function called when Autocomplete starts.
</ParamField>

<ParamField path="onStateChange" type="function">
  ```ts Type definition theme={"system"}
  (params: { state: AutocompleteState<TItem> }) => void
  ```

  The function called when the internal state changes.
</ParamField>

<ParamField path="onSubmit" type="function">
  ```ts Type definition theme={"system"}
  (params: { state: AutocompleteState, event: Event, ...setters: AutocompleteSetters }) => void
  ```

  The function called when submitting the Autocomplete form.
</ParamField>

<ParamField path="onReset" type="function">
  ```ts Type definition theme={"system"}
  (params: { state: AutocompleteState, event: Event, ...setters: AutocompleteSetters }) => void
  ```

  The function called when resetting the Autocomplete form.
</ParamField>

<ParamField path="getSources" type="function">
  ```ts Type definition theme={"system"}
  (params: { 
    query: string,
    state: AutocompleteState,
    ...setters: AutocompleteSetters 
  }) => Array<AutocompleteSource> | Promise<Array<AutocompleteSource>>
  ```

  The sources to get the suggestions from.
</ParamField>

<ParamField path="data">
  An extra plugin object to expose properties and functions as APIs.
</ParamField>
