Coder Social home page Coder Social logo

ahoy_email's Introduction

Ahoy Email

📮 Email analytics for Rails

You get:

  • A history of emails sent to each user
  • Easy UTM tagging
  • Optional open and click tracking

Ahoy Email 1.0 was recently released! See how to upgrade

🚄 To manage unsubscribes, check out Mailkick

🔥 To track visits and events, check out Ahoy

Build Status

Installation

Add this line to your application’s Gemfile:

gem 'ahoy_email'

And run the generator. This creates a model to store messages.

rails generate ahoy_email:install
rails db:migrate

How It Works

Message History

Ahoy creates an Ahoy::Message record for each email sent by default. You can disable history for a mailer:

class CouponMailer < ApplicationMailer
  track message: false # use only/except to limit actions
end

Or by default:

AhoyEmail.default_options[:message] = false

Users

Ahoy records the user a message is sent to - not just the email address. This gives you a full history of messages for each user, even if he or she changes addresses.

By default, Ahoy tries @user then params[:user] then User.find_by(email: message.to.first) to find the user.

You can pass a specific user with:

class CouponMailer < ApplicationMailer
  track user: -> { params[:some_user] }
end

The user association is polymorphic, so use it with any model.

To get all messages sent to a user, add an association:

class User < ApplicationRecord
  has_many :messages, class_name: "Ahoy::Message", as: :user
end

And run:

user.messages

Extra Attributes

Record extra attributes on the Ahoy::Message model.

Create a migration to add extra attributes to the ahoy_messages table. For example:

class AddCouponIdToAhoyMessages < ActiveRecord::Migration[5.2]
  def change
    add_column :ahoy_messages, :coupon_id, :integer
  end
end

Then use:

class CouponMailer < ApplicationMailer
  track extra: {coupon_id: 1}
end

You can use a proc as well.

class CouponMailer < ApplicationMailer
  track extra: -> { {coupon_id: params[:coupon].id} }
end

UTM Tagging

Automatically add UTM parameters to links.

class CouponMailer < ApplicationMailer
  track utm_params: true # use only/except to limit actions
end

The defaults are:

  • utm_medium - email
  • utm_source - the mailer name like coupon_mailer
  • utm_campaign - the mailer action like offer

You can customize them with:

class CouponMailer < ApplicationMailer
  track utm_params: true, utm_campaign: -> { "coupon#{params[:coupon].id}" }
end

Skip specific links with:

<%= link_to "Go", some_url, data: {skip_utm_params: true} %>

Opens & Clicks

Setup

Additional setup is required to track opens and clicks.

Create a migration with:

class AddTokenToAhoyMessages < ActiveRecord::Migration[5.2]
  def change
    add_column :ahoy_messages, :token, :string
    add_column :ahoy_messages, :opened_at, :timestamp
    add_column :ahoy_messages, :clicked_at, :timestamp

    add_index :ahoy_messages, :token
  end
end

Create an initializer config/initializers/ahoy_email.rb with:

AhoyEmail.api = true

And add to mailers you want to track:

class CouponMailer < ApplicationMailer
  track open: true, click: true # use only/except to limit actions
end

How It Works

For opens, an invisible pixel is added right before the </body> tag in HTML emails. If the recipient has images enabled in their email client, the pixel is loaded and the open time recorded.

For clicks, a redirect is added to links to track clicks in HTML emails.

https://chartkick.com

becomes

https://yoursite.com/ahoy/messages/rAnDoMtOkEn/click?url=https%3A%2F%2Fchartkick.com&signature=...

A signature is added to prevent open redirects.

Skip specific links with:

<%= link_to "Go", some_url, data: {skip_click: true} %>

By default, unsubscribe links are excluded. To change this, use:

AhoyEmail.default_options[:unsubscribe_links] = true

You can specify the domain to use with:

AhoyEmail.default_options[:url_options] = {host: "mydomain.com"}

Events

Subscribe to open and click events by adding to the initializer:

class EmailSubscriber
  def open(event)
    # your code
  end

  def click(event)
    # your code
  end
end

AhoyEmail.subscribers << EmailSubscriber.new

Here’s an example if you use Ahoy to track visits and events:

class EmailSubscriber
  def open(event)
    event[:controller].ahoy.track "Email opened", message_id: event[:message].id
  end

  def click(event)
    event[:controller].ahoy.track "Email clicked", message_id: event[:message].id, url: event[:url]
  end
end

AhoyEmail.subscribers << EmailSubscriber.new

Reference

Set global options

AhoyEmail.default_options[:user] = -> { params[:admin] }

Use a different model

AhoyEmail.message_model = -> { UserMessage }

Or fully customize how messages are tracked

AhoyEmail.track_method = lambda do |data|
  # your code
end

Mongoid

If you prefer to use Mongoid instead of ActiveRecord, create app/models/ahoy/message.rb with:

class Ahoy::Message
  include Mongoid::Document

  belongs_to :user, polymorphic: true, optional: true, index: true

  field :to, type: String
  field :mailer, type: String
  field :subject, type: String
  field :sent_at, type: Time
end

Upgrading

1.0

Breaking changes

  • UTM tagging, open tracking, and click tracking are no longer enabled by default. To enable, create an initializer with:

    AhoyEmail.api = true
    
    AhoyEmail.default_options[:open] = true
    AhoyEmail.default_options[:click] = true
    AhoyEmail.default_options[:utm_params] = true
  • Only sent emails are recorded

  • Proc options are now executed in the context of the mailer and take no arguments

    # old
    user: ->(mailer, message) { User.find_by(email: message.to.first) }
    
    # new
    user: -> { User.find_by(email: message.to.first) }
  • Invalid options now throw an ArgumentError

  • AhoyEmail.track was removed in favor of AhoyEmail.default_options

  • The heuristic_parse option was removed and is now the default

History

View the changelog

Contributing

Everyone is encouraged to help improve this project. Here are a few ways you can help:

ahoy_email's People

Contributors

12eh avatar ajb avatar ankane avatar benreyn avatar chenhoward avatar dlackty avatar fabn avatar fluke avatar gdpelican avatar georgedrummond avatar joshdover avatar kieranklaassen avatar marzapower avatar mbreit avatar milgner avatar noahpryor avatar raulsouzalima avatar rememberlenny avatar sbeckeriv avatar suaron avatar tonkpils avatar tyrauber avatar wflanagan avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.