Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- **AI referral counting.** With an API key, the SDK now counts page visits that ChatGPT, Claude, Perplexity, Gemini, Copilot and other AI products send to your application, and reports the totals about once a minute for the AI Traffic page. Only a browser loading a page counts (a GET whose fetch metadata says it is a document navigation). What is sent is aggregate: the AI platform, the landing path and a count, never anything about the visitor. It needs an API key scoped to one site; turn it off with `countAIReferrals: false`.

## [0.16.0] - 2026-09-24

### Changed
Expand Down
19 changes: 19 additions & 0 deletions packages/webdecoy/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Workers) alike.
*/

import type { AIReferralBatch } from './referrals/referral-counter';
import { SDKDetectionRequest, SDKDetectionResponse } from './types';
import type { ViolationEvent, IPEnrichmentData } from './rules/types';

Expand Down Expand Up @@ -157,6 +158,24 @@ export class WebDecoyClient {
}
}

/**
* Send AI referral counts. Resolves true when the batch needs no retry:
* accepted, or refused for a reason a retry cannot fix (a 4xx). Only a
* server error or a network failure resolves false, so the caller retries
* the same batch id.
*/
async sendAIReferrals(batch: AIReferralBatch): Promise<boolean> {
try {
const response = await this.request('POST', '/api/v1/sdk/ai-referrals', batch);
return response.status < 500;
} catch (error) {
if (this.config.debug) {
console.error('[WebDecoy] Failed to send AI referrals:', error);
}
return false;
}
}

/**
* Get IP enrichment data from the ingest service
*/
Expand Down
25 changes: 25 additions & 0 deletions packages/webdecoy/src/referrals/llm-platforms.generated.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// GENERATED from WebDecoy/app pkg/llmreferral (cmd/export-llm-platforms -ts). Do not edit.
// Referrer hostname => AI platform.

export const LLM_PLATFORMS: Readonly<Record<string, string>> = {
"chat.deepseek.com": "DeepSeek",
"chat.openai.com": "ChatGPT",
"chatgpt.com": "ChatGPT",
"claude.ai": "Claude",
"copilot.microsoft.com": "Copilot",
"deepseek.com": "DeepSeek",
"gemini.google.com": "Gemini",
"grok.com": "Grok",
"kagi.com": "Kagi",
"meta.ai": "Meta AI",
"perplexity.ai": "Perplexity",
"phind.com": "Phind",
"www.deepseek.com": "DeepSeek",
"www.grok.com": "Grok",
"www.kagi.com": "Kagi",
"www.meta.ai": "Meta AI",
"www.perplexity.ai": "Perplexity",
"www.phind.com": "Phind",
"www.you.com": "You.com",
"you.com": "You.com",
};
Loading
Loading