Aggiunge il filtro Pagina (grafico) e il link Grafico in tabella, mantenendo Da/A/Device. Co-authored-by: Cursor <cursoragent@cursor.com>
184 lines
6.3 KiB
Ruby
184 lines
6.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Admin
|
|
class AnalyticsController < Admin::BaseController
|
|
def index
|
|
@filters = {
|
|
from: parse_date(params[:from]) || 7.days.ago.to_date,
|
|
to: parse_date(params[:to]) || Time.zone.today,
|
|
device: params[:device].presence,
|
|
chart_path: params[:chart_path].presence
|
|
}
|
|
@analytics_preview_active = analytics_preview_active?
|
|
|
|
scope = AnalyticsPageStat.where(day: @filters[:from]..@filters[:to])
|
|
scope = scope.where(device: @filters[:device]) if @filters[:device].present? && AnalyticsEvent::DEVICES.include?(@filters[:device])
|
|
|
|
cell_scope = AnalyticsPageCell.where(day: @filters[:from]..@filters[:to])
|
|
cell_scope = cell_scope.where(device: @filters[:device]) if @filters[:device].present? && AnalyticsEvent::DEVICES.include?(@filters[:device])
|
|
|
|
clicks_by_path = cell_scope.group(:page_path).sum(:click_count)
|
|
moves_by_path = cell_scope.group(:page_path).sum(:move_count)
|
|
pageviews_by_path = scope.group(:page_path).sum(:pageview_count)
|
|
scroll_samples_by_path = scope.group(:page_path).sum(:scroll_samples)
|
|
scroll_sum_by_path = scope.group(:page_path).sum(:scroll_sum_pct)
|
|
max_scroll_by_path = scope.group(:page_path).maximum(:max_scroll_pct)
|
|
|
|
paths = (pageviews_by_path.keys + clicks_by_path.keys + moves_by_path.keys).uniq
|
|
@pages = paths.map do |path|
|
|
samples = scroll_samples_by_path[path].to_i
|
|
{
|
|
page_path: path,
|
|
pageviews: pageviews_by_path[path].to_i,
|
|
clicks: clicks_by_path[path].to_i,
|
|
moves: moves_by_path[path].to_i,
|
|
scroll_samples: samples,
|
|
scroll_sum: scroll_sum_by_path[path].to_i,
|
|
max_scroll: max_scroll_by_path[path].to_i
|
|
}
|
|
end.sort_by { |r| [-r[:pageviews], -r[:moves], -r[:clicks], r[:page_path]] }
|
|
|
|
@chart_path_options = @pages.map { |row| row[:page_path] }
|
|
if @filters[:chart_path].present? && @chart_path_options.exclude?(@filters[:chart_path])
|
|
@filters[:chart_path] = nil
|
|
end
|
|
|
|
trend_scope = scope
|
|
trend_scope = trend_scope.where(page_path: @filters[:chart_path]) if @filters[:chart_path].present?
|
|
pageviews_by_day = trend_scope.group(:day).sum(:pageview_count)
|
|
@trend = (@filters[:from]..@filters[:to]).map do |day|
|
|
{
|
|
day: day.iso8601,
|
|
pageviews: pageviews_by_day[day].to_i
|
|
}
|
|
end
|
|
@trend_totals = {
|
|
pageviews: @trend.sum { |r| r[:pageviews] }
|
|
}
|
|
end
|
|
|
|
def show
|
|
@page_path = params[:page_path].to_s
|
|
redirect_to admin_analytics_path, alert: t("admin.analytics.missing_path") and return if @page_path.blank?
|
|
|
|
from = parse_date(params[:from]) || 7.days.ago.to_date
|
|
to = parse_date(params[:to]) || Time.zone.today
|
|
@device_tab_stats = device_tab_stats(@page_path, from, to)
|
|
device = resolve_heatmap_device(@device_tab_stats, params[:device].presence)
|
|
|
|
@filters = {
|
|
from: from,
|
|
to: to,
|
|
device: device,
|
|
layer: params[:layer].to_s
|
|
}
|
|
|
|
cells = AnalyticsPageCell.where(
|
|
page_path: @page_path,
|
|
day: @filters[:from]..@filters[:to],
|
|
device: @filters[:device]
|
|
)
|
|
|
|
@click_total = cells.sum(:click_count)
|
|
@move_total = cells.sum(:move_count)
|
|
@filters[:layer] =
|
|
if %w[move click].include?(@filters[:layer])
|
|
@filters[:layer]
|
|
elsif @move_total.positive?
|
|
"move"
|
|
else
|
|
"click"
|
|
end
|
|
|
|
counter = @filters[:layer] == "click" ? :click_count : :move_count
|
|
@cells = cells.group(:cell_x, :cell_y).sum(counter)
|
|
@max_weight = @cells.values.max.to_i
|
|
@total_points = @cells.values.sum
|
|
|
|
stats = AnalyticsPageStat.where(
|
|
page_path: @page_path,
|
|
day: @filters[:from]..@filters[:to],
|
|
device: @filters[:device]
|
|
)
|
|
@pageviews = stats.sum(:pageview_count)
|
|
@scroll_samples = stats.sum(:scroll_samples)
|
|
@scroll_sum = stats.sum(:scroll_sum_pct)
|
|
@max_scroll = stats.maximum(:max_scroll_pct).to_i
|
|
@avg_scroll = @scroll_samples.positive? ? (@scroll_sum.to_f / @scroll_samples).round : 0
|
|
@grid = AnalyticsPageCell::GRID_SIZE
|
|
@snapshot = find_snapshot(@page_path, @filters[:device])
|
|
end
|
|
|
|
def preview_enable
|
|
Analytics::Suppress.enable!(cookies)
|
|
redirect_to preview_return_to(params[:return_to]), notice: t("admin.analytics.preview.enabled")
|
|
end
|
|
|
|
def preview_disable
|
|
Analytics::Suppress.disable!(cookies)
|
|
redirect_to admin_analytics_path, notice: t("admin.analytics.preview.disabled")
|
|
end
|
|
|
|
private
|
|
|
|
def analytics_preview_active?
|
|
Analytics::Suppress.active?(cookies[Analytics::Suppress::COOKIE_NAME])
|
|
end
|
|
|
|
def preview_return_to(value)
|
|
path = value.to_s.strip
|
|
return root_path if path.blank?
|
|
return path if path.start_with?("/") && !path.start_with?("//")
|
|
|
|
admin_analytics_path
|
|
end
|
|
|
|
def parse_date(value)
|
|
return nil if value.blank?
|
|
|
|
Date.parse(value.to_s)
|
|
rescue ArgumentError, TypeError
|
|
nil
|
|
end
|
|
|
|
def device_tab_stats(page_path, from, to)
|
|
cell_totals = AnalyticsPageCell.where(page_path: page_path, day: from..to)
|
|
.group(:device)
|
|
.pluck(
|
|
:device,
|
|
Arel.sql("SUM(click_count)"),
|
|
Arel.sql("SUM(move_count)")
|
|
)
|
|
cell_by_device = cell_totals.to_h { |device, clicks, moves| [device, { clicks: clicks.to_i, moves: moves.to_i }] }
|
|
|
|
pageview_totals = AnalyticsPageStat.where(page_path: page_path, day: from..to)
|
|
.group(:device)
|
|
.sum(:pageview_count)
|
|
|
|
AnalyticsEvent::DEVICES.index_with do |device|
|
|
cells = cell_by_device[device] || { clicks: 0, moves: 0 }
|
|
cells.merge(pageviews: pageview_totals[device].to_i)
|
|
end
|
|
end
|
|
|
|
def resolve_heatmap_device(tab_stats, requested)
|
|
if requested.present? && AnalyticsEvent::DEVICES.include?(requested)
|
|
return requested
|
|
end
|
|
|
|
AnalyticsEvent::DEVICES.max_by do |device|
|
|
stats = tab_stats[device]
|
|
stats[:clicks] + stats[:moves] + stats[:pageviews]
|
|
end
|
|
end
|
|
|
|
def find_snapshot(page_path, device)
|
|
return nil unless AnalyticsEvent::DEVICES.include?(device)
|
|
|
|
AnalyticsPageSnapshot.where(page_path: page_path, device: device)
|
|
.order(captured_at: :desc)
|
|
.detect { |snapshot| snapshot.image.attached? }
|
|
end
|
|
end
|
|
end
|