Ramp Network Mobile App, Non-EU Markets Mar 16 - Apr 1, 2026

Rewards: Two Weeks In

Two weeks since real launch. Here's what we can see, what we can't, and what we need to set up now.


1
What Rewards Is Designed to Do
The program, the structure, the targeting

An Onboarding Program

Rewards is an onboarding program for the Ramp Network mobile app. Users complete missions across four sections, each driving a first-time action. The end goal: complete all missions to unlock a loyalty bonus (0.25 USDC cashback on every future transaction).

What Users See

SectionMissionsReward
Welcome to Ramp NetworkWALLET (connect wallet)Part of 1.00 USDC
Earn with USDCTOPUP1 (top up $25+), EARN10 (earn 10 days)0.75 USDC
Discover swapsSWAP1 (first swap $50+), SWAP3 (3 swaps)2.75 USDC
Grow your networkINV3 (invite 3), INV7 (invite 7), SEND5 (send to 5)1.00 USDC
Unlock loyalty bonusONBOARD (complete all above)1.00 USDC + ongoing cashback

The reward structure incentivizes the right behavior. Swaps pay the most (2.75 USDC combined) because they're the highest-margin transaction type. The loyalty bonus at the end creates a reason to complete the full journey, not just cherry-pick easy missions.

Targeting

Mobile app only (by design). Non-EU/EEA (regulatory). Release flag (rewards-feature, ID 10188193) at 100% rollout for eligible users. No holdout group. Created by Jakub Jastrzebski, last modified by Marek Rycerski.


2
Stickiness
Early signals are strong but unproven

Retention: 7.4x Multiplier

Rewards visitors show dramatically different behavior from the general population:

Rewards Visitors
59.7%
W1 rolling retention. Rewards visitors return at nearly 60% in the first week.
All Users
8.1%
General population W1 retention. The gap is 7.4x.
MetricRewards VisitorsAll UsersMultiplier
W1 rolling retention59.7%8.1%7.4x
W2 rolling retention69.8%5.6%12.4x
Weekly transaction rate33.1%10.4%3.2x

Transaction Rate: 3.2x

33.1% of rewards visitors completed a transaction in the week of March 23, compared to 10.4% of the general population.

Rewards Visitors
33.1%
226 of 682 rewards visitors transacted in the week of Mar 23.
All Users
10.4%
6,420 of 61,659 total users transacted that same week.

Dashboard-to-Rewards: 42%

42% of users who land on the app dashboard navigate to rewards within 30 minutes (Marek's funnel). That's strong discoverability. iOS penetration is 15.7% (1,035 of 6,594 users). Android is 6.3% (424 of 6,710) with identical flag targeting, so the gap is behavioral or UX, not configuration.

The product design supports return visits. The loyalty gauge (3/10) and "Earned" counter create visible progress. "Complete missions in any order" reduces friction. Users see their journey status every time they open rewards.

The causation gap. Whether this is causation or selection bias is unknown. Users who voluntarily navigate to a loyalty feature may already be the most active users. The 7.4x retention multiplier could simply mean "engaged users are engaged." The flag is at 100% with no control group, so there's no clean way to separate the two.

What to do: Modify the rewards-feature flag (Segment 2) from 100% to 50% to create a randomized holdout. Two weeks of data at current volumes should be enough for the primary retention metric. This is the single most important thing to set up.


3
Deposits and Earn
TOPUP1 is converting. EARN10 is not.

Mission Performance

TOPUP1 (top up $25+)
65
Claims in the period. Users are clearly acting on this mission.
EARN10 (earn 10 days)
0
Zero claims across the entire period. Something is wrong.

Section Conversion: 57%

Users are clearly interested in this section. 57% section-to-action conversion is the highest across the board. They click through, they start. But EARN10 has zero claims across the entire period.

Rewards Screen
100%
43% drop
Earn with USDC
57%

From the app: a user at 1/2 progress on "Earn with USDC" has completed TOPUP1 but not EARN10. This is the exact pattern the aggregate data shows.

Why EARN10 Is Failing

EARN10 requires maintaining a $25+ USDC balance for 10 consecutive days. If the balance drops below $25 at any point (withdrawal, price movement), progress is fully deleted. Not decremented. The entire mission event history is wiped via a transactional delete.

Silent destructive resets. From the code (earn-10-days.tracker.ts): the withdrawal handler checks the balance, and if it's below threshold, calls stopTrackingMission. This deletes the MissionEventLogEntity and MissionEntity rows. The backend publishes a user stream event with completedSteps: 0. The frontend receives this and silently refetches. No toast, no message, no explanation. The user's progress bar drops from e.g. 5/10 to 0/10 and they have no idea why.

10 consecutive days is already a high bar for a first-time earn mission. Combined with silent destructive resets, the failure mode is: user deposits, sees progress building over a week, makes a small withdrawal, progress vanishes, user gives up.

What to do

Show users why progress reset. "Your balance dropped below $25 USDC. Keep your balance above $25 to maintain your earning streak."

Evaluate whether 10 consecutive days is the right threshold for an onboarding mission. Watch TOPUP1 weekly trend as a leading indicator of deposit behavior.


4
Swap Behavior
Small numbers, right direction, can't measure what matters yet

Swap Mission Claims

SWAP1 (first swap $50+)
17
Claims in the period. Small but nonzero. Users are engaging with the CTA.
SWAP3 (3 swaps)
2
Effectively dead. Users who do their first swap aren't coming back for a second and third.

17 SWAP1 claims in two weeks. Small. The swap section pays the most (2.75 USDC combined) and has 41% section-to-action conversion, so users are engaging with the CTA. But few complete.

Rewards Screen
100%
59% drop
Discover Swaps
41%

The section bundles SWAP1 and SWAP3 under "Discover swaps - 2.75 USDC" so users see the combined reward without necessarily understanding the breakdown.

The Post-Mission Tracking Gap

The question we can't answer: Do the 17 users who completed SWAP1 go on to swap again organically? This is the whole point. If the mission just rewards a swap that would have happened anyway, it's not driving behavior. If it creates a habit (swap 2, 3, 4 after claiming), it's working. There's no post-mission activity tracking to measure this.

What to do

Instrument post-claim activity: track transactions after mission completion, excluding the completing transaction itself. Once sample grows, compare swap frequency before and after SWAP1 completion for the same users. Consider merging SWAP3 into SWAP1 or auto-completing it when organic swaps accumulate.


5
Social Missions
Zero claims, but it might just be too early

All Zero

MissionClaimsSection Conversion
INV3 (invite 3)0"Grow your network": 49%
INV7 (invite 7)0
SEND5 (send to 5)0
Rewards Screen
100%
51% drop
Grow Your Network
49%

49% section-to-action conversion. Second highest. Users click "Add contacts" but nobody completes. Both INV3 and INV7 use the identical CTA text "Add contacts" (code review confirmed in rewards-actions.use-case.ts), which feels redundant.

Social missions are inherently slower than transactional ones. Getting 3 friends to sign up in 2 weeks is ambitious. 7 is unrealistic at this stage. SEND5 (send to 5 different people) is a high bar for someone who just started.

Give it more time. Social missions may convert on a longer timescale. If INV3 starts converting but INV7 doesn't, consider lowering the INV7 threshold or removing it. SEND5 may need a lower target initially.


6
Measurement Setup
The measurement infrastructure has gaps

What We Can't Measure

What We Can't MeasureWhy It MattersStatus
CausalityThe fundamental question: rewards causes activity vs attracts active usersFlag at 100%, no holdout group
Program costCan't calculate ROI even if we prove impactNot in Amplitude, Omni, or any pipeline
Unclaimed reward rateDon't know if users are earning and forgettingCould be derived from Prometheus counters in Grafana
Post-mission organic activityCan't answer "does completing X lead to more X?"Not instrumented
Reward expirationDon't know how many rewards expire unusedexpire() exists but is never called. No cron job.
Android gap root cause15.7% iOS vs 6.3% Android, identical targetingNeeds UX investigation

Product Issues Found in Code Review

IssueImpact
EARN10 progress resets silently on withdrawalProgress bar drops to 0 with no explanation to the user
MISSION_INCOMPLETE mapped to 'available'Green "available" badge on missions that aren't complete
REWARD_EXPIRED has no user-facing copyWarning icon + disabled button, no explanation
No post-claim feedback"Reward claim submitted" toast with no timeline, no receipt
Deprecated claim endpoint still in useFrontend uses POST /rewards/claim with rewardIds[]. New POST /rewards/:id/claim has zero consumers

Cashback Status

Is cashback actually on? "Unlock loyalty bonus" in the product UI is the ONBOARD meta-mission. Cashback (0.25 USDC per transaction) activates per-user when they complete all missions. REWARDS_CASHBACK_AWARDING_ENABLED defaults to false in code and likely gates the system globally. Need to confirm whether it's toggled on in production. If it's off, the loyalty bonus section is promising something that can't be delivered.


7
Recommendations
Prove it works, fix what's broken, measure the cost, trim dead weight
Prove It Works

Establish Causality and Habit Formation

1
Run a holdout experiment
P0
Modify flag ID 10188193, Segment 2 from 100% to 50%. This is the only way to answer whether rewards causes increased activity. Every other analysis will have caveats.
2
Instrument post-mission activity tracking
P0
After a user claims SWAP1, do they swap again? After TOPUP1, do they top up again? This is the metric that proves (or disproves) habit formation.
Fix What's Broken

Remove Walls Users Can't See

3
Fix EARN10 silent progress reset
P0
Show users why their progress disappeared. Right now the most engaged "Earn with USDC" users (57% section conversion, highest) are hitting a wall they can't see.
4
Investigate the Android gap
P1
15.7% iOS vs 6.3% Android with identical targeting. That's ~630 users we're leaving on the table. Is it navigation placement? App version? Something else?
5
Reconsider EARN10 difficulty
P1
10 consecutive days with a hard reset is aggressive for an onboarding mission. Consider shorter streak, or allow the streak to pause rather than destroying all progress.
Measure the Cost

Build the ROI Picture

6
Get payout data into the warehouse
P1
Amounts, not just event counts. The backend has amountWei on every reward. Pipe it to Omni so we can calculate program cost.
7
Build an unclaimed ratio
P2
The Prometheus counters (reward_event_total for AWARDED vs CLAIMED) already exist. Someone needs to build a Grafana panel dividing the two.
8
Implement the expiration batch job
P2
expire() on the reward aggregate exists and works. Nothing calls it. Rewards silently become unclaimable after 90 days while their status stays AWARDED in the database.
Trim Dead Weight

Revisit After 4-6 Weeks of Data

9
Consider dropping INV7 and SEND5
P2
Zero claims, high bars for new users. Or lower their thresholds if the mechanic has potential.
10
Consider merging SWAP3 into SWAP1
P2
2 claims. The stretch goal isn't motivating a second and third swap.

A
Appendix
Data sources, related documents, mission claim summary
Data Sources
SourceWhatScope
Amplitude (100017324)page_view, click events, retention, funnels, user propertiesNew Widget - Production
Omnifct_widget_events, transactions_simplifiedMarch 2026
Marek's dashboarde-wbjlpkscLaunch markets, properly filtered
Flag config10188193Targeting rules, rollout %
Code review/packages/backend/src/rewards/, /frontend/widget-2/src/features/rewards/Two independent reviews
Product UIApp screenshotsCurrent production build
Related Documents
Mission Claim Summary (full period)
WALLET
115
TOPUP1
65
TX1
30
SWAP1
17
SWAP3
2
EARN10
0
INV3
0
INV7
0
SEND5
0
MissionClaimsStatus
WALLET115Working
TOPUP165Working
TX130New, needs investigation
SWAP117Small but nonzero
SWAP32Effectively dead
EARN100Blocked (see EARN10 analysis)
INV30Too early to call
INV70Threshold likely too high
SEND50Threshold likely too high