Skip to content

Instantly share code, notes, and snippets.

@gampleman
Last active June 19, 2020 21:34
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gampleman/11376233 to your computer and use it in GitHub Desktop.
Save gampleman/11376233 to your computer and use it in GitHub Desktop.
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