‹  All work

JPMorgan Chase  ·  Chase Payment Solutions

Redesigning Sales Activity

How research stopped us from building the wrong thing.

Role
Senior UX Designer
End-to-end ownership
Timeline
3 months
Hard vendor deadline
Team
Product · Engineering
Research · Content · Compliance
Surface
Sales Activity
Desktop primary
Sales Activity shown on a laptop: a chronological table of card sales, refunds and disputes with a Needs attention filter.

01. Background

Digging past the assumptions

Chase Payment Solutions gives small business merchants a dashboard to accept card payments, issue refunds, and manage disputes.

There were two reasons that led to this project being initiated. The backend was migrating to an order-based data structure, where a sale and its related refund or dispute share a group identifier. And the termination of our WePay vendor relationship gave us three months to bring the entire Disputes experience into Sales Activity.

There was an assumption that the new backend structure should be reflected in the customer-facing UI. Before committing three months of design, I tested whether merchants actually thought that way.

They didn't.

02. Problem

Merchants did not understand how payments were related

The legacy table split transactions across two tabs, which were Card Sales and Refunds. Each tab's identification was easily understood, but the relationship between the two was not apparent.

When a merchant asked, "Where did my payment go?" they had to open one tab, find the sale, switch tabs, find the refund, and hold the reconstructed relationship within their memory. Disputes weren't in Sales Activity at all; they lived in a separate experience entirely, which meant a merchant could miss a chargeback deadline without ever knowing one existed.

Find
What transaction happened? Locate a specific transaction quickly.
Understand
What happened to it? Know the events connected to it.
Act
What needs me? Know when something needs a response.

The legacy design did the first job adequately and the other two not at all.

Legacy Sales Activity table with separate Card sales and Refunds tabs.

Problem Statement

Small business merchants using Chase Payment Solutions need to quickly verify payments. Merchants were forced to mentally reconstruct the story of a related event (i.e., a sale that was refunded) by cross-referencing records across multiple disconnected views. For time-sensitive actions like responding to a chargeback, that friction meant missing a deadline entirely without knowing one existed.

03. Question

The question was whether the merchants' mental model matched the grouped order structure

Based on the new backend order-based structure, a card sale, its refund, and any dispute against it share a common group identifier. The hypothesis was that exposing that grouping in the activity table would make transaction relationships clear to merchants.

Even with a three-month deadline, it was important to allocate time for research and testing to avoid rushing a product that doesn't solve the problem.

I built three prototypes, each with a different interpretation of how the transaction's relationships were represented through the design. I tested each prototype against two tasks.

04. Testing

Rejected. Exploration 1: A shared identifier across tabs

If the order number appears on every related record, does the relationship become apparent?

The most conservative direction. I kept the existing tab structure and added a Disputes tab with its own columns: dispute number, reason, date opened, status. Every related record across all three tabs maintained the same order number.

What I learned

An identifier isn't a relationship. The tab boundary was a stronger signal than the repeated number, and it overrode whatever connection the shared ID was meant to communicate.

What happened

Merchants navigated the tabs without difficulty, as that design was the same as before. When they were asked to find the original sale connected to a refund, none of the merchants used the order number to do it. They read it as a unique ID per transaction regardless of the fact that it repeated across different types.

Exploration 1: Card sales tab, with a Disputes tab added alongside Refunds.
Tabbed: Card Sales View
Exploration 1: Refunds tab, sharing the order number with its original sale.
Tabbed: Refunds View
Exploration 1: Disputes tab with dispute number, reason, date opened and status.
Tabbed: Disputes View

Rejected. Exploration 2: Structural nesting

If the relationship is expressed structurally rather than through a shared number, does it become legible?

Parent rows represented the original sale. Expanding a row revealed child rows for the related refund or dispute transactions. With the tabs removed, the shared identifier was no longer the only signal of the relationship; the hierarchy reinforced it.

What I learned

When merchants expanded the rows, they mistook the child rows for itemized line items, the components that add up to an order total, rather than separate events that happened later.

What happened

Merchants recognized nested rows through the lens of viewing receipts and invoices, and that prior model was doing the interpreting. This direction also buried the one thing that most needed to be visible: an action-required dispute sitting inside a collapsed parent row.

Exploration 2: parent rows for each original sale, collapsed.
Collapsible View
Exploration 2: a parent row expanded to reveal nested refund and dispute rows.
Collapsible View: Expanded

Pivot: The two explorations failed for the same reason

Both were attempts to make the activity table explain the relationship between transactions. Merchants weren't opening Sales Activity to understand how their order connected across related order events. They were opening it to locate a specific order.

The backend model organizes by orders as groups. Merchants organize by a single event in time. The error was assuming that a structure legible to the system would be digestible in the interface.

→ If either exploration had produced merchants successfully tracing a refund back to its sale, I would have shipped the grouping model. The backend was already built for it and it was the lower-effort path. The research is what took it off the table.

Selected. Exploration 3: Every transaction is its own event

If grouping disappears from the list entirely, does the table match how merchants already think?

Every card sale, refund, and dispute appears as its own row in chronological order. The table removes all tabs and nesting and adds a Type column to tell them apart. The relational context moves one level deeper into the detail drawer.

What I learned

Merchants found the table immediately scannable and located transactions faster than in either prior direction. Nothing was hidden behind a tab or an expandable row.

What happened

This matched what merchants encounter everywhere else. Other services such as Amazon, PayPal, Shopify, and Square all use order number, transaction ID, and confirmation number more or less interchangeably to mean one transaction corresponds to one number. Merchants arrived with that model already formed. Matching it was cheaper than teaching them a new one.

Exploration 3: every sale, refund and dispute as its own row in chronological order, with a Type column.
Order number single row

Solving for the need for action

A dispute isn't just another event in the timeline. If a deadline is missed a merchant loses money.

An account level alert would compete with urgent notifications. The platform's red dot pattern had already been applied across too many surfaces, and adding another consumer would have further diluted that signal. Dispute urgency had to live inside the context of Sales Activity.

Needs Attention sits above the table as a persistent filter. It's present and subdued when nothing requires action. When a dispute opens, a count badge appears, and the merchant sees it the moment they land on the page regardless of where that dispute falls in the list. Selecting it filters the table to action-required items.

Needs attention selected, filtering the table to the one dispute requiring a response.
Order number single row: Needs attention selected

Relationship context revealed in details drawer

Relationship context now lived where the merchant was ready to receive the information.

Opening any transaction reveals a status progression bar, full transaction details, and the transaction's history. From a refund or dispute, "View original order" takes the merchant to the sale that generated it in one click.

The dispute drawer is the highest-stakes view in the system. Action required appears in red, pointing merchants to the option to fight the dispute.

Legacy transaction details screen: amount, order number, card details and a Refund button.
Updated details drawer over the activity table, showing status progression, actions and full details.
Legacy details screen versus updated details screen
Card sale detail drawer.
Refund detail drawer, including a link back to the original order.
Dispute detail drawer, with the action required state called out in red.
Details screens: Card sale, Refund, and Dispute

05. Outcome

System

A single row for each transaction type proved to be the best solution. A merchant had three jobs, and each required a different layer.

Activity
What happened? Chronological list of every transaction, optimized for scanning and retrieval.
Attention
What needs me? Needs Attention pill, optimized for urgency without competing with the feed.
Context
What does this mean? Detail drawer, optimized for reconciliation.

Rationale and trade-offs

The grouping hypothesis, that exposing the backend order model in the UI would help merchants understand transaction relationships, was disproved.

Merchants think in chronological events, so the design prioritizes their instinct to find an order with one piece of information over the backend's hierarchical structure. Relational reconciliation is supported at the detail screen level, where merchants could make the connection without the added complexity at the activity level.

Try it. Search by order number, filter to Needs attention, open any row, then use “View original order” from a refund.

06. Next

Where I'd take it next

In future iterations, I would enhance the status experience to show a more detailed payment cycle. I would also create a high-level dashboard surfacing the metrics merchants check most, and pursue cross-team alignment on the alert system for a more cohesive experience across the platform.