User Experience & Interface Design

Define UX Success Before You Estimate the Redesign

A UI change is working only if people complete the intended task more reliably without creating more support or operational work. That is a stricter test than a successful framework spike or a cleaner-looking screen. For a product manager, the practical consequence is uncomfortable: scope measurement and error recovery alongside the interface change, or the team may ship without knowing whether it helped.

A completed task is a better unit of scope than a finished screen

Start with one task that matters enough to justify the work: submitting an order, changing an account setting, or saving a draft. Define its start, successful end, and recoverable failures before estimating UI tickets. A screen can render correctly while a user abandons after a validation error; counting the screen as complete would conceal the work still required.

I would treat Test the UI Framework Before You Estimate the Build as a way to find implementation risks, not as proof that the resulting experience will work. A framework trial can establish whether a component renders and whether its state is manageable. It cannot establish task completion unless the trial includes the actual transitions a user must survive: invalid input, a slow response, a failed save, a retry, and confirmation that the retry succeeded.

Give each task attempt a generated attempt_id. Record task_started, task_completed, and specific failure or retry events against that identifier. Completion rate is completed attempts divided by started attempts, not completed page views divided by visitors. The attempt identifier matters because one person may reload or retry several times; treating those actions as new users would distort both the numerator and denominator. Keep the identifier short-lived and avoid putting form contents in event properties, because a useful measurement plan does not require collecting the data a user typed.

For a planning example, suppose a team reviews 240 eligible attempts across 14 days and finds that 34 include a retry. Those figures are illustrative, not a reported result. They show why the estimate needs an instrumentation task: without an attempt-level record, the team cannot tell whether the retries came from a few persistent users or a broad failure in the flow. Define eligibility too. Exclude internal test accounts and automated traffic, but retain failed attempts; excluding failures because they lack a completion event would make the result look better by construction.

Measure recovery separately from completion. A user who eventually finishes after repeated errors has completed the task, but the UI has still imposed a cost. Track the share of attempts with at least one retry, the time from first error to completion, and abandonment after an error. Segment these by released UI version and task type. If a design change improves completion while sharply increasing retries, it has shifted work onto users rather than removed it.

Synthetic tests and live telemetry answer different questions

Choose Playwright synthetic tests when the question is, “Can this known failure path still be completed?” A Playwright test can deliberately make an API request fail, check that the error is visible, retry, and assert that confirmation appears. It wins before release because the team can reproduce the same condition on every build. Its cost is maintaining fixtures and selectors as the flow changes; it cannot tell you how often that condition occurs for real users.

Choose live browser telemetry when the question is, “How often are users encountering this, and do they recover?” Events collected through an existing analytics setup such as Google Analytics 4, paired with error reporting in Sentry’s JavaScript SDK, can show frequency across released versions. Live telemetry wins when failures depend on devices, networks, or user behavior that a test suite did not anticipate. Its cost is event-schema governance, privacy review, and investigation when an event is missing or duplicated. Neither option replaces the other: a passing Playwright test shows a path is possible, while a production completion rate shows whether that path is working often enough.

Keep the initial calculation simple enough to inspect. The following Node.js script reads JSON Lines from standard input; each line needs an attempt_id and an event. Save it as metrics.js and run node metrics.js < events.jsonl. It is a check on the event contract, not a substitute for a governed production query.

const fs = require('node:fs');
const text = fs.readFileSync(0, 'utf8');
const rows = text.split('\n').filter(Boolean).map(JSON.parse);
const attempts = new Map();
for (const e of rows) {
  if (!attempts.has(e.attempt_id)) attempts.set(e.attempt_id, { done: false, retried: false });
  const attempt = attempts.get(e.attempt_id);
  if (e.event === 'task_completed') attempt.done = true;
  if (e.event === 'retry_clicked') attempt.retried = true;
}
const values = [...attempts.values()];
const rate = predicate => values.length ? values.filter(predicate).length / values.length : null;
console.log({ attempts: values.length, completion: rate(a => a.done), retry: rate(a => a.retried) });

Instrument the boundary between browser and server as well. The W3C Trace Context traceparent header and OpenTelemetry traces can help connect a failed UI action to the request that served it. Prometheus and Grafana can then show whether server error rates moved at the same time as user-visible failures. That connection reduces guesswork, but a trace alone does not prove usability: a successful HTTP response may still leave a user staring at an ambiguous status message.

Use performance and accessibility checks as guardrails rather than substitutes for task outcomes. Google’s published “good” threshold for Interaction to Next Paint is 200 ms at the 75th percentile; exceeding it deserves investigation because a sluggish control can make users retry an action that already succeeded. An axe-core check against relevant WCAG 2.2 criteria can catch accessibility regressions in the tested state, while manual keyboard testing remains necessary for the full recovery path.

A lower error count does not prove the UI caused it

Operational incidents are a legitimate reason to fund interface work, but they are a poor single success metric. I disagree with using The 7 UX mistakes that page DevOps at 2 a.m. and their cost as an implicit measurement plan: a quieter on-call week could reflect lower traffic, a backend fix, or an alert-rule change rather than a better UI. The claim needs a link from a user action to a specific failure and then to an operational consequence.

Before release, tag the alerts plausibly affected by the flow. In Alertmanager or the team’s incident system, distinguish a page caused by repeated user submissions from one caused by unrelated infrastructure. Count those pages per eligible task attempt, and record support contacts about the same task. Use a separate guardrail for severe incidents; an improved average does not excuse a new failure that prevents anyone from finishing. Document the alert routing and definitions before changing the UI, because changing those definitions mid-test would break the comparison.

A staged rollout makes the evidence more credible. Keep an unchanged group on the old flow while a feature flag, such as a LaunchDarkly flag, exposes the new flow to a comparable group. Compare completion, retries, and relevant support contacts over the same period. Assign by stable account or user identifier rather than by page load, because switching variants during one attempt would make its outcome hard to interpret. Check the groups’ device mix and task mix before claiming a difference; a new flow shown mostly to desktop users should not be credited for outperforming a mobile-heavy baseline.

Set a decision rule before seeing results. An adjustable starting target might be a 5-percentage-point increase in completion with no increase in the share of attempts requiring a retry. That is a value to tune against the baseline and the value of the task, not an industry benchmark. Report the attempt counts beside both rates and include uncertainty intervals when the sample is small. A change from 80% to 85% across a handful of attempts is less persuasive than the same change across many independent attempts, because random variation has more room to explain a small sample.

Do not use raw “rage clicks” as the pass criterion, because repeated clicks can mean impatience, a missed target, or an intentionally repeatable action. Treat them as a prompt to inspect a session or reproduce a state. The primary decision should rest on whether eligible users finish, whether recovery gets easier, and whether the change avoids new operational harm.

The measurement plan determines how much work to fund

A realistic estimate includes four pieces that are often split across teams: the UI change, the event contract, failure-path tests, and the release comparison. If analytics events already exist, budget time to verify their meaning in the browser and in the warehouse. If they do not, include implementation and validation rather than assigning an analyst a query that cannot be written. “Add tracking” is not a complete ticket; specify the event name, firing condition, attempt identifier, version property, and owner of the resulting dashboard.

Scope a vertical slice before a broad redesign. Pick one high-volume task and one failure that the team can reproduce. Build the recovery state, write its Playwright test, instrument attempts, and release it behind a flag. A proposed first review window of 2 weeks after exposure is a scheduling choice, not a promise of statistical certainty; extend it if eligible attempt volume is too low or if the comparison groups differ. This sequence gives the PM a bounded deliverable even if the evidence later argues against expanding the design.

I would not fund a full component-library migration to improve one flow before running that slice, because a migration raises the amount of code at risk without answering whether the intended users recover more successfully. The slice may reveal a library constraint that justifies broader work. It may instead reveal that the confusing confirmation message or a duplicate-submit rule is the actual problem. Those outcomes have different estimates, and the measurement work helps distinguish them before the larger commitment.

Make the release decision explicit. Expand if task completion improves without a material retry or incident regression; revise if users finish but recovery remains painful; roll back if the new flow prevents completion or creates severe errors. Record what changed in server behavior during the test so the team does not attribute every movement in a dashboard to the UI. The result is a scope decision supported by observed behavior, not a declaration that a screen is done.

The first ticket should define an attempt

Before estimating the interface change, ask an engineer and an analyst to define one eligible task attempt together: its start event, successful end, error states, identifier, and exclusion rules. Then verify those events with a real failed-and-retried attempt in a test environment. If the team cannot distinguish that attempt from two separate visits, it cannot yet measure whether the proposed work is working.