Skip to content
PluginStats

@usenotra/geo weekly downloads statistics

By usenotra · npm · MCP servers

Request capture SDK for AI traffic attribution and agent feedback collection

View on npm Stale · Oct 18, 2026

@usenotra/geo has 14,280 recorded weekly downloads on npm, an increase of 302% over the past 30 days.

Weekly downloads
14,280
Official API · Oct 18, 2026
7-day growth
-20.6%
-3.7K weekly downloads
30-day growth
+302%
+10.7K weekly downloads
90-day growth
—
Insufficient history
Rank
—
Among tracked npm listings

About @usenotra/geo

@usenotra/geo

Request capture SDK for AI traffic attribution. It captures every page request your site serves and sends a neutral request envelope to Notra. All classification, crawler versus AI referral versus human, happens server side at ingest, so a stale local table never costs you traffic. Requests classified as human are discarded at ingest and never stored. The core tracker ships no signature table. Only the optional Next.js tagLinks path bundles the matcher, because it has to decide at the edge which responses to rewrite for AI agents.

Zero dependencies. No Node APIs in the core, so it runs on edge runtimes.

Install

bun add @usenotra/geo

Next.js

// proxy.ts on Next.js 16, middleware.ts before that
import { createGeoProxy } from "@usenotra/geo/next";
import { NextResponse } from "next/server";

const geo = createGeoProxy({ token: process.env.NOTRA_GEO_TOKEN ?? "" });

export function proxy(request: Request, event: { waitUntil(p: Promise<unknown>): void }) {
  geo(request, event);
  return NextResponse.next();
}

geo(request, event) never throws and never blocks the response. When an event with waitUntil is passed, the send is registered on it so it survives the response.

Nuxt and Nitro

// server/middleware/geo.ts
import { createGeoHandler } from "@usenotra/geo/nuxt";

const geo = createGeoHandler({ token: process.env.NOTRA_GEO_TOKEN ?? "" });

export default defineEventHandler(async (event) => {
  await geo(event);
});

The handler accepts an H3 event with a node.req, or any object exposing a standard web request. Geo headers are usually absent behind Nitro, so those fields stay undefined and ingest falls back to IP based lookup.

TanStack Start

// src/start.ts
import { createMiddleware, createStart } from "@tanstack/react-start";
import { createGeoMiddleware } from "@usenotra/geo/tanstack";

const geo = createMiddleware().server(createGeoMiddleware({
  token: process.env.NOTRA_GEO_TOKEN!,
  endpoint: "https://ingest.usenotra.com",
}));

export const startInstance = createStart(() => ({
  requestMiddleware: [geo],
}));

The middleware captures requests alongside your route handler and waits for the send before returning, so tracking completes on serverless hosts. It preserves the downstream response and errors. If src/start.ts already exists, add geo to its existing requestMiddleware array.

Astro

// src/middleware.ts
import { createGeoMiddleware } from "@usenotra/geo/astro";

export const onRequest = createGeoMiddleware({
  token: import.meta.env.NOTRA_GEO_TOKEN ?? "",
  endpoint: "https://ingest.usenotra.com",
});

The middleware captures requests alongside your route handler and waits for the send before returning. If src/middleware.ts already exists, compose with sequence from astro:middleware. Astro must serve pages from a server adapter (output: "server" or hybrid) so requests exist at runtime; a static build has nothing to capture after deploy.

SvelteKit

// src/hooks.server.ts
import { env } from "$env/dynamic/private";
import { createGeoHandle } from "@usenotra/geo/sveltekit";

export const handle = createGeoHandle({
  token: env.NOTRA_GEO_TOKEN ?? "",
  endpoint: "https://ingest.usenotra.com",
});

The handle captures requests alongside resolve and waits for the send before returning. If src/hooks.server.ts already has a handle, compose with sequence from @sveltejs/kit/hooks.

React Router

// app/root.tsx
import { createGeoMiddleware } from "@usenotra/geo/react-router";
import type { Route } from "./+types/root";

const geo = createGeoMiddleware({
  token: process.env.NOTRA_GEO_TOKEN!,
  endpoint: "https://ingest.usenotra.com",
});

export const middleware: Route.MiddlewareFunction[] = [geo];

The middleware sends the event after next() returns, so the response never waits on it. Long-running Node servers need nothing extra. On serverless hosts pass the host's waitUntil so the send outlives the response, for example import { waitUntil } from "@vercel/functions" on Vercel or import { waitUntil } from "cloudflare:workers" on Cloudflare. React Router 8 always runs middleware; on React Router 7.9 or later set future: { v8_middleware: true } in react-router.config.ts.

Netlify Edge Functions

// netlify/edge-functions/geo.ts
import { createGeoHandler } from "@usenotra/geo/netlify";

const geo = createGeoHandler({ token: Deno.env.get("NOTRA_GEO_TOKEN") ?? "" });

export default (request: Request, context: Context) => {
  geo(request, context);
};

export const config = { path: "/*" };

Netlify's context.geo is mapped into the envelope and context.waitUntil keeps the send alive.

Options

OptionDefaultMeaning
tokenrequiredPer organization ingest token
endpointhttps://ingest.usenotra.comIngest origin, the SDK appends /api/geo/ingest
exclude["/api"]Paths to skip. Pass [] to disable
sample1Fraction of eligible requests to send, 0 to 1
onErrornoneCalled for network failures and non-success HTTP responses, including 401, 429 and 502. The SDK never throws
fetchglobal fetchInjectable fetch, for tests
waitUntilnoneReact Router only. Keeps the send alive after the response on serverless hosts

Requests go directly to https://ingest.usenotra.com when endpoint is omitted. The SDK does not automatically retry through the dashboard. To switch back to the dashboard ingestion route, set endpoint: "https://app.usenotra.com" and redeploy your site. Self-hosted installations must set endpoint to their own ingestion origin.

What gets captured…

Description from the npm listing.

  • agents
  • ai
  • analytics
  • astro
  • attribution
  • crawler
  • edge
  • feedback
  • geo
  • llms.txt
  • mcp
  • netlify
  • nextjs
  • nuxt
  • react-router
  • sveltekit
  • tanstack

README badge

Show your rank in a README or on your website. The badge updates automatically.

Charts

Images: 30d · 1y · all time · 1600×900 dark

Adoption over time

@usenotra/geo weekly downloads on npm, last 90 days: 14,280 weekly downloads as of Oct 18, 2026.@usenotra/geoWeekly downloads on npm · Last 90 days14,280downloads / week020K40K60K80K100K120K140K160K180KJul 20Aug 4Aug 19Sep 3Sep 18Oct 3Oct 18downloads / weekobservedarchived (Internet Archive)no observationsJul 26, 2026 – Oct 18, 2026 · 85 observations · Updated Oc…pluginstats.com
@usenotra/geo weekly downloads on npm, last 90 days: 14,280 weekly downloads as of Oct 18, 2026.

7/30/90-day growth

@usenotra/geo weekly downloads growth on npm: -20.6% over 7 days, +302% over 30 days, 90-day growth unavailable.@usenotra/geoWeekly downloads growth on npm14,280downloads / week now7-day growth-3,702 weekly downloads-20.6%30-day growth+10,730 weekly downloads+302%90-day growth+14,280 weekly downloadsInsufficient historyGrowth vs. nearest observation to each baseline date · Updated Oct 18, 2026pluginstats.com
@usenotra/geo weekly downloads growth on npm: -20.6% over 7 days, +302% over 30 days, 90-day growth unavailable.

Ranking history

@usenotra/geo npm ranking history: currently #870 (by weekly downloads).@usenotra/geonpm ranking · by weekly downloads · Last 90 days#870current rank#800#810#820#830#840#850#860#870#880Jul 23Aug 7Aug 22Sep 6Sep 21Oct 6Oct 21rankOct 18, 2026 – Oct 21, 2026 · 4 observations · Updated Oct 18, 2026pluginstats.com
@usenotra/geo npm ranking history: currently #870 (by weekly downloads).

Listing placement

All npm2,429 listings · 122 pages · 1,215 shown · page 44, #15 (overall #875)
All npm: every listing in weekly downloads order

Listing placement

MCP servers305 listings · 16 pages · page 7, #16 (overall #136)
MCP servers: every listing in weekly downloads order

Filled points are observed values; hollow points come from Internet Archive snapshots of the listing page. Dashed segments span periods with no observations — values between points are not interpolated.

Each band is one page of 20. Weekly downloads on a linear scale. Placement is projected from weekly downloads, so it can differ from the marketplace's own sort order. Hover a dot to see the listing.

Recent observations

Full history (122)
Recent weekly downloads observations for @usenotra/geo
Date (UTC)Weekly downloadsChange vs. previous
14,280-1.9K
16,162-2K
18,154+1.7K
16,437-2.6K
19,056-5.7K
24,7580
24,758+6.8K
17,982-10.3K
28,290-3.9K
32,230-7.7K
39,932-10.4K
50,353-16.6K
66,951-26.7K
93,674—

Similar npm MCP servers plugins

All 20 @usenotra/geo alternatives

Data source

Weekly downloads (trailing 7 complete days) come from the official npm downloads API. Downloads include CI and mirrors and are not equivalent to installs or users. npm publishes no ratings.

Listing: https://www.npmjs.com/package/@usenotra/geo. First seen Oct 16, 2026; last successful collection Oct 23, 2026. See the methodology.