Offerwall platform, internal operations
Getting the company out of its own support queue
Every question about a missing reward became a ticket for one of our account managers. The tool they used could not represent half of what the product now did, so they were interpreting rows that no longer described reality.

One row grammar for every reward mechanic, and the reason a campaign never appeared, surfaced where the investigator is already looking.
Context
Users earn rewards by completing milestones inside partner apps. When a reward does not arrive, the explanation is spread across install attribution, postbacks, milestone progress, promotions and fraud rules. All of that work sat with our account managers, in an internal tool that had not kept pace with the product. Newer mechanics like boosters, promoted offers and cashback had no real representation in it.

Before. The table investigators worked from before. Every reward mechanic was flattened into one undifferentiated list, so a timed event, a purchase and a bonus all read the same way, and nothing explained why a payout had been withheld.
Tension
The obvious brief was to redesign the screen. That would have failed, because the screen was not the problem. The problem was that no shared definition of a reward event existed, so every new business mechanic arrived as a special case and the interface accumulated exceptions. Meanwhile support in high volume regions were handling over a hundred tickets a shift, and slow answers were making partners doubt the payout logic itself rather than just the tooling. Fixing the layout would have bought a quarter.
Insight
While shadowing investigations I noticed the agents were not reading the data, they were translating it. Each one had built a private mental model for converting rows into an explanation. The bottleneck was not access to information, it was the absence of one structure that held every mechanic. So the deliverable was not a screen, it was an event model, and the screen would fall out of it.
Five mechanics were being drawn as one undifferentiated list. Naming them was the design work. The table was a consequence.
Decisions, and what each one cost
Impact
The 56% comes from a two month comparison against the previous internal tool. The extensibility claim is verifiable in the design file: six subsequent feature releases reused the original structure.
More: the system underneath, leadership, step by step, screens, the open argument and what comes next
The system underneath
The structure has to survive mechanics that do not exist yet. Five groups, ordered by the question people arrive with rather than by how the data is stored.
- Timed events
- Level events
- Repeatable
- Bonus
- IAP and cashback
- Promotions
- Install postback
- Click window
- MMP handshake
- UUID
- External ID
- Device, country
- Fraud rules
- Payout ceilings
- Consent state
Progress and rewards lead because they answer most tickets. Guards sit last and are explicitly named, so a withheld payout reads as a decision rather than a defect. New mechanics attach to a group instead of adding a column.
Leadership and ownership
- Earning the data dependencyA schema driven table needed data engineering to expose the event store differently. I brought the ticket taxonomy from eight shadowed investigations to that conversation, so the request was evidence rather than preference.
- Auditing my own workOnce it was in daily use I ran a structured audit with support managers, TAMs and integration managers. It found that manual rewarding shipped without proper success and failure feedback, which is mine to own and is now the top priority fix.
- Holding a position against the loudest customerLarge publishers asked for an unlimited override of our fraud rules. I argued for graduated limits instead, and that argument is still live.
How it works, step by step
- Find the right recordSearch by UUID, external user ID or device. Results group per publisher app and carry fraud state up front, because picking the wrong record wastes the whole investigation.
- Read eligibility in one blockSDK version, device, country, consent, coins, revenue, account state and fraud reason together, since eligibility questions are almost never answered by a single field.
- Read the reward historyMilestone table using the one row grammar, with base, promotional and final amounts separated.
- Understand what was withheldValidation results and the constraint funnel, showing eligible campaigns narrowing and naming the rule that removed each one.
- Resolve itManual reward with or without promotion, offered only where state allows, locked while processing.

The shipped structure. One row grammar carries every reward mechanic, with base, promotional and final amounts kept as separate columns so a disputed payout explains itself without opening anything.

The row grammar specified as its own artifact, before any screen was drawn. This document is what made the next six releases cheap.

Withheld campaigns, with the responsible rule named and the count narrowing from twelve to zero. Previously this was an unexplained absence.

Actions mapped against state. Both options disable while an action processes, which is the guard against issuing the same payout twice.
The argument still open
It preserves publisher agency, makes the risky path slower instead of impossible, and gives finance a ceiling. If I am wrong, the failure shows up in an audit log rather than quietly in the margin.
What comes next
The post launch audit produced a prioritised roadmap. Quick wins are all trust repairs on work already shipped, which is why they come before anything new.
Looking back
The interface was the straightforward half. The part that mattered was an event model that still held after the business invented two mechanics nobody had described when I started.



ME
DÖ
P
UY