@traceten/ai-crawl 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,7 +5,23 @@ All notable changes to this project are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
- ## [0.1.0] - Unreleased
8
+ ## [1.0.0] - Unreleased
9
+
10
+ First stable release. No functional change since 0.1.1 — the API has held
11
+ steady in production use, so this marks it stable rather than adding to it.
12
+
13
+ ## [0.1.1] - 2026-09-05
14
+
15
+ ### Changed
16
+
17
+ - Delivery timeout raised from 1500 ms to 5000 ms. Reports are scheduled off
18
+ the host response path in every adapter, so the old value delayed nothing and
19
+ bounded nothing useful. It did abort reports the ingest edge was still
20
+ answering: measured against a real deployment, roughly 15% of reports were
21
+ lost sequentially and 32% under concurrency, each one a client-side
22
+ `TimeoutError`. Those crawls are now delivered.
23
+
24
+ ## [0.1.0] - 2026-09-05
9
25
 
10
26
  Initial public release.
11
27
 
package/README.md CHANGED
@@ -1,6 +1,7 @@
1
+ <img src="https://traceten.com/logos/traceten-wordmark-black.png" alt="Traceten" width="320" />
2
+
1
3
  # @traceten/ai-crawl
2
4
 
3
- [![CI](https://github.com/traceten/ai-crawl/actions/workflows/ci.yml/badge.svg)](https://github.com/traceten/ai-crawl/actions/workflows/ci.yml)
4
5
  [![npm version](https://img.shields.io/npm/v/@traceten/ai-crawl.svg)](https://www.npmjs.com/package/@traceten/ai-crawl)
5
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
6
7
  [![Node](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org)
@@ -21,7 +22,8 @@ Provider, category (answer fetch, search index, training, other), verification a
21
22
 
22
23
  - Never blocks the response. Never throws per-request. Failure is silent.
23
24
  - Zero runtime dependencies.
24
- - 1500 ms delivery timeout, `keepalive: true`.
25
+ - 5000 ms delivery timeout, `keepalive: true`. Delivery is scheduled off your
26
+ response path, so this bounds a background task and never delays a response.
25
27
  - Requires Node 18+ or an edge runtime with `fetch`.
26
28
  - Each adapter bundle is under 8 KB gzipped (CI-enforced).
27
29
 
package/dist/matcher.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Anchored two-tier user-agent matching.
3
3
  *
4
- * NEVER `includes()` on the whole string that is the reference package's
5
- * defect (its page claims token matching; its code does substring matching,
6
- * so a browser UA containing `grok` or `copilot` false-positives). Follows
4
+ * NEVER `includes()` on the whole string. Substring matching false-positives
5
+ * on ordinary browser traffic: a UA containing `grok` or `copilot` anywhere
6
+ * would be reported as a crawler. Follows
7
7
  * the same anchoring discipline Traceten's server-side classifier uses,
8
8
  * adapted for crawler UAs where the token sits mid-string
9
9
  * (`Mozilla/5.0 … compatible; GPTBot/1.1; +https://openai.com/gptbot`).
package/dist/matcher.js CHANGED
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Anchored two-tier user-agent matching.
3
3
  *
4
- * NEVER `includes()` on the whole string that is the reference package's
5
- * defect (its page claims token matching; its code does substring matching,
6
- * so a browser UA containing `grok` or `copilot` false-positives). Follows
4
+ * NEVER `includes()` on the whole string. Substring matching false-positives
5
+ * on ordinary browser traffic: a UA containing `grok` or `copilot` anywhere
6
+ * would be reported as a crawler. Follows
7
7
  * the same anchoring discipline Traceten's server-side classifier uses,
8
8
  * adapted for crawler UAs where the token sits mid-string
9
9
  * (`Mozilla/5.0 … compatible; GPTBot/1.1; +https://openai.com/gptbot`).
package/dist/report.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Payload construction + delivery.
3
3
  *
4
- * Contract: never throws, never blocks the response, 1500 ms
4
+ * Contract: never throws, never blocks the response, 5000 ms
5
5
  * timeout, `keepalive: true`, snake_case on the wire. Delivery failures are
6
6
  * silent — a broken analytics call must never surface on a customer's site.
7
7
  *
@@ -10,7 +10,25 @@
10
10
  * told from a delivered one, and a bad token reads as "no crawlers visited".
11
11
  */
12
12
  import type { AiCrawlWirePayload, ResolvedAiCrawlConfig } from "./types.js";
13
- export declare const REPORT_TIMEOUT_MS = 1500;
13
+ /**
14
+ * Delivery budget for one report.
15
+ *
16
+ * Generous ON PURPOSE. Every adapter schedules delivery off the host's
17
+ * response path - `event.waitUntil()` on Next and both Cloudflare adapters,
18
+ * bare `void sendReport(...)` on Express and Hono - so this value never adds
19
+ * a millisecond to your response. It bounds a background task, not a request.
20
+ *
21
+ * It was 1500, chosen as though it were on the response path. It is not, and
22
+ * Traceten's edge grants itself time for a rate-limiter check before its 204.
23
+ * At 1500 the two were close enough that ordinary edge latency aborted the
24
+ * report client-side before the edge's own fail-open could answer, so the
25
+ * crawl was lost rather than degraded. Measured against a real deployment,
26
+ * 2026-09-05: ~15% of reports lost sequentially, ~32% under 8-way
27
+ * concurrency, every one a client-side TimeoutError.
28
+ *
29
+ * If you ever move delivery ONTO your response path, lower this.
30
+ */
31
+ export declare const REPORT_TIMEOUT_MS = 5000;
14
32
  /** Rebuild the reported URL against `publicOrigin` when configured. Never throws. */
15
33
  export declare function buildReportUrl(cfg: ResolvedAiCrawlConfig, url: string): string;
16
34
  export interface ReportInput {
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAEV,kBAAkB,EAClB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,GAAG,EAAE,qBAAqB,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAa9E;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,GAAG,EAAE,qBAAqB,EAAE,KAAK,EAAE,WAAW,GAAG,kBAAkB,CAe/F;AAcD,wBAAwB;AACxB,MAAM,WAAW,WAAW;IAC1B;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,qBAAqB,EAC1B,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,IAAI,CAAC,CAsCf"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAEV,kBAAkB,EAClB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,GAAG,EAAE,qBAAqB,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAa9E;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,GAAG,EAAE,qBAAqB,EAAE,KAAK,EAAE,WAAW,GAAG,kBAAkB,CAe/F;AAcD,wBAAwB;AACxB,MAAM,WAAW,WAAW;IAC1B;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,qBAAqB,EAC1B,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,IAAI,CAAC,CAsCf"}
package/dist/report.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Payload construction + delivery.
3
3
  *
4
- * Contract: never throws, never blocks the response, 1500 ms
4
+ * Contract: never throws, never blocks the response, 5000 ms
5
5
  * timeout, `keepalive: true`, snake_case on the wire. Delivery failures are
6
6
  * silent — a broken analytics call must never surface on a customer's site.
7
7
  *
@@ -9,7 +9,25 @@
9
9
  * or a network failure to the caller. Without it a rejected report cannot be
10
10
  * told from a delivered one, and a bad token reads as "no crawlers visited".
11
11
  */
12
- export const REPORT_TIMEOUT_MS = 1500;
12
+ /**
13
+ * Delivery budget for one report.
14
+ *
15
+ * Generous ON PURPOSE. Every adapter schedules delivery off the host's
16
+ * response path - `event.waitUntil()` on Next and both Cloudflare adapters,
17
+ * bare `void sendReport(...)` on Express and Hono - so this value never adds
18
+ * a millisecond to your response. It bounds a background task, not a request.
19
+ *
20
+ * It was 1500, chosen as though it were on the response path. It is not, and
21
+ * Traceten's edge grants itself time for a rate-limiter check before its 204.
22
+ * At 1500 the two were close enough that ordinary edge latency aborted the
23
+ * report client-side before the edge's own fail-open could answer, so the
24
+ * crawl was lost rather than degraded. Measured against a real deployment,
25
+ * 2026-09-05: ~15% of reports lost sequentially, ~32% under 8-way
26
+ * concurrency, every one a client-side TimeoutError.
27
+ *
28
+ * If you ever move delivery ONTO your response path, lower this.
29
+ */
30
+ export const REPORT_TIMEOUT_MS = 5000;
13
31
  /** Rebuild the reported URL against `publicOrigin` when configured. Never throws. */
14
32
  export function buildReportUrl(cfg, url) {
15
33
  try {
@@ -44,7 +62,7 @@ export function buildPayload(cfg, input) {
44
62
  }
45
63
  return payload;
46
64
  }
47
- /** Abort signal with a 1500 ms timeout, where the runtime supports it. */
65
+ /** Abort signal with the delivery timeout, where the runtime supports it. */
48
66
  function timeoutSignal() {
49
67
  try {
50
68
  if (typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function") {
@@ -1 +1 @@
1
- {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,16 +1,28 @@
1
1
  {
2
2
  "name": "@traceten/ai-crawl",
3
- "version": "0.1.0",
3
+ "version": "1.0.0",
4
4
  "private": false,
5
5
  "description": "Traceten server-side AI crawler tracking — see the GPTBot/ClaudeBot/PerplexityBot crawls that browser JavaScript can never see. Five adapters, zero dependencies, never blocks a response.",
6
6
  "keywords": [
7
+ "traceten",
8
+ "traceten.com",
7
9
  "ai-crawler",
8
10
  "gptbot",
9
11
  "claudebot",
10
12
  "perplexitybot",
11
13
  "bot-detection",
12
14
  "analytics",
13
- "traceten"
15
+ "ai-analytics",
16
+ "web-analytics",
17
+ "ai-traffic",
18
+ "ai-visibility",
19
+ "chatgpt",
20
+ "perplexity",
21
+ "llm-traffic",
22
+ "generative-engine-optimization",
23
+ "aeo",
24
+ "server-side-analytics",
25
+ "nodejs"
14
26
  ],
15
27
  "license": "MIT",
16
28
  "homepage": "https://docs.traceten.com/install/ai-crawler-tracking",
package/src/matcher.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Anchored two-tier user-agent matching.
3
3
  *
4
- * NEVER `includes()` on the whole string that is the reference package's
5
- * defect (its page claims token matching; its code does substring matching,
6
- * so a browser UA containing `grok` or `copilot` false-positives). Follows
4
+ * NEVER `includes()` on the whole string. Substring matching false-positives
5
+ * on ordinary browser traffic: a UA containing `grok` or `copilot` anywhere
6
+ * would be reported as a crawler. Follows
7
7
  * the same anchoring discipline Traceten's server-side classifier uses,
8
8
  * adapted for crawler UAs where the token sits mid-string
9
9
  * (`Mozilla/5.0 … compatible; GPTBot/1.1; +https://openai.com/gptbot`).
package/src/report.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Payload construction + delivery.
3
3
  *
4
- * Contract: never throws, never blocks the response, 1500 ms
4
+ * Contract: never throws, never blocks the response, 5000 ms
5
5
  * timeout, `keepalive: true`, snake_case on the wire. Delivery failures are
6
6
  * silent — a broken analytics call must never surface on a customer's site.
7
7
  *
@@ -16,7 +16,25 @@ import type {
16
16
  ResolvedAiCrawlConfig,
17
17
  } from "./types.js";
18
18
 
19
- export const REPORT_TIMEOUT_MS = 1500;
19
+ /**
20
+ * Delivery budget for one report.
21
+ *
22
+ * Generous ON PURPOSE. Every adapter schedules delivery off the host's
23
+ * response path - `event.waitUntil()` on Next and both Cloudflare adapters,
24
+ * bare `void sendReport(...)` on Express and Hono - so this value never adds
25
+ * a millisecond to your response. It bounds a background task, not a request.
26
+ *
27
+ * It was 1500, chosen as though it were on the response path. It is not, and
28
+ * Traceten's edge grants itself time for a rate-limiter check before its 204.
29
+ * At 1500 the two were close enough that ordinary edge latency aborted the
30
+ * report client-side before the edge's own fail-open could answer, so the
31
+ * crawl was lost rather than degraded. Measured against a real deployment,
32
+ * 2026-09-05: ~15% of reports lost sequentially, ~32% under 8-way
33
+ * concurrency, every one a client-side TimeoutError.
34
+ *
35
+ * If you ever move delivery ONTO your response path, lower this.
36
+ */
37
+ export const REPORT_TIMEOUT_MS = 5000;
20
38
 
21
39
  /** Rebuild the reported URL against `publicOrigin` when configured. Never throws. */
22
40
  export function buildReportUrl(cfg: ResolvedAiCrawlConfig, url: string): string {
@@ -60,7 +78,7 @@ export function buildPayload(cfg: ResolvedAiCrawlConfig, input: ReportInput): Ai
60
78
  return payload;
61
79
  }
62
80
 
63
- /** Abort signal with a 1500 ms timeout, where the runtime supports it. */
81
+ /** Abort signal with the delivery timeout, where the runtime supports it. */
64
82
  function timeoutSignal(): AbortSignal | undefined {
65
83
  try {
66
84
  if (typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function") {