Skip to content
CAI
Software that uses CAICheck a score

ankane/ahoy_email

67.0

Adequate · 20 September 2026

782

lines of production code

Ruby

primary language

1

measurement over time

CAI band scale
CAI lens gauges

What this system is

Ahoy Email is a Ruby gem that tracks email engagement by injecting tracking pixels for opens and secure, signed URLs for clicks. It provides a modular architecture with configurable subscribers to store analytics data in databases or Redis, supporting both ActiveRecord and Mongoid. The system handles UTM parameter parsing, message history, and user association while enforcing security through HMAC signature verification.

How it got here

2014 — AhoyEmail v4.0.0 architectural rewrite

8 changes.

This period marked the release of AhoyEmail v4.0.0, featuring a major architectural overhaul that replaced the legacy interceptor-based system with a modular, subscriber-based tracking architecture. The update introduced robust HMAC-SHA256 security for email click tracking, added dedicated models for clicks and messages, and enforced stricter compatibility requirements by dropping support for older Ruby and Rails versions.

2015–2018 — comprehensive test suite implementation

4 changes.

This period focused on establishing a robust testing infrastructure for the email tracking and analytics library. It involved creating a comprehensive suite of integration and unit tests covering click tracking, UTM parameter handling, and campaign statistics across various database backends like SQLite and MongoDB. The work also included setting up internal test fixtures and configuration files to ensure reliable verification of core functionality.

2021–2022 — Mongoid and encryption support

4 changes.

This period focused on expanding Ahoy's compatibility by adding generators for Mongoid as an alternative data store alongside Active Record. It also introduced experimental support for encrypting message data using Active Record's built-in encryption or Lockbox. Additionally, CI infrastructure was updated to test against Rails 8.0 and newer Mongoid versions.

Features

New generators for Ahoy messages with encryption support

The \ahoy:messages\ generator now supports creating the \Ahoy::Message\ model and migration with optional encryption using either Active Record's built-in encryption or Lockbox. Users can specify the encryption method via the \--encryption\ flag (accepting \lockbox\, \activerecord\, or \none\). The generated migration includes primary key and foreign key type configurations compatible with modern Rails versions, and the model templates apply the appropriate encryption directives (e.g., \encrypts\ or \has\_encrypted\) to the \to\ field, ensuring secure storage of recipient addresses.

lib/generators/ahoy/messages · high confidence

Support for custom primary key types and Mongoid in click tracking migrations

The generator for the \ahoy\_clicks\ table now respects the application's configured primary key type (e.g., \:uuid\ or \:bigint\) when creating the ActiveRecord migration, ensuring consistency with modern Rails defaults. Additionally, a new Mongoid generator has been added, allowing users to generate a \Ahoy::Click\ model for MongoDB-based applications instead of using ActiveRecord.

lib/generators/ahoy/clicks · high confidence

Removals

Removed legacy install generator for Ahoy Email

The \InstallGenerator\ class, which previously handled the creation of the \create\_ahoy\_messages\ migration for older Rails versions, has been removed. Users relying on this specific generator to set up database migrations will no longer have this automated path available, reflecting a shift away from supporting legacy Rails versions like 4.2.

_lib/generators/ahoy\email · high confidence

Behavioural changes

Added Click model and updated Message model for email tracking

A new Ahoy::Click model has been introduced to track email clicks, mapping to the 'ahoy\_clicks' database table. The existing Ahoy::Message model has been updated to explicitly set its table name to 'ahoy\_messages' and now includes an optional, polymorphic belongs\_to association with the User model, allowing messages to be linked to various user types without requiring a user record.

app/models · high confidence

AhoyEmail v4.0.0: Major rewrite with new tracking architecture and HMAC-SHA256 security

This release introduces a complete architectural overhaul of the email tracking system. The legacy \Interceptor\ has been removed and replaced with a new \Mailer\ concern that uses \after\_action\ callbacks to process emails, allowing for more granular control via \has\_history\, \utm\_params\, and \track\_clicks\ class methods. Tracking is now handled by dedicated subscribers (\DatabaseSubscriber\, \RedisSubscriber\, \MessageSubscriber\) that decouple storage logic, supporting both ActiveRecord and Mongoid. Security has been strengthened by transitioning to HMAC-SHA256 for link signatures, removing support for legacy secret token generation, and enforcing strict keyword validation for options. The processor now defaults to HTML5 parsing when available and only tracks absolute HTTP/HTTPS links, while UTM parameters are stored on the message model rather than being included in links by default.

_lib/ahoy\email · high confidence

Configurable API mode and new click tracking routes

The engine's routing is now conditional: the main mount point at /ahoy is only active when the new AhoyEmail.api configuration option is enabled, allowing users to disable the API entirely. Additionally, the engine now exposes a dedicated /ahoy/click route for tracking email clicks, while retaining legacy /ahoy/messages/:id/open and /ahoy/messages/:id/click routes for backward compatibility.

config · high confidence

Enhanced email click tracking with signature verification and open redirect protection

The MessagesController now implements a robust \click\ action that verifies URL signatures using HMAC to prevent open redirects, falling back to a configurable invalid redirect URL or a 404 error if verification fails. It supports both legacy and new parameter formats for tracking clicks, publishes click events to subscribers, and skips unnecessary application controller filters to ensure reliable tracking. The \open\ action has been updated to serve a transparent GIF for open tracking instead of logging to stdout.

app/controllers · high confidence

Major architectural overhaul of email tracking and configuration

The library has been refactored from a simple interceptor-based approach to a modular, subscriber-based architecture. This change replaces the previous \AhoyEmail::Interceptor\ with new \Observer\, \Processor\, and \Tracker\ components, allowing for more flexible event handling via \database\_subscriber\, \message\_subscriber\, and \redis\_subscriber\. Configuration is now centralized in \AhoyEmail\ with explicit accessors for \secret\_token\, \default\_options\, \subscribers\, and \track\_method\, enabling users to customize UTM parameters, click analytics, and message history storage more granularly. The dependency list has also expanded to include \nokogiri\, \addressable\, and \safely\, reflecting the new parsing and error-handling capabilities.

lib · high confidence

Removed default email tracking migration template

The default installation migration template for the \ahoy\_messages\ table has been removed from the generator. This means that running the installer will no longer automatically create the database schema for tracking email metrics such as opens, clicks, and content, requiring users to manually define or opt-in to this tracking structure if needed.

_lib/generators/ahoy\email/templates · high confidence

Support for Mongoid and Active Record encryption in Ahoy generators

The Ahoy installation generators for clicks and messages now support Mongoid as an alternative data store alongside Active Record. When both libraries are present, users are prompted to choose between Active Record (default) and Mongoid. Additionally, the messages generator includes experimental support for Active Record encryption via a new \--encryption\ option, while retaining the deprecated \--unencrypted\ flag for backward compatibility.

lib/generators/ahoy · high confidence

Test coverage

Added Mongoid test support files; Added comprehensive test suite for email tracking and analytics; Added internal test infrastructure for database schema and configuration; Added test fixtures for mailer tracking and history features.

Dependencies

Added CI gemfiles for Rails 8.0 and Mongoid 8/9

New gemfiles have been added to the \gemfiles/\ directory to enable continuous integration testing against Rails 8.0.0 (via \actionmailer80.gemfile\ and \actionmailer72.gemfile\) and Mongoid 8 and 9 (via \mongoid8.gemfile\ and \mongoid9.gemfile\). These files define the specific dependency versions required to run the test suite against these newer framework and library versions.

gemfiles · high confidence

Updated dependencies and raised minimum Ruby/Rails versions

The gem now requires Ruby 3.3 or higher and depends on Action Mailer 7.2 or newer, dropping support for older versions. Development dependencies have been explicitly added to the Gemfile (including Rake, Minitest, Action Mailer 8.1, ActiveRecord 8.1, Combustion, SQLite3, and Redis) to streamline local testing and CI, while the gemspec itself now lists specific runtime dependencies for Addressable, Nokogiri, and Safely Block.

(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

Baseline

  • First survey — no prior run to compare against. CAI 67.

Lenses

  • Code Health 99
  • Architecture 69
  • Maturity 55
  • Readiness 70
  • Security 98
  • Domain Modelling 100

Changes since last survey

  • 300 commits — 268 feature/other, 32 fixes

By area

  • (root) — 155 commits
  • lib/ahoy_email — 34 commits
  • .github/workflows — 16 commits
  • test/click_test.rb — 13 commits
  • test/internal — 13 commits
  • lib/ahoy_email.rb — 10 commits
  • lib/generators — 9 commits
  • app/controllers — 7 commits
  • (repo) — 6 commits
  • test/support — 5 commits
  • test/message_test.rb — 4 commits
  • test/test_helper.rb — 4 commits
  • test/gemfiles — 3 commits
  • test/mailer_test.rb — 3 commits
  • test/utm_params_test.rb — 3 commits
  • gemfiles/mongoid9.gemfile — 2 commits
  • test/clicks_generator_test.rb — 2 commits
  • test/messages_generator_test.rb — 2 commits
  • test/subscriber_test.rb — 2 commits
  • .github/ISSUE_TEMPLATE — 1 commit

Notable commits

  • fix: Fix incorrect reconstruction of emails with <head> elements (#150)
  • fix: Fix sprockets error on Travis
  • fix: Fixed CI
  • fix: Fixed CI
  • fix: Fixed CI
  • fix: Fixed CI
  • fix: Fixed CI
  • fix: Fixed CI
  • fix: Fixed CI
  • fix: Fixed UTM parameters storage on model
  • fix: Fixed bundler resolution
  • fix: Fixed change to key generator hash digest class - #168
  • fix: Fixed custom message model - fixes #115
  • fix: Fixed deprecation warning with Rails 7.1 - fixes #164
  • fix: Fixed deprecation warning with Redis 4.6+
  • fix: Fixed error with attr_accessor being private in earlier versions of Ruby - fixes #114
  • fix: Fixed external redirects with Rails 7 - fixes #154
  • fix: Fixed issue with Mailkick and SECRET_KEY_BASE_DUMMY with Rails 7.1
  • fix: Fixed link [skip ci]
  • fix: Fixed message option with proc
  • …and 280 more

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_email 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 20 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 f997633d7243d9810fddc04a9824e1bb7253a18a — 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-b51f968c9b10.