Mailgun and Your Rails App

There are a lot of email services that allow you to send emails and then look at statistics like open and click-through rates. It’s very easy to get these stats for yourself personally. However sometimes you want to give others access to them as well. It’s not like you can send around your email service password and let everyone check the dashboard whenever they’re curious. Here’s one way to make open and click-through rates available directly in your app.

Theoretically you could build all sorts of information tracking into the email itself. 1x1 pixel images that load when an email is opened so you can track email open rates. Custom urls to check click-thru rates. But since there are services that do this for you already, I’ll be using Mailgun here. According to Mailgun there are three ways to access the tracking data from your emails.

  1. Control Panel: There are summary tracking stats, tables with event details and campaign reports.

  2. HTTP API: You can programmatically access event data and tracking stats.

  3. Events: Mailgun can perform an HTTP request into your application when an event occurs.

The third one is of interest since it can send the data you want directly to your app. If you’re using SMTP already, you won’t even need to change your configuration much except to put in your Mailgun info. For the app I was working on, we needed to keep track of click-through rates for links that users emailed to other memebers in their group. So to start I somehow had to get Mailgun to perform an HTTP POST request whenever a specific event (link was clicked) occurred. This was actually pretty easy in Mailgun. You just provide them with a callback URL and then set that URL up as a route in your app that hits a specific event.

1
match '/email/mailgun' => 'stats#create'

Look at us using webhooks!

Now that the callback URL was set up we needed to somehow get the user ID and article ID passed from our app to Mailgun, to the email recipient, back to Mailgun, who would then send it back to us. There was no point in having statistics if we couldn’t tell who they were for. Reading through Mailgun’s documentation will reveal that there are custom MIME headers that can be used for this purpose. According to the documentation X-Mailgun-Variables can be used to attach custom JSON data to the message. So in the mailer you can manually set the variables in the header.

1
headers['X-Mailgun-Variables'] = {:article_id => @article.id, :user_id => user.id}.to_json

Now when the event triggers the HTTP POST request to our app we can access the ID of the user the email was sent to as well as the ID of the article they were sent so we can save that data in our database.

1
2
3
4
5
6
7
8
9
10
11
  def create
    event = params[:event]
    if event == 'opened'
      stats = Stat.where(:user_id => params[:user_id], :article_id => params[:article_id]).first
      stats.opens = 1
    elsif event == 'clicked'
      stats = Stat.where(:user_id => params[:user_id], :article_id => params[:article_id]).first
      stats.clicks = 1
    end
    stats.save
  end

Once the data is saved, we’re able to access it anytime and display it for users who now know exactly who has and hasn’t clicked the link in the email they were sent.