Skip to content

Commit

Permalink
Merge pull request sendgrid#234 from awinabi/stats-helpers
Browse files Browse the repository at this point in the history
Helpers for email statistics - global, category, subuser
  • Loading branch information
thinkingserious authored Oct 31, 2017
2 parents 52cd634 + a514fc5 commit 42e6a49
Show file tree
Hide file tree
Showing 8 changed files with 391 additions and 0 deletions.
42 changes: 42 additions & 0 deletions examples/helpers/stats/example.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require 'sendgrid-ruby'
require 'date'

include SendGrid

sg_client = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY']).client
stats = SendGrid::EmailStats.new(sendgrid_client: sg_client)

# Fetch stats by day, between 2 dates
from = Date.new(2017, 10, 01)
to = Date.new(2017, 10, 12)

email_stats = stats.by_day(from, to)

email_stats.metrics

if !email_stats.error?
email_stats.metrics.each do |metric|
puts "Date - #{metric.date}"
puts "Number of Requests - #{metric.requests}"
puts "Bounces - #{metric.bounces}"
puts "Opens - #{metric.opens}"
puts "Clicks - #{metric.clicks}"
end
end

# Fetch stats by week, between 2 dates for a category
from = Date.new(2017, 10, 01)
to = Date.new(2017, 10, 12)
category = 'abcd'

email_stats = stats.by_week(from, to, category)

if !email_stats.error?
email_stats.metrics.each do |metric|
puts "Date - #{metric.date}"
puts "Number of Requests - #{metric.requests}"
puts "Bounces - #{metric.bounces}"
puts "Opens - #{metric.opens}"
puts "Clicks - #{metric.clicks}"
end
end
3 changes: 3 additions & 0 deletions lib/sendgrid-ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@
require_relative 'sendgrid/helpers/mail/substitution'
require_relative 'sendgrid/helpers/mail/tracking_settings'
require_relative 'sendgrid/helpers/settings/settings'
require_relative 'sendgrid/helpers/stats/email_stats'
require_relative 'sendgrid/helpers/stats/stats_response'
require_relative 'sendgrid/helpers/stats/metrics'
46 changes: 46 additions & 0 deletions lib/sendgrid/helpers/stats/email_stats.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require 'json'

module SendGrid
class EmailStats
def initialize(args)
@sendgrid_client = args[:sendgrid_client]
end

def by_day(start_date, end_date, categories = nil, subusers = nil)
get('day', start_date, end_date, categories, subusers)
end

def by_week(start_date, end_date, categories = nil, subusers = nil)
get('week', start_date, end_date, categories, subusers)
end

def by_month(start_date, end_date, categories = nil, subusers = nil)
get('month', start_date, end_date, categories, subusers)
end

def get(aggregated_by, start_date, end_date, categories = nil, subusers = nil)
params = query_params(aggregated_by, start_date, end_date, categories, subusers)

response_body = @sendgrid_client.stats.get(query_params: params).body
build_response(response_body)
end

private

def query_params(aggregated_by, start_date, end_date, categories, subusers)
params = {
aggregated_by: aggregated_by,
start_date: start_date,
end_date: end_date
}
params.merge(categories: categories) if categories
params.merge(subusers: subusers) if subusers
params
end

def build_response(response_body)
response_json = JSON.parse(response_body)
StatsResponse.new(response_json)
end
end
end
35 changes: 35 additions & 0 deletions lib/sendgrid/helpers/stats/metrics.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
require 'json'

module SendGrid
class Metrics
attr_reader :blocks, :bounce_drops,
:bounces, :clicks, :deferred, :delivered,
:invalid_emails, :opens, :processed, :requests,
:spam_report_drops, :spam_reports, :unique_clicks,
:unique_opens, :unsubscribe_drops, :unsubscribes

def initialize(args={})
@date = args['date']
@blocks = args['blocks']
@bounce_drops = args['bounce_drops']
@bounces = args['bounces']
@clicks = args['clicks']
@deferred = args['deferred']
@delivered = args['delivered']
@invalid_emails = args['invalid_emails']
@opens = args['opens']
@processed = args['processed']
@requests = args['requests']
@spam_report_drops = args['spam_report_drops']
@spam_reports = args['spam_reports']
@unique_clicks = args['unique_clicks']
@unique_opens = args['unique_opens']
@unsubscribe_drops = args['unsubscribe_drops']
@unsubscribes = args['unsubscribes']
end

def date
Date.parse(@date)
end
end
end
31 changes: 31 additions & 0 deletions lib/sendgrid/helpers/stats/stats_response.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require 'json'

module SendGrid
class StatsResponse
def initialize(args)
@errors = args['errors'] if args.is_a? Hash
@stats = args if args.is_a? Array
end

def errors
@errors.map do |error|
error['message']
end
end

def error?
!@errors.nil?
end

def metrics
@stats.flat_map do |stat|
starting_date = stat['date']
all_stats_for_date = stat['stats']

metrics = all_stats_for_date.map do |metric|
Metrics.new(metric['metrics'].merge('date' => starting_date))
end
end
end
end
end
112 changes: 112 additions & 0 deletions spec/sendgrid/helpers/stats/email_stats_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
require 'spec_helper'

describe SendGrid::EmailStats do
let(:sg_client) { SendGrid::API.new(api_key: 'abcd').client }
let(:stats) { SendGrid::EmailStats.new(sendgrid_client: sg_client) }
let(:sg_response) { double('SendGrid::Response') }

let(:sample_response) do
[{
"date" => "2017-10-01",
"stats" => [
{"metrics" =>
{
"blocks" => 101,
"bounce_drops" => 102,
"bounces" => 103,
"clicks" => 104,
"deferred" => 105,
"delivered" => 106,
"invalid_emails" => 107,
"opens" => 108,
"processed" => 109,
"requests" => 110,
"spam_report_drops" => 111,
"spam_reports" => 112,
"unique_clicks" => 113,
"unique_opens" => 114,
"unsubscribe_drops" => 115,
"unsubscribes" => 116
}
}
]
}]
end

let(:error_response) do
{
"errors" => [
{
"message" => "end_date should be a YYYY-MM-DD formatted date"
}
]
}
end

describe '.new' do
it 'initializes with SendGrid::Client' do
expect(stats).to be_a SendGrid::EmailStats
end
end

describe 'successful response' do
before do
allow_any_instance_of(SendGrid::Response).to receive(:body) { sample_response.to_json }
end

describe '#by_day' do
it 'fetches data aggregated by day' do
day_stats = stats.by_day('2017-10-01', '2017-10-02')
day_metrics = day_stats.metrics.first

expect(day_metrics).to be_a SendGrid::Metrics
expect(day_metrics.date.to_s).to eq('2017-10-01')
expect(day_metrics.requests).to eq(110)
expect(day_metrics.clicks).to eq(104)
expect(day_metrics.bounces).to eq(103)
expect(day_metrics.opens).to eq(108)
end
end

describe '#by_week' do
it 'fetches data aggregated by week' do
day_stats = stats.by_week('2017-10-01', '2017-10-12')
day_metrics = day_stats.metrics.first

expect(day_metrics).to be_a SendGrid::Metrics
expect(day_metrics.date.to_s).to eq('2017-10-01')
expect(day_metrics.requests).to eq(110)
expect(day_metrics.clicks).to eq(104)
expect(day_metrics.bounces).to eq(103)
expect(day_metrics.opens).to eq(108)
end
end

describe '#by_month' do
it 'fetches data aggregated by month' do
day_stats = stats.by_month('2017-10-01', '2017-11-01')
day_metrics = day_stats.metrics.first

expect(day_metrics).to be_a SendGrid::Metrics
expect(day_metrics.date.to_s).to eq('2017-10-01')
expect(day_metrics.requests).to eq(110)
expect(day_metrics.clicks).to eq(104)
expect(day_metrics.bounces).to eq(103)
expect(day_metrics.opens).to eq(108)
end
end
end

describe 'error response' do
before do
allow_any_instance_of(SendGrid::Response).to receive(:body) { error_response.to_json }
end

it 'fetches data aggregated by month' do
day_stats = stats.by_month('2017-10-01', '2017-10-02')

expect(day_stats.errors).to include('end_date should be a YYYY-MM-DD formatted date')
expect(day_stats.error?).to be_truthy
end
end
end
46 changes: 46 additions & 0 deletions spec/sendgrid/helpers/stats/metrics_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require 'spec_helper'

describe SendGrid::Metrics do
let(:params) do
{
"date" => "2017-10-01",
"blocks" => 101,
"bounce_drops" => 102,
"bounces" => 103,
"clicks" => 104,
"deferred" => 105,
"delivered" => 106,
"invalid_emails" => 107,
"opens" => 108,
"processed" => 109,
"requests" => 110,
"spam_report_drops" => 111,
"spam_reports" => 112,
"unique_clicks" => 113,
"unique_opens" => 114,
"unsubscribe_drops" => 115,
"unsubscribes" => 116
}
end

subject { described_class.new(params) }

it 'initializes with metric parameters' do
expect(subject).to be_a SendGrid::Metrics
end

it 'returns date as object' do
expect(subject.date).to be_a Date
end

%w(
blocks bounce_drops bounces clicks deferred delivered invalid_emails
opens processed requests spam_report_drops spam_reports unique_clicks
unique_opens unsubscribe_drops unsubscribes
).each do |attribute|
it "responds to #{attribute}" do
expect(subject).to respond_to(attribute.to_sym)
end
end

end
Loading

0 comments on commit 42e6a49

Please sign in to comment.