npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@foglift/tracker

v1.4.1

Published

Track AI crawler visits and AI engine referrals to your website. See which AI engines (ChatGPT, Claude, Perplexity, Gemini, Copilot) are crawling your content AND sending you human visitors.

Readme

@foglift/tracker

Track AI crawler visits and AI engine referrals to your website. See which AI engines (ChatGPT, Claude, Perplexity, Gemini, Copilot) are crawling your content and sending you human visitors.

  • Two signals, one install. UA-detected bot visits + Referer/utm_source-detected human visits from AI engines.
  • Zero customer install friction. One-line middleware in Next.js, Express, or plain Node.
  • Cookieless. No fingerprinting. Only the visit's path, the matched UA category, and the matched referrer host or UTM marker are sent to Foglift.
  • Fire-and-forget. Reporting never blocks your request lifecycle.
  • Hostname-bound Sensor installs. Server and edge adapters send the observed request hostname with a publishable workspace capability. Foglift requires both to match; a caller-controlled hostname alone cannot write analytics.

Install

npm install @foglift/tracker

Copy your workspace ID from Foglift's AI Traffic install panel. It is a publishable identifier, not a secret, and works on every plan. Existing API-key installs remain supported.

Quickstart — Next.js

// middleware.ts
import { trackAITraffic } from "@foglift/tracker/nextjs";

export const middleware = trackAITraffic({
  siteToken: "YOUR_WORKSPACE_ID",
});

export const config = {
  matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
};

That's it. Within ~5 seconds of a real ChatGPT/Claude/Perplexity user clicking through to your site, a row lands in your dashboard at https://foglift.io/dashboard/crawlers.

Composing with an existing middleware

import { trackAITraffic } from "@foglift/tracker/nextjs";
import { auth } from "./auth-middleware";

export const middleware = trackAITraffic({
  siteToken: "YOUR_WORKSPACE_ID",
  next: auth,
});

Quickstart — Express

import express from "express";
import { trackAITraffic } from "@foglift/tracker/express";

const app = express();
app.use(trackAITraffic({ siteToken: "YOUR_WORKSPACE_ID" }));

Quickstart — plain Node (any framework)

import http from "node:http";
import { createAITrafficTracker } from "@foglift/tracker/node";

const tracker = createAITrafficTracker({ siteToken: "YOUR_WORKSPACE_ID" });

http
  .createServer((req, res) => {
    tracker.track(req);
    res.end("ok");
  })
  .listen(3000);

Quickstart — Cloudflare Workers

import { trackAITrafficWorker } from "@foglift/tracker/cloudflare";

export default {
  fetch: trackAITrafficWorker({ siteToken: "YOUR_WORKSPACE_ID" }),
};

Every server adapter derives the hostname from the request and sends it with the publishable token. Foglift accepts the event only when that hostname belongs to the workspace.

What gets reported

trackAITraffic emits one of two visit shapes per matching request, then drops the call. Nothing is reported if neither the UA, Referer, nor supported utm_source matches — the vast majority of your traffic is invisible to Foglift.

API-key compatibility and multi-brand attribution

Existing API-key installs continue to work. Multi-brand API-key accounts should pass the selected Foglift brand UUID as brandId:

trackAITraffic({
  apiKey: process.env.FOGLIFT_API_KEY!,
  brandId: process.env.FOGLIFT_BRAND_ID,
});

The SDK serializes brandId as brand_id in the reporting payload. Single-brand accounts can omit it.

Crawler visits (UA wins over Referer)

When the User-Agent matches a known AI-related agent, the visit is reported as source: "crawler" with its matched name, engine, and documented role: training, indexing, user_fetch, mixed, or owner_requested. mixed is reserved for agents whose documented uses cross categories; owner_requested identifies a crawl initiated by a site owner to build an agent. A user_fetch means the matched agent is documented for end-user answers; it is citation-proximate, not proof of citation. User-Agent strings can be spoofed, so verify vendor IP ranges before treating an individual request as authoritative.

Referrer visits (human users from AI search)

When the User-Agent looks human but the Referer header points at one of the canonical AI search hostnames, the visit is reported as source: "referrer". If the Referer host is absent or non-AI, the tracker falls back to utm_source values commonly used by AI engines, such as chatgpt, openai, perplexity, claude, anthropic, gemini, bard, and copilot. Referer-host matches always win, so a request with both signals is reported once.

| Engine | Hostname(s) tracked | |---------------|--------------------------------------------------| | ChatGPT | chatgpt.com, chat.openai.com | | Claude | claude.ai | | Perplexity | perplexity.ai, www.perplexity.ai | | Gemini | gemini.google.com | | Copilot | copilot.microsoft.com | | NotebookLM | notebooklm.google.com |

Google AI Overview disambiguation (parsing udm=/ved= on google.com referrers) is intentionally out of scope for v1.2.0 — google.com referrers stay classified as organic search by your host application. Tracked for v1.3.

Privacy

  • No cookies, no fingerprinting. The tracker reads the request's User-Agent, Referer header, and path — nothing else.
  • No PII. The Referer is parsed for hostname only; query parameters are discarded before reporting.
  • HTTPS reporting. Visits are posted to https://foglift.io/api/v1/crawler-analytics with a hostname-bound publishable workspace ID. Legacy API-key installs continue to use the X-API-Key header.
  • Fire-and-forget. A failed report logs (only when debug: true) and never throws.

Migrating

Migrating to v1.4.0

New installs should use siteToken. Existing apiKey and optional brandId configuration remains backward compatible, so upgrading does not require an immediate configuration change.

trackAITraffic({ siteToken: "YOUR_WORKSPACE_ID" });

From v1.1.0

If you're upgrading from @foglift/[email protected], the trackAICrawlers export still works and now additionally reports referrer visits — no code change required, you get the new signal for free. The export will warn in v1.3 and be removed in v2.0; switch to trackAITraffic at your convenience.

// v1.1.0 (still works, additive in v1.2.0)
import { trackAICrawlers } from "@foglift/tracker/nextjs";

// v1.2.0 — preferred
import { trackAITraffic } from "@foglift/tracker/nextjs";

The crawler-visit payload shape is byte-identical to v1.1.0 (with one additive source: "crawler" field) — receiver-side aggregation is unchanged for existing crawler customers.

Debugging

trackAITraffic({
  apiKey: process.env.FOGLIFT_API_KEY!,
  debug: true,
});

In debug mode, failed reports log to console.warn with the HTTP status and error message. Disable in production.

Manual classification helpers

If you'd rather drive the classification yourself (e.g. you already have a custom analytics pipeline), the detectors are exported as pure functions:

import { detectAICrawler, detectAIReferrer } from "@foglift/tracker";

detectAICrawler("Mozilla/5.0 (compatible; PerplexityBot/1.0)");
//=> { crawler: "PerplexityBot", engine: "Perplexity" }

detectAIReferrer("https://chatgpt.com/c/abc123");
//=> { source: "chatgpt.com", engine: "ChatGPT" }

Both return null on no-match.

Links

  • Dashboard: https://foglift.io/dashboard/crawlers
  • Foglift docs: https://foglift.io/docs/tracker
  • Issue tracker: https://github.com/foglift/tracker/issues
  • License: MIT