Skip to content
CAI
Software that uses CAICheck a score

ankane/ahoy

68.8

Adequate · 26 September 2026

1.1k

lines of production code

Ruby

primary language

4

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This system is the Ahoy analytics gem, a library for tracking website and app visits and events. It provides server-side and client-side tracking capabilities, supporting multiple database backends like ActiveRecord and Mongoid, while handling device detection, bot filtering, and privacy-focused cookie-less options. The codebase includes comprehensive test coverage and generators to facilitate integration into Rails applications.

How it got here

2014 — Ahoy 5.0 architecture and dependency overhaul

10 changes.

This period focused on upgrading the Ahoy analytics library to version 5.0 and 5.5, introducing a modular architecture with cookie-less tracking, server-side defaults, and robust database storage. The work involved refactoring controllers and models to align with these new internal structures, updating installation generators for multiple storage backends, and upgrading client-side JavaScript and core runtime dependencies like Rails and Ruby.

2018–2024 — Test coverage and CI expansion

6 changes.

This period focused on establishing comprehensive test coverage for Ahoy's query methods across multiple database adapters, including Mongoid, MySQL, PostgreSQL, and SQLite. The work involved creating detailed test schemas, support infrastructure, and model definitions to ensure consistent behavior and compatibility. Additionally, CI support was expanded to include testing against Rails 7.2 and 8.0.

Behavioural changes

This release restructures the library into a modular \lib/ahoy\ namespace and shifts default behaviors to support modern tracking requirements. Geocoding is now disabled by default, and server-side visits are enabled by default. A new \Ahoy.cookies\ configuration allows users to disable cookie-based tracking entirely (set to \:none\) in exchange for a database index on \ahoy\_visits\, facilitating privacy-friendly, cookie-less analytics. The gem also introduces IP masking, configurable bot detection, and stricter defaults for content length and events per request.

lib · high confidence

Ahoy analytics library updated to version 5.5.0

The Ahoy analytics library has been upgraded to version 5.5.0. This release includes a complete rewrite of the internal storage and tracking architecture, introducing new base and database store classes to handle visit and event persistence more robustly. The update also refactors the controller integration to use request store for better thread safety, improves bot detection logic, and adds support for asynchronous geocoding via background jobs. Additionally, it enhances query methods for filtering events by properties across various database adapters (MySQL, PostgreSQL, SQLite) and ensures proper handling of cookies and tokens for both web and API contexts.

lib/ahoy · high confidence

Conditional API mounting and expanded event tracking routes

The Ahoy engine is now mounted conditionally at /ahoy only when the Ahoy.api configuration is enabled, allowing users to disable the API endpoint if not needed. Additionally, the engine's internal routes now explicitly scope visits and events resources under the 'ahoy' module, and a new route for creating events has been added alongside the existing visits route, enabling direct API-based event tracking.

config · high confidence

Refactored analytics controllers to use Ahoy::BaseController and simplified visit tracking

The analytics controllers have been restructured to inherit from a new Ahoy::BaseController, which centralizes common logic such as skipping application filters, enforcing request size limits, validating required parameters, and managing cookie renewal. The VisitsController has been significantly simplified: instead of manually instantiating and populating an Ahoy::Visit object with browser, OS, device, and location data, it now delegates to ahoy.track\_visit, returning tokens directly. The EventsController now supports batch event submission via JSON, handles legacy single-event formats, and enforces maximum event counts per request, while also improving error handling for invalid JSON payloads.

app/controllers · high confidence

Refactored install generator to support ActiveRecord and Mongoid stores

The install generator has been restructured to allow users to choose between ActiveRecord and Mongoid as the data store for Ahoy events and visits. Instead of automatically generating a single migration, the generator now detects available dependencies (ActiveRecord or Mongoid) and prompts the user to select the desired store. Based on this selection, it invokes specific sub-generators (ahoy:activerecord, ahoy:mongoid, or ahoy:base) that handle the appropriate model files, initializers, and migrations. This change also introduces support for the Trilogy database adapter and ensures generated migrations respect the application's primary key type configuration.

lib/generators/ahoy · high confidence

Removal of custom Ahoy Visit model override

The custom \Ahoy::Visit\ model class has been removed from the application. This eliminates the local override that previously defined a polymorphic \belongs\_to :user\ association, reverting the visit tracking behavior to the default provided by the Ahoy gem.

app/models · high confidence

Updated generator templates for Ahoy 3.0 with expanded tracking fields and disabled geocoding

The generator templates for ActiveRecord and Mongoid have been updated to reflect Ahoy 3.0 changes, including the addition of latitude, longitude, UTM parameters, and native app fields (app\_version, os\_version, platform) to the visit model. The migration templates now use datetime types and include specific indexes for performance. Geocoding is disabled by default in the generated initializers, and the old install template has been removed in favor of the new Thor-based templates.

lib/generators/ahoy/templates · high confidence

Test coverage

Add CI support for Rails 7.2 and 8.0; Added test configuration for multi-database support and health checks; Added test coverage for query methods across multiple database adapters; Added test database schema for analytics and user tracking; Added test support infrastructure for database-specific query method validation; Added test support models for Ahoy analytics and product tracking; Expanded test coverage for Ahoy analytics integration.

Dependencies

Updated Ahoy.js to v0.4.5

The vendorized Ahoy.js analytics library has been upgraded from version 0.0.1 to 0.4.5. This major update introduces a configurable API via \ahoy.configure()\, supports sending visit and visitor tokens in the request body or headers, and utilizes \navigator.sendBeacon\ for more reliable event tracking. It also adds support for custom cookie domains, anonymous tracking options, and improved compatibility with modern browsers and module loaders.

vendor · high confidence

Upgrade to Rails 8.1 and Ruby 3.3 with new device detection support

This release updates the gem's runtime dependencies to require Ruby 3.3+ and Rails 7.2+, with development testing configured for Rails 8.1. It introduces a new \device\_detector\ dependency to replace the legacy user agent parser, enabling more accurate device detection. The gem also adds explicit dependencies on \activesupport\, \cgi\, and \safely\_block\, while removing the \geocoder\ gem from the default runtime dependencies to make geocoding optional.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.

Score

  • CAI 48 → 69 (+20.6)
  • Rubric changed (rubric-2026.08.15 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 100 → 97 (-2.9)
  • Architecture 69 → 69 (+0.0)
  • Maturity 63 → 63 (+0.0)
  • Readiness 26 → 65 (+38.9)
  • Security 68 → 100 (+32.3)

Resolved (11)

  • Coverage not measured — test suite did not build
  • Dimension evaluation failed
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • No exposed public API
  • No tests found
  • Test reliability not included

New (16)

  • Banned license: device_detector
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • Inconsistent parameter naming and type for authentication. BaseStore expects a generic data object, while Tracker expects a specific user object. This implies different internal handling or expectations for what constitutes 'authentication data' between the low-level store and the high-level tracker.
  • Inconsistent parameter signatures for the same logical operation. BaseStore and DatabaseStore accept a single data object, while Tracker accepts two distinct arguments defer and started_at. This forces consumers to know which interface they are calling to construct the correct arguments.
  • Inconsistent return value intent or parameter usage. While the signature looks identical, DatabaseStore.visit(started_at) (from the constructor/impl list) suggests it might take arguments in some contexts or versions, whereas BaseStore and Tracker show no arguments. More critically, DatabaseStore has visit_or_create(started_at) while BaseStore and Tracker have visit_or_create() with no arguments. This inconsistency in arity for the same logical 'get or create' operation is confusing.
  • No dependency advisory monitoring
  • TodoComment (app/controllers/ahoy/events_controller.rb)
  • TodoComment (lib/ahoy.rb)
  • TooManyMethods: Tracker (lib/ahoy/tracker.rb)
  • VisitProperties.tech_properties (cognitive 16) (lib/ahoy/visit_properties.rb)
  • Workflow token permissions not restricted

Changes since last survey

  • 3 commits — 3 feature/other, 0 fixes

By area

  • (root) — 2 commits
  • .github/workflows — 1 commit

Notable commits

  • change: Removed unneeded line
  • change: Updated checkout action [skip ci]
  • change: Updated comment [skip ci]

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

ankane/ahoy was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 26 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 7cd30eeb4baf54a737ed4ecccf4fc1fa22f80ff7 — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-7c1cb6328e11.