Features

Reserved events

The event names Flowgrid understands out of the box. Most arrive on their own; the rest are one call each, and every one of them lights up a part of your dashboard without any setup there.

Five events that matter

Clicks, page speed, forms, searches and errors are collected for you. What Flowgrid can't see is what happens inside your product — so these few calls are where your winning metrics come from. Add them first.

QuestionEventCall
How many people sign up?signup_completedfg.signup(userId, "google")
How many come back?login_completed, active_userfg.login(userId) · fg.setUser(userId)
Do new users reach the “aha” moment?first_actionfg.track("first_action", { … })
Do they finish onboarding?onboarding_completedfg.track("onboarding_completed", { … })
Are we growing MRR?subscription_start / _cancelfg.trackSubscription({ event: "start", … })
1import { fg } from "./flowgrid"; // your FlowGrid.init() instance 2 3// 1. Signups and logins 4fg.signup(user.id, "google"); 5fg.login(user.id, "google"); 6 7// Every page load once the user is known: keeps DAU / WAU / MAU right 8fg.setUser(user.id, { email: user.email, name: user.name }); 9 10// 2. Activation — the first thing that proves your product's value 11fg.track("first_action", { 12 userId: user.id, 13 actionName: "first_report_created", 14 timeSinceSignup: Date.now() - signedUpAt, // ms 15}); 16 17// 3. Onboarding — one call per step, one when it's done 18fg.track("onboarding_step", { 19 userId: user.id, stepId: "connect", stepName: "Connect data", stepOrder: 2, totalSteps: 4, 20}); 21fg.track("onboarding_completed", { 22 userId: user.id, totalTimeSpent: Date.now() - onboardingStartedAt, stepsCompleted: 4, 23});

Tip

Using a hosted sign-in (Google, SSO, magic links)? Call fg.markSignup() before the redirect and fg.setUser() after it — the signup fires exactly once. See Signups & Logins.

Reserved vs your own

Your own events go through fg.capture(name, properties) and keep their exact name. The names on this page are taken: capture()refuses them (and the dashboard won't let you define one), so a click you name click_eventcan never be counted as Flowgrid's click stream and inflate it. Send a reserved event through its helper or fg.track() instead.

names.ts
1// ✅ Your own event — any name that isn't reserved 2fg.capture("report_exported", { format: "csv" }); 3 4// ✅ A reserved event — through its helper or track() 5fg.signup(user.id, "email"); 6 7// ❌ Refused: "signup_completed" is a name Flowgrid sends itself 8fg.capture("signup_completed", { plan: "pro" });

Collected automatically

The flowgrid.js script sends these on its own. There is nothing to call, and they arrive within minutes of install.

EventHow it's sentShows up in
click_eventEvery link and button clickClicks, Heatmaps
heatmap_clickEvery click, with its positionHeatmaps
heatmap_rage_clickRepeated clicks on one spotHeatmaps, Session Replays (rage clicks)
heatmap_scrollHow far each page is scrolledHeatmaps (scroll map)
heatmap_movementMouse movement, sampledHeatmaps (move map)
web_vitalsLCP, INP, CLS, FCP and TTFB per pagePerformance (page speed)
form_eventEvery form submit, with its field names and completion timeForm Events, funnel steps
search_eventSearches in a search form or a search inputSearches, funnel steps
error_eventUncaught errors and unhandled promise rejectionsPerformance, Session Replays (errors), flag guardrails
attribution_touchpointArrivals from a campaign (UTM) or a referrerCampaign touches, attribution
attribution_conversionReturn from a Stripe, Lemon Squeezy or Polar checkoutRevenue attribution

Sent by an SDK helper

One call each. The helper fills in the visitor, session and timing; you pass who the user is.

EventHow it's sentRequiredShows up in
signup_completedfg.signup(userId, method, source?)userId, methodSignups, Acquisition Funnel “Signed up”
login_completedfg.login(userId, method?)userIdLogins
active_userfg.setUser(userId, traits) — once a day per useruserIdActive Users (DAU / WAU / MAU)
identify_userfg.identifyUser(userId, traits)userIdIdentified visitors, Users
update_traitsfg.updateTraits(userId, traits) (server)userId, traitsUsers (profile)
alias_userfg.aliasUser(previousId, userId) (server)previousId, userIdUsers (merged history)
reset_identityfg.logout() / fg.reset()—Ends the identified session
subscription_startfg.trackSubscription({ event: "start", … }) (server)subscriptionId, userId, plan, mrr, billingCycleMRR and churn
subscription_changefg.trackSubscription({ event: "change", … }) (server)subscriptionId, userId, previousPlan, newPlan, previousMrr, newMrr, changeTypeMRR and churn
subscription_cancelfg.trackSubscription({ event: "cancel", … }) (server)subscriptionId, userId, plan, lostMrr, immediateMRR and churn
subscription_renewfg.trackSubscription({ event: "renew", … }) (server)subscriptionId, userId, mrrMRR and churn
trial_convertedfg.trackSubscription({ event: "trial_converted", … }) (server)subscriptionId, userId, plan, mrrMRR and churn
trial_expiredfg.trackSubscription({ event: "trial_expired", … }) (server)subscriptionId, userIdMRR and churn

Sent with track()

No dedicated helper: call fg.track() with the reserved name. TypeScript checks the required properties for you.

EventHow it's sentRequiredShows up in
onboarding_stepfg.track("onboarding_step", …)userId, stepId, stepName, stepOrder, totalStepsOnboarding steps, funnel steps
onboarding_completedfg.track("onboarding_completed", …)userId, totalTimeSpent (ms), stepsCompletedOnboardings, funnel steps
first_actionfg.track("first_action", …)userId, actionName, timeSinceSignup (ms)First actions, funnel steps
funnel_stepfg.track("funnel_step", …)funnelId, step, stepNumberEvent counts
funnel_completefg.track("funnel_complete", …)funnelIdFunnel completions, funnel steps
funnel_abandonfg.track("funnel_abandon", …)funnelId, lastStepEvent counts
prompt_submittedfg.track("prompt_submitted", …)promptId, promptTypeAI prompts sent, funnel steps
prompt_responsefg.track("prompt_response", …)promptId, responseTime, completedEvent counts
prompt_feedbackfg.track("prompt_feedback", …)promptId, feedbackTypeEvent counts
prompt_conversationfg.track("prompt_conversation", …)conversationId, userId, turnCount, totalDurationEvent counts
user_activityfg.track("user_activity", …)userIdEvent counts

Internal names

Used by the SDK and the tracker to talk to Flowgrid. You never send these — they are reserved so your own events can't be mistaken for them.

EventHow it's sent
page_loadPage views
page_viewPage views from the npm SDK
page_exitLeaving a page
time_on_pageTime spent on a page
scroll_depthScroll milestones
session_startA new session
session_updateSession progress
session_heartbeatSession keep-alive
session_endEnd of a session
resource_timingSlow assets
api_timingSlow API calls
lifecycle_changeA user moving lifecycle stage
group_userLinking a user to an account
custom_eventThe envelope for legacy track() calls with your own name
batch_eventsSeveral events in one request
create_trackingRegistering a feature
define_funnelFunnel definition calls
analyze_funnelFunnel definition calls
compare_funnelFunnel definition calls
list_funnelsFunnel definition calls