A product manager at a B2B SaaS company I worked with had a dashboard she checked every morning. Funnel completion, weekly actives, feature adoption by cohort. The numbers looked reasonable. Step 3 of onboarding had a 61% completion rate, which the team had decided was “good enough.” Nobody had looked at what was happening inside Step 3 — how many times users were clicking the same field, whether they were leaving and coming back, or whether the 39% who dropped were doing so after five seconds or five minutes. The analytics stack was running. It was just being used as a scoreboard instead of a signal.

That distinction — scoreboard versus signal — is what this post is about. Most teams have Amplitude, Mixpanel, or PostHog instrumented. Most are not using them anywhere near their actual capacity as behavioral data pipelines. And most of what’s missing isn’t a tool problem. It’s a framing problem.

What autocapture actually gives you

Every major analytics platform now ships with some version of autocapture — an SDK that hooks into DOM events and logs clicks, pageviews, and form submissions without you having to write custom tracking calls. PostHog’s autocapture is particularly aggressive about this; Amplitude’s is more conservative but still covers the basics.

Here’s what autocapture reliably produces: a timestamped log of user interactions with named elements. Click on a button, that’s an event. Load a page, that’s an event. Submit a form, that’s an event. For a baseline behavioral picture, this is useful. You can build a funnel, see where users fall off, and know that a problem exists somewhere.

What autocapture does not give you is context. It cannot tell you that a user clicked the “Continue” button three times before it registered because they were confused about whether it was interactive. It doesn’t capture that a user hovered over a tooltip for eight seconds before moving on — or that they opened the same modal twice in sixty seconds because the first visit didn’t answer their question. It captures the action, not the behavioral state behind the action.

This is the gap that matters. A click is a data point. What the click means — and what was happening in the five seconds before it — is behavioral state. Autocapture gets you the former almost for free. The latter requires intentional instrumentation.

Events versus behavioral state

An event is a record of something that happened: signup_completed, plan_upgraded, checkout_initiated. Behavioral state is the pattern of events that tells you what a user is actually doing and how they’re experiencing the product.

Consider two users who both complete onboarding_step_3_finished. User A took 45 seconds, clicked three times, and moved directly to Step 4. User B took 8 minutes, clicked 22 times across the step, left the page and came back twice, and triggered the help widget before finishing. Both users show the same event in your funnel. They had completely different experiences. And if you’re optimizing for Step 3 completion rate, you’re treating them identically.

Behavioral state is the aggregate signal from the full interaction sequence: time on step, interaction count, revisit rate, the presence or absence of frustration signals like rage clicks, whether the user sought help mid-step. None of that is captured in the event name. All of it is instrumentable. Most teams aren’t instrumenting it.

The reason this matters is downstream. If you want to do anything with your analytics data beyond reporting — if you want to understand why a cohort is churning, or which users are struggling silently before they leave — you need behavioral state, not just events. Events tell you what happened. Behavioral state tells you how it happened. Those are different questions, and the second one is almost always the more actionable one.

What Amplitude captures well — and where it stops

Amplitude is genuinely strong at cohort-level behavioral analysis. Its funnel visualization, retention curves, and cohort comparison tooling are production-grade and handle scale well. If you want to know that users who complete your onboarding within 24 hours have a 2.3x higher 90-day retention rate than users who take longer, Amplitude will tell you that accurately and quickly.

Its strength is aggregated event sequences at scale. The thing it doesn’t do natively is instrument the texture of individual step interactions. You won’t get time-on-step unless you build it yourself — typically by emitting step_entered and step_exited events with a server-side or client-side timestamp delta. Amplitude will store and query that if you send it, but it doesn’t surface it automatically.

More importantly, Amplitude’s default instrumentation has no concept of hesitation. A user who loads a checkout page and converts in 12 seconds looks identical in the funnel to a user who loads it, scrolls to the bottom, scrolls back, hovers over the price section for 40 seconds, and then converts. Same funnel step, same outcome, wildly different behavioral signal. The second user is telling you something about their confidence level that the first user is not. Amplitude doesn’t capture that unless you build the instrumentation for it explicitly.

The practical implication: Amplitude is excellent for answering “where do users drop off?” It is not well-suited, out of the box, for answering “what are users doing right before they drop off?” That second question requires you to have instrumented interaction count, dwell time, and micro-frustration signals at the step level — which most Amplitude implementations haven’t done.

What PostHog adds to the picture

PostHog’s differentiation is the session layer. Session replay gives you a direct window into the interaction texture that Amplitude’s event stream abstracts away. You can watch the actual sequence: where the mouse moved, what got clicked, where the page was scrolled, how long the user paused before the form field. This is useful for qualitative investigation — when you know something is wrong in a specific funnel step, PostHog replay lets you see it concretely.

PostHog also ships rage click detection out of the box, which is a meaningful signal. A rage click — defined as three or more rapid clicks on the same element — is a frustration indicator with a reasonably reliable behavioral mechanism: users click repeatedly when they expect a response and don’t get one. Dead click detection (clicks that produce no DOM response) follows similar logic. These signals are available in PostHog’s autocapture pipeline without additional instrumentation.

Where PostHog still falls short is in systematic behavioral state construction. Session replay is inherently qualitative — you can watch sessions, but you can’t programmatically analyze 50,000 sessions to extract aggregate hesitation patterns. The rage click signal exists, but it’s exposed as an event flag in session data rather than as a queryable cohort dimension you can plug into funnel analysis. And like Amplitude, PostHog doesn’t natively surface interaction count per step or revisit rate per step unless you instrument those explicitly.

The combination of Amplitude and PostHog — events plus session layer — gets you meaningfully closer to the full behavioral picture. But the gap between “closer” and “complete” is still significant, and it lives in the instrumentation choices your team makes, not in what either tool provides by default.

The signal pipeline framing

Here’s the reframe that changes what you instrument: your analytics stack is not a reporting layer. It is a behavioral signal pipeline.

A reporting layer captures outcomes and presents them in dashboards. The job of a reporting layer is to tell you what happened. You look at it weekly, you review it in planning, you use it to answer “how did that feature launch go?”

A signal pipeline is different in purpose. Its job is to surface actionable behavioral signals in as close to real time as the underlying tools allow — not for humans to review in dashboards, but for systems to act on. The question a signal pipeline is designed to answer isn’t “what happened?” It’s “what is happening right now, and for which cohorts?”

When you think about your analytics stack as a signal pipeline, the instrumentation choices change. You stop asking “are we tracking the events the PM needs for the monthly review?” and start asking “are we capturing the behavioral signals that distinguish struggling users from confident ones?” Those are different questions and they produce different event schemas.

Specifically: a signal pipeline needs behavioral state signals, not just outcome signals. It needs time-on-step, because that tells you whether a user is engaging or stalling. It needs interaction count per step, because a user who clicks twelve times on a single CTA before converting is not the same as a user who clicks once. It needs exit intent signals, because a user whose cursor moves toward the browser chrome is sending a pre-churn signal that’s still recoverable. It needs frustration signals — rage clicks, dead clicks — because those are leading indicators of abandonment, not just artifacts of bad UX.

What to actually instrument

If you’re going to treat your analytics stack as a signal pipeline rather than a reporting layer, here is the instrumentation layer that makes that real.

Time-on-step is the most important single metric most teams are missing at the step level. Emit a step_entered event with a timestamp and a step_exited event with a timestamp. Compute the delta. Store it as a property on the exit event. Now you can query which cohorts are spending 4x longer than the median on a given step — which is almost always where the friction is, even when completion rates look fine.

Interaction count per step means counting discrete user interactions — clicks, keystrokes, scroll events — within a defined step boundary. A user who interacts twelve times with a form before submitting it is expressing uncertainty. Three interactions suggest confidence. The ratio between these cohorts in a given step tells you more about the UX quality of that step than the completion rate does.

Exit intent signals — cursor movement toward browser chrome, tab switching, window blur — are available via standard browser events and can be emitted as analytics events with step context attached. They’re leading indicators. A user who triggers exit intent and then recovers is a different cohort from a user who never triggers it. Both may convert, but the first group is telling you something about the friction they experienced.

Revisit rate per step is how often users navigate back to a step they’ve already completed, or reload a page mid-session. A high revisit rate on a pricing or configuration step usually means the information architecture isn’t answering the right question on first pass.

Frustration signal completeness means ensuring rage click and dead click events — whether from PostHog’s autocapture or from custom instrumentation — carry step context as a property. A rage click on your checkout page is more urgent than a rage click on your documentation site. The signal is only actionable if it carries location.

None of this requires a new analytics tool. All of it can flow through your existing Segment, Amplitude, PostHog, or Mixpanel pipeline. The gap is in what you’re choosing to emit, not in what the tools can receive.

Where Rayform fits

Everything above is instrumentable and useful on its own. But the reason to instrument behavioral telemetry with this level of fidelity isn’t primarily so humans can review better dashboards — it’s so the downstream system can act on it.

This is where the insight-to-action gap lives. You can have a perfectly instrumented signal pipeline that tells you, with high precision, that users from enterprise accounts who hit Step 4 of onboarding with an interaction count above 15 and a time-on-step above 180 seconds have a 47% 30-day retention rate versus 71% for users who don’t. That’s a real and actionable insight. What happens with it? Typically, it goes into a Slack thread, then a Jira ticket, then a sprint backlog, then a design review, then a frontend build, then a QA cycle, then a deploy. Six to twelve weeks later, if everything stays prioritized, a UI change ships.

The behavioral signal was real. The gap was between the signal and the action.

Rayform reads the behavioral telemetry already flowing through your stack — Amplitude, Mixpanel, Segment, PostHog — via OAuth read-only token, identifies the cohorts where behavioral signals indicate friction, drafts UI variants targeted to those cohorts, and ships them at runtime without a codebase change or a deploy. One script tag. p99 runtime under 20ms. And the pricing is tied to outcome: no charge if the variant is flat or negative.

The behavioral telemetry you need is probably already flowing. The gap is what happens next.


Rayform reads the behavioral telemetry already flowing through your stack and uses it to adapt your UI at runtime — without a deploy. See how it works.


Behavioral telemetry is only useful if something acts on it.

Rayform closes the loop: it ingests your Amplitude, Mixpanel, Segment, or PostHog signals and ships UI variants to the cohorts where the behavioral data says something is wrong — at runtime, before you’ve filed a ticket.

See how Rayform works →