惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

月光博客
月光博客
C
Check Point Blog
J
Java Code Geeks
腾讯CDC
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
Microsoft Azure Blog
Microsoft Azure Blog
WordPress大学
WordPress大学
量子位
Google DeepMind News
Google DeepMind News
I
InfoQ
The GitHub Blog
The GitHub Blog
aimingoo的专栏
aimingoo的专栏
N
Netflix TechBlog - Medium
Hugging Face - Blog
Hugging Face - Blog
博客园 - Franky
V
V2EX
Blog — PlanetScale
Blog — PlanetScale
T
The Blog of Author Tim Ferriss
小众软件
小众软件
博客园_首页
人人都是产品经理
人人都是产品经理
博客园 - 聂微东
IT之家
IT之家

Giant Robots Smashing Into Other Giant Robots

Client success starts before kickoff 5 easy, actionable tips for software development in healthcare Announcing importmap-update: automated dependency updates for importmap-rails When to vibe code an app and when to hire someone Why leaders have to know about PMS 🩸 Is AI ruining my brain? Tech Leaders Meetup is coming to Edinburgh Designers already think in React Tech Leaders Meetups are back in London this autumn GPT and Claude go to heraldry school Inserting State Transitions in Postgres Don’t hire thoughtbot to write code AI makes creating software faster, but in regulated industries, judgment matters more Tech Leaders meetup in Amsterdam PMs Don't Need to Code, but They Do Need to Understand How healthcare tech teams innovate while balancing speed and security Can’t touch the DOM? Reach for :has() to style any element Buying Time, Choosing Words: Consulting Through Diplomatic Communication thoughtbot around the world, meet us at upcoming events Modeling State Transitions in Postgres Humid 1.0: React server-side rendering in Rails can be easy! A prototype is not a product. It's a conversation. New: The State of Software Delivery in Healthcare Sign in with Google for React Native What founders told us about working with AI tools for startups Join us: Building Secure Healthcare Systems Upcase has retired, but the learning continues The Bike Shed Ep 506: The Muppet Software Team Migrating to native stack navigation, with a surprise from iOS 26 Past and present thoughtbotters at LRUG this Monday
AI crawlers are inflating your view counts
Trésor Bireke · 2026-06-16 · via Giant Robots Smashing Into Other Giant Robots

Your most-viewed page might be one no human has ever opened. That is what AI crawlers have done to view tracking in 2026.

I ran into this problem on a production app that needed engagement tracking. The first version tracked everything server-side, the way Rails apps have done analytics for years. It broke within a day.

The problem: crawlers inflate every count

We used Ahoy for tracking. Each controller action called ahoy.track while rendering the page, and every event rolled up into a denormalized counter column with counter_culture.

The issue is that server-side tracking fires on every request, including bots. AI crawlers like Meta-ExternalAgent, Bytespider, and Baiduspider were making roughly 100,000 requests per day. They were not attacking the site, just reading to feed training pipelines.

Ahoy has bot detection built in. It uses the device_detector gem to check user agents and skips known bots. That list catches Googlebot and older crawlers, but it misses the new wave of AI crawlers. As a result, every one of those requests created an Ahoy::Event row and incremented the corresponding counters.

Our view counts were not measuring human interest. They were measuring how hungry the scrapers were that week.

Fix one: require JavaScript

Chasing user agent strings is a losing game. New crawlers appear faster than blocklists update. But there is one thing AI crawlers reliably do not do, and that is execute JavaScript.

So we moved view tracking out of the controllers. Pages declare what is trackable as a data attribute, and a small Stimulus controller fires a beacon after the page loads.

connect() {
  if (this.element.dataset.viewTrackerFired === "true") return
  this.element.dataset.viewTrackerFired = "true"

  const fire = () => this.fire()
  if ("requestIdleCallback" in window) {
    requestIdleCallback(fire, { timeout: 2000 })
  } else {
    setTimeout(fire, 500)
  }
}

A few details mattered here:

  • requestIdleCallback defers the beacon until the browser is idle, so tracking never competes with rendering. The 2-second timeout guarantees it still fires on busy pages.
  • keepalive: true on the fetch lets the request survive the user navigating away immediately.
  • The fired flag guards against Turbo reconnecting the controller and double-counting.

Crawlers fetch the HTML and move on. Real browsers run the beacon and get counted. View counts dropped sharply the day this deployed. That was the fix landing, not a regression.

Fix two: the bots found the beacon

Three days later, the tracking endpoint /track/events was the most-crawled path on the site. Crawlers do not execute JavaScript, but they do parse it. The endpoint URL sits in the markup as a data attribute, so the scrapers extracted it and started requesting it directly.

None of those requests created events, but they still burned through the full Rails stack for nothing. The fix was two cheap layers.

First, robots.txt for the well-behaved bots:

Second, a guard in the controller for everyone else:

class TrackingEventsController < ApplicationController
  before_action :reject_bots

  private

  def reject_bots
    head :no_content if DeviceDetector.new(request.user_agent).bot?
  end
end

Any request with a bot user agent gets a 204 before the action runs. No parsing, no resource lookups, no database work. The well-behaved crawlers respect robots.txt and never arrive, and the rest get the cheapest possible response.

The takeaway

Server-side analytics was built for a web that no longer exists. In 2026, a meaningful share of your traffic comes from AI crawlers, so counting views on the server measures scraper appetite, not audience.

The defense is not one clever trick. It is stacked cheap layers: robots.txt for the bots that ask permission, a user agent check that returns early for the ones that announce themselves, and a JavaScript beacon for the bots that do neither.

Check your own numbers. If your view counts have never had a suspicious cliff in them, the bot tax is probably still baked in.