UTM parameters are one of those things that just work. Stick ?utm_source=newsletter&utm_medium=email&utm_campaign=march on the end of a URL, and Google Analytics tells you exactly where that visitor came from. Simple. Reliable. Free.
Then you try to do the same thing for a mobile app, and the whole system falls apart.
Why UTMs break for mobile apps
The problem is straightforward. UTM parameters live in URLs. When someone clicks a UTM-tagged link to your website, the browser carries those parameters through to the page load, and your analytics tool reads them. The chain is unbroken.
With mobile apps, that chain snaps in at least two places.
First, the App Store sits between your link and the install. Someone clicks your UTM link, lands on the App Store listing, taps "Get," waits for the download, opens the app. By that point, the original URL parameters are gone. The App Store doesn't pass them through.
Second, even if you could somehow preserve UTM data through the install, there's a time gap. People don't always install immediately. They might see your link on Tuesday, install on Thursday, and make their first purchase the following week. UTM parameters don't survive that kind of delay.
So the web approach โ append UTMs, read them on arrival โ doesn't translate to mobile. You need a different mechanism.
What people try (and why it mostly doesn't work)
Firebase Dynamic Links used to be the standard answer. Google's dynamic links could carry UTM parameters through the install process and into the app on first open. It was clever, widely used, and Google shut it down in August 2025. If you were relying on it, you already know this.
Branch and AppsFlyer offer deep linking that preserves campaign data through installs. They work well. They also cost hundreds of pounds a month, which is a strange amount to spend on campaign tracking when you're making a few hundred in revenue.
Apple's campaign attribution API gives you some data about App Store search ads, but it only covers Apple Search Ads. It tells you nothing about your TikTok posts, email newsletters, or Reddit comments.
Manual UTM tracking with a web redirect is the scrappy approach. You send people to a landing page with UTMs, log the visit server-side, then redirect to the App Store. You know who clicked, but you still can't connect that click to an actual in-app purchase unless you have something linking the two events together.
That last approach is closest to what actually works. It just needs one more piece.
The approach that works: tracked links with purchase attribution
The idea is essentially UTM tracking, rebuilt for mobile. Instead of tagging a URL with parameters and hoping the destination reads them, you create a tracked link that logs the click server-side, then connects it to the install and any purchases that follow.
Here's the flow:
- You create a link for a specific campaign, source, or channel (the same way you'd create a UTM-tagged URL)
- Someone clicks that link
- The click gets logged with all the context โ where it came from, when, what device
- The person installs your app and the SDK matches them back to that click
- When they make a purchase, the purchase gets attributed to the original link
You end up with the same data UTMs give you on the web โ which source, which campaign, which medium โ but it survives the App Store gap.
Setting this up with LinkOwl
LinkOwl does exactly this. You create links (think of them as UTM-tagged URLs for mobile), and each link tracks clicks through to purchases.
Step 1: Create your links with campaign context
When you create a link in LinkOwl, you name it something descriptive. "Newsletter - March 12" or "Reddit - r/indiedev post" or "TikTok - bio link week 11." This is your UTM equivalent โ the name is how you identify the source later.
Step 2: Use those links wherever you'd normally use UTM URLs
Put them in your email campaigns, social media bios, Reddit posts, landing pages, QR codes. Anywhere you'd normally drop a UTM link.
Step 3: Connect purchase tracking
If you use RevenueCat, add LinkOwl's webhook URL in your RevenueCat dashboard. Every purchase event gets sent to LinkOwl automatically. If you're using StoreKit directly, the Swift SDK handles it with a few lines of code.
Step 4: Read the data
Your LinkOwl dashboard shows clicks, installs, and purchases per link. You can see which campaign drove the most revenue, not just the most clicks.
What you get that UTMs can't give you
Web UTMs tell you about sessions. Someone visited from this source, viewed these pages, maybe converted. With mobile attribution, you're tracking actual purchases tied to specific marketing links. That's closer to what matters.
A few things I've found useful about this approach:
Revenue per source, not just clicks. Your newsletter might drive fewer clicks than TikTok, but if newsletter visitors purchase at 3x the rate, you want to know that. Click-through rates alone don't tell you.
Time-to-purchase by channel. Some channels produce fast converters. Others bring people who browse for a week before buying. Understanding this changes how you evaluate a campaign that looks like it's underperforming โ it might just be slow.
Actual ROI on paid campaigns. If you're spending money on a Reddit ad or a creator sponsorship, you can calculate real cost per acquisition. Not estimated, not modelled โ actual purchases divided by actual spend.
Naming conventions that help
Since your link names are your campaign identifiers, it's worth being consistent. I use a simple format:
[Channel] - [Campaign or content description] - [Date or batch]
Examples:
- "Email - Weekly digest - March 12"
- "TikTok - Bio link - Teeth brushing video"
- "Reddit - r/SideProject launch post"
- "Instagram - Story swipe up - Promo batch 3"
Keep it readable. You'll be scanning these in a dashboard, not writing database queries. Future you will appreciate knowing what "TikTok - March 12" referred to.
The cost question
LinkOwl charges 5p per attributed purchase. No monthly fee. If a campaign drives 50 purchases, that's ยฃ2.50 in attribution costs. If a campaign drives zero purchases, you pay nothing.
Compare that to a ยฃ200/month MMP subscription where you're paying the same whether you have 10 purchases or 10,000. For apps doing under a few thousand purchases a month, pay-per-sale pricing makes more sense mathematically.
Getting started
If you're currently using UTMs for web and have nothing for mobile, the gap in your data is probably bigger than you think. Every app install from a marketing link is a black box right now.
Setting up tracked links takes about 10 minutes. Create an account, connect your purchase tracking, and create links for your active campaigns. After a week, you'll have the mobile equivalent of the UTM data you've been relying on for web โ and you'll probably rethink at least one channel based on what you find.