include browser/os/screen_size in e-commerce analytics events
All checks were successful
deploy / deploy (push) Successful in 1m37s

Event call sites (product_view, add_to_cart, checkout_start, purchase)
were only passing visitor_hash and pathname, leaving browser, OS, screen
size and country nil. Add AnalyticsHook.attrs/1 helper to extract common
analytics fields from socket assigns, and use it in all LiveView event
call sites. Checkout controller reads the same fields from the session.

Also fix plug analytics test to clear stale events before assertions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey 2026-02-22 21:13:47 +00:00
parent e26a02a0fb
commit f91b47f0c3
5 changed files with 37 additions and 14 deletions

View File

@ -79,6 +79,20 @@ defmodule BerrypodWeb.AnalyticsHook do
end
end
@doc """
Extracts common analytics attributes from socket assigns.
Call sites can merge their own fields (pathname, revenue, etc.) on top.
"""
def attrs(socket) do
%{
visitor_hash: socket.assigns[:analytics_visitor_hash],
browser: socket.assigns[:analytics_browser],
os: socket.assigns[:analytics_os],
screen_size: socket.assigns[:analytics_screen_size],
country_code: socket.assigns[:analytics_country_code]
}
end
defp handle_analytics_event("analytics:screen", %{"width" => width}, socket)
when is_integer(width) do
screen_size = classify_screen(width)

View File

@ -134,7 +134,11 @@ defmodule BerrypodWeb.CheckoutController do
if visitor_hash do
Analytics.track_event("checkout_start", %{
pathname: "/checkout",
visitor_hash: visitor_hash
visitor_hash: visitor_hash,
browser: get_session(conn, "analytics_browser"),
os: get_session(conn, "analytics_os"),
screen_size: get_session(conn, "analytics_screen_size"),
country_code: get_session(conn, "country_code")
})
end
end

View File

@ -14,11 +14,11 @@ defmodule BerrypodWeb.Shop.CheckoutSuccess do
# Track purchase event
if order && connected?(socket) && socket.assigns[:analytics_visitor_hash] do
Analytics.track_event("purchase", %{
pathname: "/checkout/success",
visitor_hash: socket.assigns.analytics_visitor_hash,
revenue: order.total
})
attrs =
BerrypodWeb.AnalyticsHook.attrs(socket)
|> Map.merge(%{pathname: "/checkout/success", revenue: order.total})
Analytics.track_event("purchase", attrs)
end
# Clear the cart after successful checkout

View File

@ -42,10 +42,10 @@ defmodule BerrypodWeb.Shop.ProductShow do
gallery_images = filter_gallery_images(all_images, selected_options["Color"])
if connected?(socket) and socket.assigns[:analytics_visitor_hash] do
Analytics.track_event("product_view", %{
pathname: "/products/#{slug}",
visitor_hash: socket.assigns.analytics_visitor_hash
})
Analytics.track_event(
"product_view",
Map.put(BerrypodWeb.AnalyticsHook.attrs(socket), :pathname, "/products/#{slug}")
)
end
socket =
@ -185,10 +185,14 @@ defmodule BerrypodWeb.Shop.ProductShow do
cart = Cart.add_item(socket.assigns.raw_cart, variant.id, socket.assigns.quantity)
if socket.assigns[:analytics_visitor_hash] do
Analytics.track_event("add_to_cart", %{
pathname: "/products/#{socket.assigns.product.slug}",
visitor_hash: socket.assigns.analytics_visitor_hash
})
Analytics.track_event(
"add_to_cart",
Map.put(
BerrypodWeb.AnalyticsHook.attrs(socket),
:pathname,
"/products/#{socket.assigns.product.slug}"
)
)
end
socket =

View File

@ -9,6 +9,7 @@ defmodule BerrypodWeb.Plugs.AnalyticsTest do
setup do
send(Buffer, :flush)
:timer.sleep(50)
Repo.delete_all(Event)
:ok
end