Commit 492c3d63 authored by Braulio Bhavamitra's avatar Braulio Bhavamitra
Browse files

analytics: measure time on page

parent 15eb68fe
class AnalyticsPlugin::StatsController < MyProfileController
no_design_blocks
before_filter :skip_page_view
def index
end
protected
def default_url_options
# avoid rails' use_relative_controller!
{use_route: '/'}
end
def skip_page_view
@analytics_skip_page_view = true
end
end
module AnalyticsPlugin
TimeOnPageUpdateInterval = 2.minutes * 1000
TimeOnPageUpdateInterval = 2.minutes
TimeOnPageUpdateIntervalMs = TimeOnPageUpdateInterval * 1000
extend Noosfero::Plugin::ParentMethods
......
......@@ -28,8 +28,7 @@ class AnalyticsPlugin::Base < Noosfero::Plugin
unless profile.analytics_anonymous?
# FIXME: use session.id in Rails 4
session_id = Marshal.load(Base64.decode64 request['_session_id'])['session_id'] rescue nil
#session_id = request.session_options[:id]
session_id = request.session_options[:id]
page_view.user = user
page_view.session_id = session_id
end
......@@ -40,4 +39,12 @@ class AnalyticsPlugin::Base < Noosfero::Plugin
}]
end
def control_panel_buttons
{
title: I18n.t('analytics_plugin.lib.plugin.panel_button'),
icon: 'analytics-access',
url: {controller: 'analytics_plugin/stats', action: :index}
}
end
end
......@@ -13,7 +13,7 @@ end
class Profile
def analytics_settings attrs = {}
@analytics_settings ||= Noosfero::Plugin::Settings.new self, AnalyticsPlugin, attrs
@analytics_settings ||= Noosfero::Plugin::Settings.new self, ::AnalyticsPlugin, attrs
attrs.each{ |a, v| @analytics_settings.send "#{a}=", v }
@analytics_settings
end
......
......@@ -5,6 +5,13 @@ en: &en
plugin:
name: 'Access tracking'
description: 'Register the access of selected profiles'
panel_button: 'Access tracking'
views:
stats:
user: 'User'
initial_time: 'Time'
pages: 'Pages'
en-US:
<<: *en
......
......@@ -5,6 +5,13 @@ pt: &pt
plugin:
name: 'Rastreio de accesso'
description: 'Registra o acesso de perfis selecionados'
panel_button: 'Rastreio de accesso'
views:
stats:
user: 'Usuário'
initial_time: 'Horário'
pages: 'Páginas'
pt-BR:
<<: *pt
......@@ -25,10 +25,24 @@ class AnalyticsPlugin::PageView < ActiveRecord::Base
before_validation :fill_referer_page_view, on: :create
before_validation :fill_visit, on: :create
scope :latest, -> { order 'request_started_at DESC' }
def request_duration
self.request_finished_at - self.request_started_at
end
def initial_time
self.page_loaded_at || self.request_finished_at
end
def user_last_time_seen
self.initial_time + self.time_on_page
end
def user_on_page?
Time.now < self.user_last_time_seen + AnalyticsPlugin::TimeOnPageUpdateInterval
end
def page_load!
self.page_loaded_at = Time.now
self.update_column :page_loaded_at, self.page_loaded_at
......@@ -36,10 +50,9 @@ class AnalyticsPlugin::PageView < ActiveRecord::Base
def increase_time_on_page!
now = Time.now
initial_time = self.page_loaded_at || self.request_finished_at
return unless now > initial_time
return unless now > self.initial_time
self.time_on_page = now - initial_time
self.time_on_page = now - self.initial_time
self.update_column :time_on_page, self.time_on_page
end
......@@ -59,7 +72,7 @@ class AnalyticsPlugin::PageView < ActiveRecord::Base
end
def fill_visit
self.visit = self.referer_page_view.visit if self.referer_page_view
self.visit = self.referer_page_view.visit if self.referer_page_view and self.referer_page_view.user_on_page?
self.visit ||= AnalyticsPlugin::Visit.new profile: profile
end
......
......@@ -3,9 +3,17 @@ class AnalyticsPlugin::Visit < ActiveRecord::Base
attr_accessible *self.column_names
attr_accessible :profile
default_scope -> { includes :page_views }
belongs_to :profile
has_many :page_views, class_name: 'AnalyticsPlugin::PageView', dependent: :destroy
default_scope -> { joins(:page_views).includes :page_views }
scope :latest, -> { order 'analytics_plugin_page_views.request_started_at DESC' }
def first_page_view
self.page_views.first
end
delegate :user, :initial_time, to: :first_page_view
end
......@@ -31,6 +31,8 @@ class ContentViewerControllerTest < ActionController::TestCase
first_page_view = @community.page_views.order(:id).first
assert_equal @request.referer, first_page_view.referer_url
assert_equal @user, first_page_view.user
assert first_page_view.request_duration > 0 and first_page_view.request_duration < 1
@request.env['HTTP_REFERER'] = first_url
get :view_page, profile: @community.identifier, page: @community.articles.last.path.split('/')
......@@ -40,9 +42,13 @@ class ContentViewerControllerTest < ActionController::TestCase
second_page_view = @community.page_views.order(:id).last
assert_equal first_page_view, second_page_view.referer_page_view
assert_equal @user, second_page_view.user
assert second_page_view.request_duration > 0 and second_page_view.request_duration < 1
# another visit, the referer is set but should be ignored because
# the user didn't report to be on the page until now
@request.env['HTTP_REFERER'] = first_url
future = Time.now + 2*AnalyticsPlugin::TimeOnPageUpdateInterval
Time.stubs(:now).returns(future)
get :view_page, profile: @community.identifier, page: @community.articles.last.path.split('/')
assert_equal 2, @community.visits.count
end
end
javascript:
analytics.timeOnPage.baseUrl = #{url_for(controller: 'analytics_plugin/time_on_page').to_json}
analytics.timeOnPage.updateInterval = #{AnalyticsPlugin::TimeOnPageUpdateInterval.to_json}
analytics.timeOnPage.updateInterval = #{AnalyticsPlugin::TimeOnPageUpdateIntervalMs.to_json}
analytics.requestId = #{request.env['action_dispatch.request_id'].to_json}
analytics.init()
table#analytics-stats.table data-toggle='table' data-striped='true' data-sortable='true' data-icons-prefix='fa'
thead
- unless profile.analytics_anonymous?
th= t'analytics_plugin.views.stats.user'
th= t'analytics_plugin.views.stats.initial_time'
th= t'analytics_plugin.views.stats.pages'
tbody
- profile.visits.each do |visit|
tr
td= link_to visit.user.name, visit.user.url
td
div data-toggle="tooltip" data-title='#{l visit.initial_time}'
= time_ago_in_words(visit.initial_time)
|&nbsp
= _'ago'
td
- visit.page_views.each do |page_view|
= link_to page_view.url, page_view.url
|&nbsp;
= "(#{distance_of_time_in_words page_view.time_on_page})"
|&nbsp;->&nbsp;
javascript:
$('#analytics-stats').bootstrapTable({
striped: true,
columns: [
{sortable: true},
{sortable: true},
{sortable: true},
],
})
$(document).ready(function() {
$('[data-toggle="tooltip"]').tooltip()
})
- content_for :head
= javascript_include_tag 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.8.1/bootstrap-table-all.min.js'
= stylesheet_link_tag 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.8.1/bootstrap-table.css'
= render 'table'
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment