Skip to main content
Introducing packages.sweber.dev
Documentation menuSearch insights

Search insights

Find out which questions your docs do not answer, without tracking people.

Every search that finds nothing is a page someone wanted and you have not written. @weber-development/cosine-insights collects those searches and turns them into a to-do list.

1. Record searches in the browser

import { trackSearches } from "@weber-development/cosine-insights";

trackSearches(document.querySelector("cosine-search")!, { endpoint: "/api/search-insights" });

A search counts once typing has paused (1.5 s), not on every keystroke. Opening a result sends the query, the URL and its rank. Options: settleMs, sampleRate (record only a share of visitors), send (use your own analytics instead).

2. Receive them on your server

The handler is a plain Request → Response function:

app/api/search-insights/route.ts

import { createInsightsHandler } from "@weber-development/cosine-insights";
import { fileStore } from "@weber-development/cosine-insights/node";

export const POST = createInsightsHandler({ store: fileStore("data/searches.ndjson") });

It accepts same-origin requests only (set origins for others), validates every event and adds a timestamp. Implement InsightsStore (append(event)) to write to a database, KV store or log service instead of a file.

3. Read the report

npx cosine-insights report --log data/searches.ndjson --out insights.html --since 2026-09-01

The report lists:

  • Searches without results: missing pages, or missing words in existing ones.
  • Results nobody opened: the search found something, but it did not look like the answer.
  • Most searched queries and most opened pages, the click rate and the mean rank of opened results.

--out insights.md writes Markdown, e.g. for a monthly issue. From code: analyze(events), renderMarkdown(report), renderHtml(report).

Privacy

  • Events go to your own server, never to us or a third party.
  • No IP address, cookie, user id or header is stored, only query, result count, opened URL, rank and time.
  • Queries that look like e-mail addresses, phone or account numbers, IBANs or tokens are dropped in the browser and again on the server.

Mention the search statistics in your privacy notice all the same.