Analytics
Track storefront activity through Umami, Google Analytics, or both — without leaking personal information.
Configuration
Each tenant can connect a Umami website ID and/or a Google Analytics 4 measurement ID. Set these on the tenant record (Platform Admin → Tenants → edit). Scripts only load in production when the corresponding ID is present.
What gets tracked
Beyond automatic page views, the platform fires a typed set of business events from the customer-facing site, the admin app, and the instructor app:
- Conversions —
booking_completed,checkout_completed,signup_completed,login_completed - Funnel —
course_view,schedule_view,product_view,cart_add,checkout_started,booking_started,waitlist_join - Engagement —
search,filter_applied,discount_applied,discount_code_failed,contact_submit - Friction —
payment_failed,booking_blocked_prereq,out_of_stock - Lifecycle —
enrollment_cancelled(withactorset tocustomeroradmin) - Admin / instructor —
admin:course_created,admin:invoice_sent,admin:order_refunded,instructor:session_marked_complete
Filtering staff activity
Events fired inside the admin or instructor surfaces — or with an admin: / instructor: namespace — are tagged with is_internal: true. Funnel dashboards should filter on this tag so staff dogfooding doesn't pollute customer conversion data.
Server-side delivery
Conversion events that don't have a reliable client (webhooks, redirect-driven OAuth flows, background jobs) are emitted from the server via Umami's send API and the Google Analytics 4 Measurement Protocol. The Square payment.completed webhook, for example, re-asserts checkout_completed so checkouts aren't lost when the customer tab is closed or ad-block strips the client beacon. Each event is delivered by exactly one side to avoid double counting. Configure with the UMAMI_HOST and GA_API_SECRET environment variables.
User identification
When a user is signed in, their internal user ID is passed to both backends as a stable identifier for cross-device attribution and conversion reporting. No emails, names, or other personal details are sent. The identifier is cleared on logout.
Privacy
Event payloads contain only non-identifying details — internal resource IDs, amounts, currency, item counts, route group, and locale. We never send emails or IP-derived data. Search queries are lowercased, trimmed, and limited to 100 characters.
Google Analytics 4 mapping
Conversion events map to GA4's recommended event names so Google's built-in Monetization, Acquisition, and Conversions reports populate automatically: checkout_completed and booking_completed become purchase; signup_completed becomes sign_up; search stays as search with search_term. Other events fire under their original snake-cased names.