Nuxt Swiftsearch
Examples

Analytics and Insights Events

End-to-end pattern for wiring click and conversion events from widgets.

Use this setup when you want Algolia Insights events from custom slots (sendEvent) while keeping SSR-safe rendering.

1) Initialize Insights on the client

Install search-insights in your app and create a client plugin:

bun add search-insights
plugins/algolia-insights.client.ts
import aa from "search-insights";

export default defineNuxtPlugin(() => {
  const config = useRuntimeConfig();

  aa("init", {
    appId: config.public.algoliaAppId,
    apiKey: config.public.algoliaSearchApiKey,
    useCookie: true,
  });
});

2) Enable Insights and dispatch events from slots

pages/search.vue
<template>
  <AisInstantSearch :configuration="configuration">
    <AisSearchBox placeholder="Search products" />

    <AisRefinementList attribute="brand" searchable>
      <template #item="{ item, refine }">
        <button type="button" :aria-pressed="item.isRefined" @click="refine(item.value)">
          {{ item.label }} ({{ item.count }})
        </button>
      </template>
    </AisRefinementList>

    <AisHits>
      <template #default="{ items, sendEvent }">
        <ol>
          <li v-for="item in items" :key="item.objectID">
            <NuxtLink
              :to="`/products/${item.objectID}`"
              @click="sendEvent('click', item, 'Search Result Clicked')"
            >
              {{ item.name }}
            </NuxtLink>

            <button type="button" @click="sendEvent('conversion', item, 'Product Added To Cart')">
              Add to cart
            </button>
          </li>
        </ol>
      </template>
    </AisHits>
  </AisInstantSearch>
</template>

<script setup lang="ts">
import { algoliasearch } from "algoliasearch";

const config = useRuntimeConfig();

const configuration = {
  indexName: "instant_search",
  searchClient: algoliasearch(config.public.algoliaAppId, config.public.algoliaSearchApiKey),
  insights: true,
};
</script>

Alternative: explicit middleware

If you want to control how events are dispatched (custom onEvent handler, scoping by index, swapping the insights client), pass createInsightsMiddleware through the :middlewares prop instead of the auto-flag:

<script setup lang="ts">
import { createInsightsMiddleware } from "instantsearch.js/es/middlewares";
import aa from "search-insights";

const middlewares = [
  createInsightsMiddleware({
    insightsClient: aa,
    onEvent: (event, insightsClient) => {
      // forward, transform, or fan-out to other analytics here
      insightsClient(event.insightsMethod!, event.payload);
    },
  }),
];
</script>

<template>
  <AisInstantSearch :configuration="configuration" :middlewares="middlewares">
    <!-- ... -->
  </AisInstantSearch>
</template>

<AisInstantSearch> watches :middlewares reactively, so adding or removing entries swaps them on the live InstantSearch instance via instance.use / instance.unuse. Drop configuration.insights: true in this path so the auto-middleware doesn't double-register.

Notes

  • sendEvent is available in AisHits and AisInfiniteHits slots using Insights-enabled connectors.
  • Keep event names stable (for example, Search Result Clicked) to simplify reporting.
  • Use runtime config for credentials, and keep the Insights plugin client-only.
Copyright © 2026