Skip to content

Count the bare Grok and xAI-Bot user agents, not only prerender them - #442

Merged
MarkusNeusinger merged 3 commits into
mainfrom
claude/ai-agents-grok-xai
Aug 28, 2026
Merged

Count the bare Grok and xAI-Bot user agents, not only prerender them#442
MarkusNeusinger merged 3 commits into
mainfrom
claude/ai-agents-grok-xai

Conversation

@MarkusNeusinger

Copy link
Copy Markdown
Owner

What

The nginx $is_bot map has served ~*grok and ~*xai since the prerender path landed (#433, #440), but AI_AGENTS — the taxonomy behind bot_fetch and asset_fetch — knew only grok-deepsearch, grokbot and xai-grok. So xAI's fetcher sending plain Grok/1.0 (seen on anyplot, 2026-08-19) or xAI-Bot (seen here, 2026-08-28) got the prerendered page and left no event on bots.kurrentschrift.ink.

Two bare entries — ("grok", "grok", "user_directed"), ("xai", "grok", "user_directed") — close the gap, placed last among the xAI patterns so the specific ones keep winning. Two test cases pin them.

Doctrine

AI_AGENTS is kept verbatim-identical with anyplot by decision (frontend-stack.md §6, crawler-richtlinie.md §3); anyplot merged the same two entries in #10808 today. The entry lists now diff empty again (comments aside). No new term, no glossary entry; CHANGELOG under Fixed.

Verification

  • uv run --extra test pytest — 1756 passed, 17 skipped
  • uv run --extra dev ruff check . + ruff format --check . — clean
  • diff of the two AI_AGENTS tuples (comments stripped) against ~/projects/anyplot/api/analytics.py — identical

The nginx $is_bot map has served ~*grok and ~*xai since the prerender
path landed, but AI_AGENTS — the taxonomy behind bot_fetch and
asset_fetch — knew only grok-deepsearch, grokbot and xai-grok. xAI's
fetcher sending plain "Grok/1.0" (seen on anyplot, 2026-08-19) or
"xAI-Bot" (seen here, 2026-08-28) got the page and left no event. Two
bare entries close the gap, last among the xAI patterns so the specific
ones keep winning; two test cases pin them. Mirrored verbatim from
anyplot #10808 — the taxonomy is kept identical between the two sites
by decision.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016joUzstV3siE3WqJtbcych
Copilot AI lite review requested due to automatic review settings August 28, 2026 21:48
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016joUzstV3siE3WqJtbcych

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The change is low risk, narrowly scoped, and pinned by focused unit tests with an accompanying changelog entry.

Pull request overview

This PR closes a bot-analytics classification gap by teaching the server-side AI_AGENTS taxonomy to recognize the bare xAI user-agent tokens (Grok/* and xAI-Bot/*) that were already being prerendered by nginx, ensuring they are also counted via Plausible bot events.

Changes:

  • Add two new substring patterns ("grok" and "xai") to api/analytics.py::AI_AGENTS so bare xAI fetchers are classified as ("grok", "user_directed").
  • Add two parametrized test cases to pin the new classifications.
  • Add a CHANGELOG.md entry under Fixed describing the behavioral impact and doctrine (mirrored taxonomy).
File summaries
File Description
api/analytics.py Extends AI_AGENTS with bare grok/xai patterns so prerendered xAI fetchers are also counted in bot analytics.
tests/test_api_analytics.py Adds coverage to assert Grok/1.0 and xAI-Bot/1.0 are classified as grok/user_directed.
CHANGELOG.md Documents the fix under [Unreleased] -> Fixed per project convention.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tests/test_api_analytics.py Outdated
Copilot AI review requested due to automatic review settings August 28, 2026 21:50
Copilot review nit on #442: the parenthetical read as if it applied to
both test cases; it describes only the xAI-Bot one.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016joUzstV3siE3WqJtbcych

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The change is small, well-scoped, and test-pinned, with only a minor comment-clarity nit remaining.

Review details

Suppressed comments (1)

tests/test_api_analytics.py:52

  • This comment is a bit misleading: it reads as if both "Grok" and "xAI-Bot" have “no grok substring”, but only the xAI-Bot UA lacks a grok substring. Clarifying avoids confusion when future readers compare this to the actual matching behavior.
        # The bare xAI tokens the nginx map serves: plain "Grok" and "xAI-Bot"
        # (no grok substring) were prerendered but not counted until these
        # patterns existed — mirrored from anyplot #10808.
  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings August 28, 2026 21:52

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The new UA patterns and tests align with the existing substring-first matching contract and the change is narrowly scoped with appropriate changelog and regression coverage.

Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@MarkusNeusinger
MarkusNeusinger merged commit 136942f into main Aug 28, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants