ankane/ahoy_email
67.0
Adequate · 20 September 2026
782
lines of production code
Ruby
primary language
1
measurement over time
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.