# See which campaign brings app installs

Last updated 31 October 2026

Make one link for each place you share your app: YouTube, TikTok, Instagram, a poster. Each link goes to the same app, but the App Store and Google Play see which link brought the visitor and count installs for each one. You read those numbers in App Store Connect and your analytics. There is nothing to add to your app.

## How to set it up

1. **Add your app.** Paste your App Store or Google Play link at app.oxi.cc/new. Jumper fills in the name, icon and both stores.
2. **Add one link per channel.** On your app’s page, press “Add the social set” to get links for YouTube, TikTok, Instagram, Facebook at once, or add a link for any other channel, a campaign or a poster.
3. **Add your Apple provider token once.** Copy the pt number from a campaign link in App Store Connect and paste it in your Jumper settings. Google Play needs nothing.
4. **Share each link in its own place.** Put the YouTube link in your YouTube description, the TikTok link in your TikTok bio, and so on.
5. **Read the numbers.** Taps per link are in Jumper. Installs per campaign are in App Store Connect and in Google Play’s referrer data.

## In plain words

The stores already know how to count installs per campaign. They just need to be told which campaign a visitor came from. A Jumper link tells them. You make one link per channel, and every link carries its own name to the store when someone taps it.

You do not change your app, add a library or ship an update. You do not need an account with an attribution company. You need one link per place you share your app, and a few minutes to set them up.

Jumper counts the taps on each link so you can compare channels the same day. The stores count the installs, because only they see an install happen.

## One app, many links

Every link of an app sends people to the same store pages. What differs is the name it carries: the channel (like YouTube), the medium (like description or bio), the campaign (like summer-launch) and, if you want, the content. Those names live in your Jumper account. The link itself is a short random address on oxi.cc, so nobody can guess another link or change the campaign by editing the address.

Here is an example for one app with three links. It is generated by the same code that builds the real store addresses:

```text
oxi.cc/k3xp9oq  (YouTube, description)
  App Store gets:   ct=yt-summer-launch  pt=123456
  Google Play gets: utm_source=yt&utm_medium=description&utm_campaign=summer-launch&jumper=lnk_k3xp9oq

oxi.cc/t7mq2lc  (TikTok, bio)
  App Store gets:   ct=tt-summer-launch  pt=123456
  Google Play gets: utm_source=tt&utm_medium=bio&utm_campaign=summer-launch&jumper=lnk_t7mq2lc

oxi.cc/r4nb0we  (Instagram, bio)
  App Store gets:   ct=ig-summer-launch  pt=123456
  Google Play gets: utm_source=ig&utm_medium=bio&utm_campaign=summer-launch&jumper=lnk_r4nb0we
```

## What each store receives

Apple receives a campaign token, ct, made of the channel and the campaign joined by a hyphen and cut to 30 characters, plus your provider token, pt. For the YouTube link above, an iPhone goes to https://apps.apple.com/app/id1234567890?pt=123456&ct=yt-summer-launch&mt=8.

Google Play receives a referrer with utm_source (the channel), utm_medium, utm_campaign, utm_content when you set it, and jumper=\<link id>. Google Play keeps it with the install and hands it to your app on first launch. Firebase Analytics reads the utm values on its own.

## Where each number appears

Three places, three different numbers. Each answers a different question.

### Where to read the numbers

Taps happen on the link; installs happen in the store.

| Where | What it counts | Split by |
| --- | --- | --- |
| Jumper stats | Taps and daily unique visitors per link | Link, channel, campaign, country, phone system, in-app browser |
| App Store Connect | Downloads and first-time downloads per campaign token (ct) | Campaign, under App Analytics, Sources, Campaigns |
| Google Play (in your app) | The referrer of each install, read by your app or by Firebase Analytics | utm_source, utm_medium, utm_campaign, utm_content, link id |

Apple shows campaign numbers only when enough people agreed to share data, so very small campaigns can show nothing.

## Reading the Google Play referrer in your app (optional)

With Firebase Analytics you need nothing more. Without it, read the referrer once on first launch with Google’s Install Referrer library. In Kotlin:

```kotlin
import android.content.Context
import android.net.Uri
import com.android.installreferrer.api.InstallReferrerClient
import com.android.installreferrer.api.InstallReferrerStateListener

data class JumperReferrer(val linkId: String?, val campaign: String?)

/** Reads the Jumper referrer once after install. Calls back with null if there is none. */
fun readJumperReferrer(context: Context, onResult: (JumperReferrer?) -> Unit) {
    val client = InstallReferrerClient.newBuilder(context).build()
    client.startConnection(object : InstallReferrerStateListener {
        override fun onInstallReferrerSetupFinished(code: Int) {
            var result: JumperReferrer? = null
            if (code == InstallReferrerClient.InstallReferrerResponse.OK) {
    // … the full function is on /docs/google-play-referrer
```

## The same in Flutter and React Native

Both use a small wrapper around Google’s library. The full Kotlin version and its explanation are on the Google Play referrer page.

```dart
// pubspec.yaml: android_play_install_referrer
import 'package:android_play_install_referrer/android_play_install_referrer.dart';

/// The Jumper link id and campaign, or null when the install did not come from a Jumper link.
Future<Map<String, String>?> readJumperReferrer() async {
  final details = await AndroidPlayInstallReferrer.installReferrer;
  final raw = details.installReferrer; // utm_source=yt&utm_medium=description&…&jumper=lnk_…
  if (raw == null) return null;
  final query = Uri.splitQueryString(raw);
  final linkId = query['jumper'];
  return linkId == null ? null : {'link': linkId, 'campaign': query['utm_campaign'] ?? ''};
}
```

## React Native

The referrer is Android only; Apple gives apps no referrer, which is why the ct token goes to App Store Connect instead.

```typescript
// npm install react-native-play-install-referrer
import { PlayInstallReferrer } from 'react-native-play-install-referrer';

/** Calls back with the Jumper link id and campaign, or null. Android only. */
export function readJumperReferrer(onResult: (r: { link: string; campaign: string | null } | null) => void) {
  PlayInstallReferrer.getInstallReferrerInfo((info, error) => {
    if (error || !info?.installReferrer) return onResult(null);
    const query = new URLSearchParams(info.installReferrer);
    const link = query.get('jumper');
    onResult(link ? { link, campaign: query.get('utm_campaign') } : null);
  });
}
```

## Taps per channel from the stats API

Every number in your Jumper stats is also available as JSON with a read-only token, grouped by link, channel, campaign, day, country or phone system:

```bash
curl -s 'https://app.oxi.cc/api/stats?app=6757088042&from=2026-10-01&to=2026-10-31&group=link,channel' \
  -H 'Authorization: Bearer jmp_…'
```

## Limits

Jumper counts taps, not installs. Apple’s campaign reports hide small numbers for privacy. Jumper does not do deferred deep links: after the install, your app opens at its start screen, not at a page chosen by the link. It does not follow what people do inside your app.

## Make your first link

Paste your App Store or Google Play link. 3 links are free, nothing to install in your app, no credit card.

Your App Store or Google Play link: [Get my free link](https://app.oxi.cc/new)

- 3 links free
- Nothing to install in your app
- No credit card

[Start from scratch](https://app.oxi.cc/new)

## Related

- [Apple campaign tokens (ct and pt)](https://jumper.to/docs/apple-campaign-tokens)
- [Google Play install referrer (full Kotlin)](https://jumper.to/docs/google-play-referrer)
- [Stats API](https://jumper.to/docs/stats-api)
- [Universal Links and App Links: when you need them](https://jumper.to/docs/universal-links-and-app-links)
- [Pricing](https://jumper.to/pricing)

## Questions

### Do I need to add anything to my app to see installs per channel?

No. The App Store and Google Play count installs for each link by themselves. You read the numbers in App Store Connect and in your analytics. Reading the Google Play referrer in your own code is optional.

### Does Jumper count installs?

No. Jumper counts taps on each link and how many different people tapped it each day. Installs are counted by Apple and Google, who see them. We show you where to find both numbers.

### Why do my links have random letters instead of the channel name?

So nobody can guess or edit them. The channel, medium and campaign live in your Jumper account, and each store receives them when someone taps the link. A link like oxi.cc/k3xp9oq looks the same whether it is in your YouTube description or on a poster.

### Why does App Store Connect show fewer installs than Jumper shows taps?

Not everyone who taps installs, and Apple only reports campaigns once enough people opted in to share data. Small numbers can stay hidden. Taps and installs are different things, so they never match exactly.

### Does it work inside Instagram and TikTok?

Yes. The campaign token and the referrer travel along on the route Jumper takes out of in-app browsers, on iPhone and on Android.

### Can I use my own campaign names?

Yes. Set the channel, medium, campaign and content on each link. Apple receives the channel and campaign joined by a hyphen, cut to 30 characters. Google Play receives all four as utm values.

### Does this replace an attribution platform?

No. It answers “which channel brought installs” with the stores’ own numbers. It does not follow people inside your app, match installs to ad clicks across apps, or open your app after the install at a specific screen.
