In-app upsell design: upgrade prompts that merchants say yes to
Where to put upgrade prompts in an e-commerce app, which merchants should see them, what the copy should say, how often to show them, and how to measure.
In short: Expansion revenue in an e-commerce app lives in four places: empty states, usage limits, the moment right after a merchant gets a result, and the dashboard. An in-app upsell works when it is shown only to the merchants it fits, arrives before a limit rather than after, names the outcome rather than the plan, and can be dismissed once and stays gone. Measure it as a funnel from prompt seen to plan changed, and watch downgrades and support tickets in the weeks after.
Where does expansion revenue live inside the product?
Most teams put the upgrade prompt where it is easiest to build, which is a banner at the top of every page. That is the one place a merchant has learned to ignore. The places that work are the ones where the merchant is already thinking about the thing the next tier does.
| Surface | What the merchant is doing | What the upsell can say |
|---|---|---|
| Empty state | Looking at a feature they have not set up | "Here is what this does. It is on the Growth plan." |
| Usage limit | About to run out of affiliates, emails, creator invites | "You have 40 invites left this month. Here is how to get more." |
| After a win | Just saw a first sale, first reply, first order | "You just made your first affiliate sale. Here is what would double it." |
| Dashboard | Reading their numbers | "Revenue from affiliates is up. Tiered commissions would reward the top ten." |
The empty state is the quietest of the four. A merchant who opens the "Automations" tab on a free plan is telling you they are curious. Show them the feature, greyed out and honest about which plan it is on. Shopify's Built for Shopify requirements say this directly: features gated by a plan must be disabled both visually and functionally and clearly indicated, and it is a rejection reason when it is not obvious which tier unlocks a feature. I cover the design of these screens in empty state design.
The moment after a win is the loudest. The first affiliate sale, the first creator reply, the first TikTok Shop sample request that turns into a video. The merchant is reading the notification and feeling that the app works. That is the only moment when "do you want more of this" is a welcome question. Everywhere else it is an interruption.
Which merchants should see the upgrade prompt?
Not all of them. An upsell shown to a merchant who has not had a result yet reads as "pay us more for the thing that has not worked". It costs you the trust you need for the next prompt.
Define the cohort before you design the prompt. For an affiliate app, "tracked at least one affiliate order in the last 30 days and has more than 20 active affiliates" is a cohort that could use tiered commissions. "Installed four days ago, zero affiliates" is not. For a creator outreach tool, "has had at least five creator replies and is sending messages by hand" is the cohort for an automation upsell. "Has sent 200 messages with no replies" needs help, not a plan page.
Three rules I apply:
- The merchant has had the result that the next tier makes bigger. No result, no prompt.
- The merchant is close to the limit, or doing manually what the tier automates. The prompt should match something they can already feel.
- The merchant is not in a bad state. Failed billing, an open support ticket, a broken integration. Suppress upsells for all of those. If you have a customer health score, gate prompts on it.
The last rule is the one I learned in the support queue at Social Snowball, before I designed anything. A merchant who is asked to pay more while something is broken is a merchant you now have to win back before you can sell to them again.
When should you warn about a usage limit?
Before they hit it. Always before.
A merchant who finds out about the limit when the app stops working has just had a bad day caused by you. Their affiliate payouts did not go out. The creator invites stopped at number 50 of 80. The email did not send. The upgrade dialog they see at that moment is read as a ransom note, and the merchants who do pay at that moment are the ones most likely to downgrade or leave once the pressure is off.
The better pattern is a quiet notice when the merchant still has room, the same notice again as a card on the dashboard when they are close, and a clear explanation of what happens at the limit. Does the app stop? Does it keep working and bill for overage? Does it queue the work until next month? Say which, in the notice, in plain words.
Two more things. Make the limit visible all the time, not just when it is near, so the merchant can plan. And if your pricing is usage-based, let the merchant see the number that drives the bill on the same screen where they see the result it produced. "You tracked $38,000 in affiliate revenue this month" next to "your plan covers up to $50,000" is a growth story. The bill alone is not.
What should upgrade prompt copy say?
Name the outcome, not the plan. The merchant does not want "Pro". They want their top affiliates to earn more so they keep posting, or their creator follow-ups to go out while they sleep.
| Weak | Better |
|---|---|
| Upgrade to Pro | Pay your top 10 affiliates a higher rate automatically |
| Unlock automations | Send the follow-up to creators who have not replied in 3 days |
| You have reached your limit | You have 5 creator invites left this month |
| Get more features | See which TikTok videos drove each sale |
The outcome has to be one the merchant can verify in the product. Shopify's Built for Shopify requirements list "Upgrade to the Pro plan to increase your sales by 18%" as an example of a prohibited outcome claim under "don't make false claims", and they also bar pressure tactics: visible timers, guilt language, and the specific example of a 7-day trial with an animated countdown timer encouraging an upgrade. Those rules only apply to apps seeking the badge, but they describe what merchants dislike everywhere.
Keep the prompt to one sentence of outcome, one line of what it costs, and one button. Put the price in. Hiding it until the plan page makes the merchant click to find out, and most will not.
How often should you show an upsell?
Less often than you think, and never on page load.
Nielsen Norman Group's article on modal and nonmodal dialogs says to use modals for important warnings and to prevent or correct critical errors, and not for nonessential information unrelated to the current user flow. Its warning about repetition is the one to remember: when the format is used for nonessential content, users will refuse to give attention to further instances of it. An upsell modal spends the attention you need for the "your payout failed" modal.
Shopify's Built for Shopify requirements make the same point as rules. A modal or popover that appears automatically on page load, after a set time, or as a result of an unrelated merchant action is a rejection reason. Promotional content must be dismissible, and it is a rejection reason when the same or similar content reappears after being dismissed.
What I ship:
- One prompt per surface, inline, never a modal. The after-a-win prompt lives inside the notification or the success card.
- Dismissed means gone for at least 30 days, and gone for good on the second dismissal.
- One active upsell at a time per merchant. If they are seeing the limit warning, they are not also seeing the automation pitch.
- No prompt in the first session after install. The merchant has not had a result yet.
How do you measure an in-app upsell?
As a funnel with a cohort and a control group, and then by what happens after.
The funnel is prompt seen, prompt clicked, plan page viewed, plan changed. Tag every prompt with its surface so the expansion MRR it produces shows up by surface in your net revenue retention reporting. If you use PostHog, its experiments documentation describes the setup: saving an experiment creates a feature flag for you, a user counts as exposed by default when a $feature_flag_called event is recorded, and you can switch exposure to a custom event to narrow it to users who actually reached the relevant part of the product. Use that custom event. Exposure should be "saw the prompt", not "loaded a page where the prompt might render".
The control group matters because merchants in the right cohort upgrade anyway. A prompt that produces upgrades at the same rate as no prompt is just noise with a conversion number attached.
Then the after. Three things I watch for 60 days after an upsell converts:
- Downgrades and uninstalls from the merchants who upgraded. A prompt that converts and then churns was a pressure tactic, whether you meant it or not.
- Support tickets mentioning the plan or the bill. Read them.
- Whether the merchant used the thing they paid for. If they upgraded for automations and never built one, the plan picker or the onboarding after it needs work.
Where to start
- List every place your app currently asks for an upgrade. Remove any that show on page load, in a modal, or in the first session after install.
- Write the cohort definition for your single best upsell. Who has had the result, is near the limit, and is not in a bad state.
- Find the notification or screen where a merchant sees their first real result, and put one inline prompt there that names the outcome and the price.
- Move every usage limit warning to fire before the limit, and say what happens when it is reached.
- Tag each prompt by surface, set up a control group, and review conversions and 60-day downgrades together once a month.
Frequently asked questions
Where is the best place to put an upgrade prompt in a SaaS app?
Right after the merchant gets a result that the next plan would make bigger, inside the success message or notification. Usage limits and relevant empty states are the other two surfaces that work. Page-load banners and modals are the places merchants have learned to ignore.
Should an in-app upsell be a modal?
No. Nielsen Norman Group reserves modals for important warnings and critical errors, and Shopify's Built for Shopify requirements treat a modal that appears on page load or after a timer as a rejection reason. Use an inline card or banner that the merchant can dismiss, and do not show it again after they do.
How often can you show an upgrade prompt without annoying users?
One prompt per surface, one active prompt per merchant at a time, and a dismissal that lasts at least 30 days. If a merchant dismisses the same offer twice, stop showing it. Frequency caps protect the attention you need for the messages that matter, like a failed payout.
How do you measure whether in-app upsells are working?
Track a funnel from prompt seen to plan changed, with a control group of eligible merchants who did not see the prompt. Then watch downgrades, uninstalls and support tickets from the merchants who upgraded over the following 60 days. Conversion alone will reward prompts that pressure merchants into plans they then leave.