<MT />
Back to Blog
App Store Connectapp attributioncampaign linksApp Analyticsindie appsiOSapp marketing

App Store Campaign Links: The Indie Attribution Checklist

T

Muhammad Tayyab

October 9, 2026·16 min read
Hand holding an iPhone showing an analytics dashboard with key metrics and a traffic chart — photo by Swello via Unsplash

Small iOS apps keep finding that App Store search drives most installs and link clicks are mostly noise. Here's how to set up Apple's free campaign links (pt/ct tokens), read the numbers despite the 5-user threshold, and avoid the usual attribution traps.

Early October on Indie Hackers turned into a run of install post-mortems, and they kept landing on the same awkward point.

  • A solo developer behind a small US stock-and-options app shared 45 days of install data (Oct 3, 2026). The headline: "82% of my iOS installs came from App Store search." Over 90 days, about four out of five iOS downloads started with a typed query, and daily link clicks had a correlation of about -0.1 with new users. In other words, none. When the developer dug into the logs, a crawler was hitting several links in the same millisecond.
  • A developer relaunching a dead 2020 iOS app tagged every channel link from day one (Oct 6, 2026), because "App Store Connect hides campaign numbers until a source has five downloads." In a follow-up reply: "of the first four downloads App Store Connect attributed, three were Search and one Browse, so the tagged links haven't moved anything yet."
  • I've already written about the SelfOS install wave, where 2,475 of 2,536 iOS installs over 90 days came from App Store search, so I'll leave that one alone here.

None of these posts prove a universal rule. They're a handful of small apps. Still, the pattern is consistent enough to act on: for a small iOS app, your click counter is probably not measuring what you think it is, and App Store search will often take credit for installs that your posts actually caused.

You can't fix that completely. You can get much closer with a free tool that's already in App Store Connect: campaign links. This post covers setting them up, reading the results honestly, and the traps that quietly break attribution.

What a campaign link actually is

A campaign link is your normal App Store URL with two tokens added. Apple's own example:

https://apps.apple.com/app/apple-store/id123456789?pt=123456&ct=test1234&mt=8
  • pt (provider token): identifies your developer account. Apple generates it the first time you create a campaign link. It stays the same for every campaign and app, and you can't create one by hand.
  • ct (campaign token): the campaign name you choose. It can be up to 30 characters (letters, numbers, spaces and a set of punctuation marks) and can't start or end with a space.
  • mt=8: the media type. Leave it as Apple generates it.

When someone taps the link and makes a first-time download within 24 hours, App Analytics credits that download to the campaign. If they tapped more than one of your campaign links, the most recent one wins.

Everything stays inside Apple's analytics, so there's no SDK, no fingerprinting and no consent banner. The trade-off is that Apple gives you aggregate numbers only, behind privacy thresholds.

Design your token scheme before you make a single link

Most of the value comes from naming things consistently. With 30 characters to work with, a simple channel_placement_date pattern holds up well:

  • ig_bio_2610: Instagram bio link, started October 2026
  • x_launch_thread_2610: the launch thread on X
  • ih_post_2610: an Indie Hackers build story
  • newsletter_oct26: your own email list
  • site_footer: the App Store badge on your website
  • creator_jane_2610: one specific creator or affiliate. Tag the person, not just the platform.

A finished link looks like this:

https://apps.apple.com/app/apple-store/id<YOUR_APP_ID>?pt=<YOUR_PT>&ct=ig_bio_2610&mt=8

Keep a plain list somewhere, in a note or spreadsheet, of every ct value, where it lives and when it went live. Six weeks from now you won't remember what x2_alt meant.

Setup checklist

  • Make sure your app has analytics data. The Campaigns tab and its + button only appear after the app has been live and generating downloads for at least 24 hours.
  • Generate your first link in App Store Connect: Apps → your app → Analytics → Acquisition → Campaigns → +. Enter a campaign name and copy the link. This is also how you get your pt value.
  • Make one link per placement, not one per platform. An Instagram bio link and an Instagram story link are two campaigns.
  • Link straight to apps.apple.com. Every extra redirect through a shortener or link-in-bio service is another place for blockers, in-app browsers or bot filters to break things.
  • Don't worry about storefronts. Users get redirected to their local App Store storefront, so a /us/ in the link doesn't limit who can use it.
  • For cross-promotion from your other apps, present the product page with SKStoreProductViewController and pass SKStoreProductParameterCampaignToken and SKStoreProductParameterProviderToken. Apple attributes those downloads the same way it does a normal campaign link.
  • For iMessage apps or sticker packs, add &app=messages to send people to the App Store for iMessage.
  • Test every link on a real iPhone, inside every app it will live in (Instagram, X, Threads, Reddit, Messages, your email client), not just in Safari on your desktop.

Add custom product pages for the channels that matter

Campaign tokens tell you who sent someone. Custom product pages let you change what they see when they arrive, and Apple measures each page separately.

  • You can create up to 70 custom product pages per app, each with its own screenshots, previews, promotional text and optional keywords.
  • Each page gets a unique URL that adds a ppid= (product page ID) parameter to your normal App Store link.
  • App Analytics shows impressions, downloads and conversion rate per page once a page has at least five first-time downloads.
  • Pages need App Review approval, work on iOS 15 and later, and can include an app deep link for users on iOS 18 and later.

A commenter on the finance-app thread suggested exactly this pairing: one custom product page per main channel, with screenshots and opening line matched to the post that sent the visitor. That gives you per-channel conversion even while a channel's campaign numbers are still too small to show.

Apple's docs show campaign tokens and ppid separately and don't document a URL that combines both. Many developers append pt/ct to a custom product page URL. If you try that, confirm in App Analytics that both the page and the campaign are recording before you rely on it.

(If your screenshots themselves need work, that's a separate job. Fix the page before you blame the channel.)

How to read the results

Where to look:

  • Acquisition → Campaigns: per-campaign impressions, product page views, first-time downloads and more.
  • Metrics → Add Filter → Campaign: lets you break any metric down by campaign.
  • Acquisition → Sources: App Store Search, App Store Browse, App Referrer, Web Referrer and others. This is where untagged traffic ends up.
  • The App Store Analytics API detailed reports, if you want raw exports. Apple notes that small groups of users may be withheld or combined there too.

The threshold, stated precisely. The pitch for this post said "a 5-download reporting threshold". Apple's wording is a bit different, and the difference matters:

  • Each campaign metric shows up only if it reaches at least 5 in the date range you've selected.
  • A campaign's data appears once it has generated first-time downloads from at least five individual users.
  • New campaigns appear in the dashboard after at least 24 hours.

In practice, a link that brought in three installs this week can look identical to a link that brought in zero. Widen the date range before deciding a channel is dead. Apple suggests this directly, and it's the single most useful habit here.

What the sources really mean:

  • App Store Search covers taps in App Store search results, including Apple Ads in search. It also absorbs everyone who saw your app name in a video or post, didn't click, and typed it in later. Both the finance-app and SelfOS developers concluded their posts were working through search. The finance-app developer found that posts per day correlated with next-day new users at roughly r = 0.5 over about 18 days, and called it a hypothesis from a small sample.
  • App Referrer means someone tapped a link inside another app, including apps that use StoreKit and Apple apps like Messages. Safari is excluded.
  • Web Referrer means a link on a website opened in Safari. If a chain of redirects led to the App Store, the last URL in the chain gets the credit.
  • Downloads that can't be attributed, such as promo codes and gift cards, show up as Unavailable.

A practical reading routine:

  • Compare first-time downloads by campaign over 30 or more days, not day by day.
  • Check product page views per impression and conversion rate for search traffic. If people see you in search but don't open the page, the problem is your icon, name or subtitle, not your posting schedule.
  • Look for search lifts that line up with posting days. A creator on X suggested comparing "first-time downloads in app store connect the 48h after posting vs a normal day" alongside a tagged bio link. That's crude, but honest.
  • Add a one-question "Where did you hear about us?" screen in onboarding. It's the only way to name the source behind a "search" install.

Pitfalls that quietly break attribution

  • In-app browsers. On iOS, a tap from a non-Safari browser such as Chrome is credited to that browser app under App Referrer, not to Web Referrer. Links opened in social apps have the same problem. The campaign token still works, which is exactly why you need it. Also check your own redirect code: the finance-app developer found their router treated KakaoTalk's in-app browser as a link-preview bot, so real taps got a preview card instead of a redirect. A commenter added that Facebook and Instagram in-app browsers include "FBAN/FBAV" or "Instagram" in a real person's user agent, while the preview fetcher is facebookexternalhit. Match exact bot names, never app names.
  • Bots inflating click counts. If you run your own click counter, audit it for same-millisecond hits and spikes at the same hour every day. After cleaning up, the finance-app developer counts only likely-human navigations and excludes known collectors, prefetches and requests without normal browser headers.
  • Ad and content blockers. Shorteners, link-in-bio services and third-party click trackers are exactly the kind of domains blockers and privacy tools interfere with. Apple's campaign link doesn't need any of them, so keep the redirect chain as short as you can, ideally zero hops.
  • Web-to-app hops. For sites opened in Safari, only the last URL before the App Store gets credit. If your landing page sends people through a tracker domain, the tracker gets the Web Referrer credit, not your page. Put the ct link directly on the button.
  • Last click overwrites earlier clicks. Someone who taps your newsletter link and later your Instagram link gets credited to Instagram. Don't treat campaigns as cleanly separate audiences.
  • The 24-hour window. If someone taps today and installs three days later after searching your name, that's a search download, not a campaign download.
  • Smart App Banners. Apple says you can add your ct and pt tokens to a Smart App Banner, but its banner docs only spell out app-id and app-argument. The syntax developers commonly pass around (affiliate-data=pt=…&ct=…) isn't in Apple's current banner documentation, and forum reports are mixed. Treat it as unverified until you see it in your own campaign data. Banners also don't appear inside frames or in the Simulator.
  • Tiny numbers. Below the threshold, a dead channel and a slow one look the same. Don't kill a channel because of one empty week.

What to do this week

  • Monday: generate your first campaign link, write down your pt, and draft a token list for every place you currently link to your app.
  • Tuesday: replace every App Store link you control (website badge, bios, email footer, pinned posts) with its own tagged link that goes straight to apps.apple.com.
  • Wednesday: test each link on a real iPhone inside the apps it lives in, and check your own redirect or bot rules for in-app browser user agents.
  • Thursday: pick your highest-intent channel and draft a custom product page whose screenshots and first line match what that audience saw.
  • Friday: add a "Where did you hear about us?" question to onboarding, with "a video", "a post" and "searched the App Store" as options.
  • In 30 days: open Campaigns with a 30-day range, compare first-time downloads and conversion rate, and only then decide where your posting time goes.

Soft close

Campaign links won't show you the person who heard your app's name in a video and typed it into search. Nothing will. What they do is turn "I think Instagram works" into a number you can check, and they stop you from crediting a channel because of clicks that were mostly bots. For a solo developer, a few hours of setup pays off every time you decide where to spend your time.

If you're setting up attribution for an iOS app and want a second pair of eyes on the link structure or the analytics, get in touch.

About the author

Muhammad Tayyab is a full-stack and mobile developer based in Lahore. He builds DripScore, an AI outfit rating app live on the App Store, under dawnapps.co. Find him on GitHub, LinkedIn, and X, or say hello at /#contact.

Sources

Back to all posts
Thanks for reading 🙏