This repository has been archived by the owner on Apr 4, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 627dc61
Showing
6 changed files
with
253 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
source 'https://rubygems.org' | ||
|
||
gem 'actionmailer', '3.2.12' | ||
gem 'oauth' | ||
gem 'garb' | ||
gem 'terminal-table' | ||
gem 'aws-ses', '0.4.4', :require => 'aws/ses' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
GEM | ||
remote: https://rubygems.org/ | ||
specs: | ||
actionmailer (3.2.12) | ||
actionpack (= 3.2.12) | ||
mail (~> 2.4.4) | ||
actionpack (3.2.12) | ||
activemodel (= 3.2.12) | ||
activesupport (= 3.2.12) | ||
builder (~> 3.0.0) | ||
erubis (~> 2.7.0) | ||
journey (~> 1.0.4) | ||
rack (~> 1.4.5) | ||
rack-cache (~> 1.2) | ||
rack-test (~> 0.6.1) | ||
sprockets (~> 2.2.1) | ||
activemodel (3.2.12) | ||
activesupport (= 3.2.12) | ||
builder (~> 3.0.0) | ||
activesupport (3.2.12) | ||
i18n (~> 0.6) | ||
multi_json (~> 1.0) | ||
aws-ses (0.4.4) | ||
builder | ||
mail (> 2.2.5) | ||
mime-types | ||
xml-simple | ||
builder (3.0.4) | ||
crack (0.3.2) | ||
erubis (2.7.0) | ||
garb (0.9.1) | ||
activesupport (>= 2.2.0) | ||
crack (>= 0.1.6) | ||
hike (1.2.1) | ||
i18n (0.6.4) | ||
journey (1.0.4) | ||
mail (2.4.4) | ||
i18n (>= 0.4.0) | ||
mime-types (~> 1.16) | ||
treetop (~> 1.4.8) | ||
mime-types (1.21) | ||
multi_json (1.6.1) | ||
oauth (0.4.7) | ||
polyglot (0.3.3) | ||
rack (1.4.5) | ||
rack-cache (1.2) | ||
rack (>= 0.4) | ||
rack-test (0.6.2) | ||
rack (>= 1.0) | ||
sprockets (2.2.2) | ||
hike (~> 1.2) | ||
multi_json (~> 1.0) | ||
rack (~> 1.0) | ||
tilt (~> 1.1, != 1.3.0) | ||
terminal-table (1.4.5) | ||
tilt (1.3.4) | ||
treetop (1.4.12) | ||
polyglot | ||
polyglot (>= 0.3.1) | ||
xml-simple (1.1.2) | ||
|
||
PLATFORMS | ||
ruby | ||
|
||
DEPENDENCIES | ||
actionmailer (= 3.2.12) | ||
aws-ses (= 0.4.4) | ||
garb | ||
oauth | ||
terminal-table |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
require 'oauth' | ||
require 'garb' | ||
require 'active_support/core_ext' | ||
|
||
class MainVisits | ||
extend Garb::Model | ||
|
||
metrics :pageviews, :unique_pageviews, :avg_time_on_page | ||
dimensions :page_path, :page_title | ||
end | ||
|
||
class Overview | ||
extend Garb::Model | ||
|
||
metrics :visitors, :new_visits | ||
end | ||
|
||
module AnalyticsUtils | ||
def percentage_change(from, to) | ||
change = 100 * (to.to_f - from.to_f) / from.to_f | ||
change = change.round(2) | ||
if change > 0 | ||
"+#{change}" | ||
else | ||
change.to_s | ||
end | ||
end | ||
end | ||
|
||
class AnalyticsInterface | ||
|
||
attr_accessor :profile, :property, :oauth_token, :oauth_secret | ||
|
||
def initialize(analytics_id, oauth_token, oauth_secret) | ||
establish_garb_session | ||
self.property = Garb::Management::WebProperty.all.detect { |p| p.id == analytics_id } | ||
self.profile = Garb::Management::Profile.all.detect { |p| p.web_property_id == analytics_id } | ||
self.oauth_token = oauth_token | ||
self.oauth_secret = oauth_secret | ||
end | ||
|
||
def weekly_stats | ||
yesterday = Date.yesterday | ||
start_of_the_week = yesterday - 7.days | ||
start_of_previous_week = start_of_the_week - 7.days | ||
|
||
first_period = overview(start_of_the_week, yesterday) | ||
second_period = overview(start_of_previous_week, start_of_the_week) | ||
describe_period(first_period, second_period, "this week", "last week") | ||
end | ||
|
||
def daily_stats | ||
yesterday = Date.yesterday | ||
day_before_yesterday = Date.yesterday - 1.day | ||
|
||
first_period = overview(yesterday, yesterday) | ||
second_period = overview(day_before_yesterday, day_before_yesterday) | ||
describe_period(first_period, second_period, "yesterday", "the day before") | ||
end | ||
|
||
def main_visits_data | ||
profile.main_visits( | ||
:start_date => Date.yesterday, | ||
:end_date => Date.yesterday, | ||
:limit => 10, | ||
:sort => :unique_pageviews.desc | ||
) | ||
end | ||
|
||
private | ||
include AnalyticsUtils | ||
|
||
def overview(start_date, end_date) | ||
profile.overview( | ||
:filters => { :page_path.does_not_contain => 'admin' }, | ||
:start_date => start_date, | ||
:end_date => end_date | ||
).first | ||
end | ||
|
||
def describe_period(current_period, previous_period, this_kind, last_kind) | ||
{ | ||
visitors: current_period.visitors, | ||
visitors_change: percentage_change(previous_period.visitors, current_period.visitors), | ||
new_visits: current_period.new_visits, | ||
new_visits_change: percentage_change(previous_period.new_visits, current_period.new_visits) | ||
} | ||
end | ||
|
||
def build_oauth_token | ||
consumer = OAuth::Consumer.new('anonymous', 'anonymous', { | ||
:site => 'https://www.google.com', | ||
:request_token_path => '/accounts/OAuthGetRequestToken', | ||
:access_token_path => '/accounts/OAuthGetAccessToken', | ||
:authorize_path => '/accounts/OAuthAuthorizeToken' | ||
}) | ||
|
||
OAuth::AccessToken.new(consumer, oauth_token, oauth_secret) | ||
end | ||
|
||
def establish_garb_session | ||
Garb::Session.access_token = build_oauth_token | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
require 'terminal-table' | ||
|
||
class ReportMailer < ActionMailer::Base | ||
default from: "winston@alphagov.co.uk" | ||
|
||
def daily_analytics(recipient_address, daily, weekly, top_ten_pages) | ||
@daily = daily | ||
@weekly = weekly | ||
@top_ten_pages = top_ten_pages | ||
|
||
mail(to: recipient_address, subject: analytics_subject(daily, weekly)) do |format| | ||
format.text | ||
end | ||
end | ||
|
||
protected | ||
def top_ten_table(top_ten_pages) | ||
Terminal::Table.new do |t| | ||
t.add_row ['Title', 'Page Views', 'Unique Page Views', 'Avg Time on Page'] | ||
t.add_separator | ||
top_ten_pages.each do |detail| | ||
t.add_row [ | ||
detail.page_title, detail.pageviews, detail.unique_pageviews, | ||
detail.avg_time_on_page.to_i | ||
] | ||
end | ||
end | ||
end | ||
|
||
def analytics_subject(daily, weekly) | ||
[ | ||
"NEEDOTRON DAILY: Yesterday: #{daily[:visitors]} (#{daily[:visitors_change]}%) #{daily[:new_visits]} (#{daily[:new_visits_change]}%)", | ||
"7 days: #{weekly[:visitors]} (#{weekly[:visitors_change]}%) #{weekly[:new_visits]} (#{weekly[:new_visits_change]}%)" | ||
].join(' | ') | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#!/usr/bin/env ruby | ||
|
||
require 'action_mailer' | ||
require 'aws/ses' | ||
|
||
require_relative 'lib/analytics_interface' | ||
require_relative 'lib/report_mailer' | ||
|
||
view_path = File.expand_path('views', File.dirname(__FILE__)) | ||
|
||
ActionMailer::Base.add_delivery_method :ses, AWS::SES::Base, | ||
:access_key_id => ENV['SES_ACCESS_KEY_ID'], | ||
:secret_access_key => ENV['SES_SECRET_KEY'] | ||
ActionMailer::Base.delivery_method = :ses | ||
ActionMailer::Base.view_paths = view_path | ||
|
||
interface = AnalyticsInterface.new(ENV['ANALYTICS_ACCOUNT_ID'], ENV['GOOGLE_OAUTH_TOKEN'], ENV['GOOGLE_OAUTH_SECRET']) | ||
daily = interface.daily_stats | ||
weekly = interface.weekly_stats | ||
details = interface.main_visits_data | ||
ReportMailer.daily_analytics(ENV['RECIPIENT_ADDRESS'], daily, weekly, details).deliver |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
UNIQUE VISITS YESTERDAY: <%= @daily[:visitors] %> (<%= @daily[:visitors_change] %>%) | ||
NEW VISITS YESTERDAY: <%= @daily[:new_visits] %> (<%= @daily[:new_visits_change] %>%) | ||
|
||
UNIQUE VISITS LAST 7 DAYS: <%= @weekly[:visitors] %> (<%= @weekly[:visitors_change] %>%) | ||
NEW VISITS LAST 7 DAYS: <%= @weekly[:new_visits] %> (<%= @weekly[:new_visits_change] %>%) | ||
|
||
TOP PAGES YESTERDAY | ||
|
||
Title (page views / unique page views / average time) | ||
|
||
<% @top_ten_pages.each do |page| %> | ||
<%= page.page_title %> (<%= page.pageviews %> / <%= page.unique_pageviews %> / <%= page.avg_time_on_page.to_i %>) | ||
<%= "https://www.gov.uk#{page.page_path}" %> | ||
<% end %> |