Skip to content

Instantly share code, notes, and snippets.

@gampleman
Last active June 19, 2020 21:34
Adding tracking to emails in Rails

This gist illustrates how you would add Google Analytics tracking into your Rails mailers. Add the tracking_interceptor.rb into your path and enable it for your mailers with:

register_interceptor TrackingInterceptor
class TrackingInterceptor
def self.delivering_email(email)
if email.html_part
ERB::Util.url_encode
# Open Tracking
# @see http://dyn.com/blog/tracking-email-opens-via-google-analytics/
tracking_img = '<img src="http://www.google-analytics.com/collect?v=1'
tracking_img << '&tid=' + Rails.application.config.ga_account_id # Analytics tracking ID
tracking_img << '&cid=' + email.to.first.hash.to_s # Id identifying user, but need to not be personally identifying
tracking_img << '&t=event' # Tells Google Analytics this is an Event Hit Type
tracking_img << '&ec=Email' # The Event Category helps segment various events
tracking_img << '&ea=Open' # The Event Action helps specify exactly what happened
tracking_img << '&el=' + ERB::Util.url_encode label # Event Label specifies a unique identification for this event
tracking_img << '&cs=' + ERB::Util.url_encode campaign_source # Campaign Source allows segmentation of campaign types
tracking_img << '&cm=email' # Campaign Medium could segment social vs. email, etc.
tracking_img << '&cn=' + ERB::Util.url_encode capaign_name # Campaign Name identifies the campaign to you
tracking_img << '" />'
email.html_part.body.raw_source.gsub!(/(?=<\/body>)/, tracking_img.html_safe) # Assumes that the email has proper body tags
# Click Tracking
# @see http://www.smartinsights.com/email-marketing/email-marketing-analytics/email-campaign-tracking-with-google-analytics/
tracking_params = "utm_medium=email&utm_campaign=#{ERB::Util.url_encode capaign_name}&utm_source=#{ERB::Util.url_encode campaign_source}"
email.html_part.body.raw_source.gsub!(/href=".+?(?=")/) do |link|
if link =~ /\?/
link + '&' + tracking_params
else
link + '?' + tracking_params
end
end
end
end
end
@srghma
Copy link

srghma commented Sep 8, 2018

My take

module Helpers
  module MailAddGoogleAnalyticsTraking
    extend self

    def mail_add_google_analytics_traking(mail, ga_account_id:, label:, campaign_name:, campaign_source:)
      substitute_html(mail) do |old_html|
        user_email = mail.to
        mail_content_add_google_analytics_traking(old_html, user_email, ga_account_id, label, campaign_name, campaign_source)
      end
    end

    def mail_content_add_google_analytics_traking(old_html, user_email:, ga_account_id:, label:, campaign_name:, campaign_source:)
      # Open Tracking
      # @see http://dyn.com/blog/tracking-email-opens-via-google-analytics/
      tracking_img_ = traking_img(
        ga_account_id:   ga_account_id,
        user_email:      user_email,
        label:           label,
        campaign_name:   campaign_name,
        campaign_source: campaign_source
      )

      new_html = old_html.gsub(%r{(?=<\/body>)}, tracking_img_.html_safe) # Assumes that the email has proper body tags

      # Click Tracking
      # @see http://www.smartinsights.com/email-marketing/email-marketing-analytics/email-campaign-tracking-with-google-analytics/
      url_tracking_query_ = url_tracking_query(
        campaign_name:   campaign_name,
        campaign_source: campaign_source
      )

      new_html.gsub!(/href=".+?(?=")/) do |link|
        if link.match?(/\?/)
          link + "&" + url_tracking_query_
        else
          link + "?" + url_tracking_query_
        end
      end

      new_html
    end

    private

    def traking_img(
      ga_account_id:,
      user_email:,
      label:,
      campaign_name:,
      campaign_source:
    )
      tracking_img = '<img src="//www.google-analytics.com/collect?v=1'
      tracking_img << "&tid=" + ga_account_id.to_s                   # Analytics tracking ID
      tracking_img << "&cid=" + user_email.first.hash.to_s           # Id identifying user, but need to not be personally identifying
      tracking_img << "&t=event"                                     # Tells Google Analytics this is an Event Hit Type
      tracking_img << "&ec=Email"                                    # The Event Category helps segment various events
      tracking_img << "&ea=Open"                                     # The Event Action helps specify exactly what happened
      tracking_img << "&el=" + ERB::Util.url_encode(label)           # Event Label specifies a unique identification for this event
      tracking_img << "&cs=" + ERB::Util.url_encode(campaign_source) # Campaign Source allows segmentation of campaign types
      tracking_img << "&cm=email"                                    # Campaign Medium could segment social vs. email, etc.
      tracking_img << "&cn=" + ERB::Util.url_encode(campaign_name)   # Campaign Name identifies the campaign to you
      tracking_img << '" />'
      tracking_img
    end

    def url_tracking_query(
      campaign_name:,
      campaign_source:
    )
      "utm_medium=email&utm_campaign=#{ERB::Util.url_encode(campaign_name)}&utm_source=#{ERB::Util.url_encode(campaign_source)}"
    end

    def substitute_html(mail)
      mail.tap do
        html_part = mail.html_part || mail
        old_html = html_part.body.to_s

        new_html = yield(old_html)

        html_part.body = new_html
      end
    end
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment