Anonymous telemetry

SEO sends small anonymous usage events so the project can count installs, completed setup and audits, retention, agent usage, and report popularity.

Your SEO data stays on your machine. Telemetry never contains an identifier that could link events to a person or machine.

See the same aggregate data as the maintainer on the public usage stats page.

First run notice

This notice is shown before the first event is sent.

The notice shown before anonymous telemetry starts.

SEO Skill collects anonymous usage data to improve the tool (event name,
report id, version, agent, OS, architecture, Node major, and install week;
never URLs, report data, or identifiers of any kind).
Docs: https://seoskill.dev/telemetry
Disable: seo telemetry disable (or set DO_NOT_TRACK=1)

Every event

Event nameWhen it is sentFrequency
first_runThe first invocation that creates local telemetry state.Once per local install.
setup_completeA non-dry-run guided setup finishes successfully.Once per local install.
audit_startA recognised report starts through the CLI or MCP server.Every report run.
audit_completeA recognised report finishes successfully.Every successful report run.
audit_failedA recognised report fails. It includes only a fixed errorCategory.Every failed report run.
first_audit_completeThe first recognised report finishes successfully.Once per local install.
active_d1An invocation happens at least one day after the first run.Once per local install.
active_d7An invocation happens at least seven days after the first run.Once per local install.
active_d30An invocation happens at least 30 days after the first run.Once per local install.

Every field sent

FieldValue
eventOne event name from the table above.
versionThe installed seo package version, such as 0.2.5.
agentclaude-code | cursor | codex | cli | unknown. MCP uses the client name from its standard initialize handshake, then discards the original name.
osaix | android | darwin | freebsd | haiku | linux | openbsd | sunos | win32.
archarm | arm64 | ia32 | loong64 | mips | mipsel | ppc | ppc64 | riscv64 | s390 | s390x | x64.
nodeThe Node.js major version as a string, such as 22.
cohortThe ISO week of the first run, such as 2026-W29. The exact first-run time never leaves local state.
schemaThe integer wire schema version. The current value is 1.
errorCategorySent only with audit_failed. One of auth | crawl_timeout | network | config | unknown. Raw errors are never sent.
reportSent only with report lifecycle events. It is one fixed public report identifier from the list below, never a URL or user-supplied string.

A successful report completion event.

{
  "event": "audit_complete",
  "version": "0.2.5",
  "agent": "codex",
  "os": "darwin",
  "arch": "arm64",
  "node": "22",
  "cohort": "2026-W29",
  "schema": 1,
  "report": "site-crawl"
}

Never collected or transmitted

  • User IDs, machine IDs, UUIDs, advertising IDs, or fingerprints of any kind.
  • Audited domains, URLs, hostnames, page content, search queries, or crawl results.
  • Report findings, recommendations, scores, exports, or other report content.
  • Google Search Console or Google Analytics responses, property IDs, account data, or metrics.
  • API keys, OAuth tokens, secrets, file paths, usernames, local hostnames, or raw error messages.
  • IP addresses in D1, Worker logs, application storage, or the public stats response.
  • Country, region, city, coordinates, or any other location data.

How to disable it

The local command is the simplest permanent setting. Environment settings can disable every telemetry network call without changing the saved preference.

Change or check the saved telemetry setting.

seo telemetry disable
seo telemetry status
seo telemetry enable

Disable telemetry for the current environment.

DO_NOT_TRACK=1
SEOSKILL_TELEMETRY_DISABLED=1
SEO_TELEMETRY_DISABLED=1

Telemetry is also disabled when CI=true or a common CI environment variable is present, including GitHub Actions, GitLab CI, CircleCI, Travis CI, Buildkite, Jenkins, TeamCity, Azure Pipelines, Bitbucket Pipelines, and AWS CodeBuild. An environment override wins over seo telemetry enable.

Local state

The memory needed for once-only events stays in telemetry.json inside the existing SEO config directory. Run seo telemetry status --json to see the exact path on your platform. The file contains only these fields.

The complete local telemetry state file.

{
  "telemetryEnabled": true,
  "firstRunAt": "2026-07-16T09:12:00.000Z",
  "cohort": "2026-W29",
  "sentMilestones": ["first_run", "first_audit_complete", "active_d1"]
}

firstRunAt is used only on your machine to decide when a retention milestone is due. Only its week-level cohort is sent. Clearing all local SEO state means a later run is counted as a new install because the server has no identity to recognise it.

Transport and storage

Each event is one JSON POST to https://seoskill.dev/api/t. The sender has a two-second timeout, does not batch or retry, silently drops failures, and never changes command output or exit status.

The Cloudflare Worker accepts only the fields and fixed values documented above. Unknown fields or values are rejected. It writes those values to a dedicated D1 table through a Worker binding. The server adds only the UTC receipt month, such as 2026-07, for monthly totals. It does not store the exact request time. There is no account or identity column, and no telemetry KV, R2, or Analytics Engine dataset. Worker invocation logs are disabled, and the code never readsrequest.cf, IP headers, or location fields. Cloudflare handles the ordinary network request at the edge, but no IP address or geography is written to D1.

D1 keeps the accepted anonymous events until they are deliberately deleted. Public totals cover all events recorded since collection began. Only aggregate counts are returned by the public stats endpoint.

Read the source