Aggiunge heatmaps first-party (click/scroll) con pagina admin Analytics.
Raccoglie eventi aggregati dietro consenso cookie, senza PII né tracking su admin/regia/live/replay; GA4 resta invariato. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe "Admin analytics", type: :request do
|
||||
let!(:admin) { AdminAccount.create!(username: "ops-analytics", password: "Password123") }
|
||||
|
||||
before do
|
||||
post admin_login_path, params: { username: admin.username, password: "Password123" }
|
||||
AnalyticsPageStat.create!(
|
||||
day: Time.zone.today,
|
||||
page_path: "/prezzi",
|
||||
device: "desktop",
|
||||
pageview_count: 12,
|
||||
scroll_samples: 10,
|
||||
scroll_sum_pct: 600,
|
||||
max_scroll_pct: 90
|
||||
)
|
||||
AnalyticsPageCell.create!(
|
||||
day: Time.zone.today,
|
||||
page_path: "/prezzi",
|
||||
device: "desktop",
|
||||
cell_x: 10,
|
||||
cell_y: 15,
|
||||
click_count: 4
|
||||
)
|
||||
end
|
||||
|
||||
it "mostra l'elenco pagine" do
|
||||
get admin_analytics_path
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(response.body).to include("/prezzi")
|
||||
expect(response.body).to include("12")
|
||||
end
|
||||
|
||||
it "mostra la heatmap di una pagina" do
|
||||
get admin_analytics_page_path, params: { page_path: "/prezzi" }
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(response.body).to include("admin-heatmap")
|
||||
expect(response.body).to include("/prezzi")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,59 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe "Analytics ingest", type: :request do
|
||||
it "accetta eventi validi, normalizza il path e aggrega" do
|
||||
post "/analytics/events",
|
||||
params: {
|
||||
events: [
|
||||
{
|
||||
type: "pageview",
|
||||
path: "/clubs/461d369a-104c-4d3c-8860-1518b4e95d35",
|
||||
device: "desktop",
|
||||
ts: Time.current.to_i * 1000
|
||||
},
|
||||
{
|
||||
type: "click",
|
||||
path: "/clubs/461d369a-104c-4d3c-8860-1518b4e95d35",
|
||||
device: "desktop",
|
||||
x: 25,
|
||||
y: 50,
|
||||
ts: Time.current.to_i * 1000
|
||||
},
|
||||
{
|
||||
type: "scroll",
|
||||
path: "/clubs/461d369a-104c-4d3c-8860-1518b4e95d35",
|
||||
device: "desktop",
|
||||
scroll: 80,
|
||||
ts: Time.current.to_i * 1000
|
||||
}
|
||||
]
|
||||
},
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:accepted)
|
||||
body = JSON.parse(response.body)
|
||||
expect(body["accepted"]).to eq(3)
|
||||
|
||||
expect(AnalyticsEvent.count).to eq(0)
|
||||
expect(AnalyticsPageStat.find_by(page_path: "/clubs/:id").pageview_count).to eq(1)
|
||||
expect(AnalyticsPageStat.find_by(page_path: "/clubs/:id").max_scroll_pct).to eq(80)
|
||||
expect(AnalyticsPageCell.where(page_path: "/clubs/:id").sum(:click_count)).to eq(1)
|
||||
end
|
||||
|
||||
it "rifiuta path esclusi" do
|
||||
post "/analytics/events",
|
||||
params: {
|
||||
events: [
|
||||
{ type: "pageview", path: "/admin/ops", device: "desktop", ts: Time.current.to_i * 1000 },
|
||||
{ type: "pageview", path: "/live/461d369a-104c-4d3c-8860-1518b4e95d35", device: "mobile", ts: Time.current.to_i * 1000 }
|
||||
]
|
||||
},
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:accepted)
|
||||
expect(JSON.parse(response.body)["accepted"]).to eq(0)
|
||||
expect(AnalyticsEvent.count).to eq(0)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user