How affiliate attribution actually works — and why most tools get it wrong
Attribution is the whole job of an affiliate platform: credit the affiliate who genuinely drove an install, and only that affiliate. On Shopify it's deceptively hard — and the common shortcut quietly pays the wrong person. Here's what's really going on, and how to do it right.
The problem: Shopify strips your query params
The obvious approach is to tag the affiliate's link with a code — ?ref=CODE — and read it back when the merchant installs your app. It seems simple. It doesn't work on its own.
When a merchant installs a Shopify app, the flow passes through the App Store and Shopify's OAuth. Along the way, Shopify strips arbitrary query parameters. By the time your app's install callback runs, that ?ref=CODE is gone. The affiliate's code never reaches the moment where you'd record the referral.
The shortcut most tools take (and why it misattributes)
Because the code is lost, many affiliate tools fall back to a heuristic: when a new install shows up, look back ~30 days for any affiliate click for that app and credit the most recent one.
The trouble is that a click carries no shop identifier — it happens before the install, in a different browser context. So "the most recent click for this app" is a guess. If two affiliates promoted you in the same window, the last click wins, even if the other one drove the install. Worse, a single stray click — say, an affiliate testing their own link — can capture an entirely unrelated install and pay it to the wrong person.
The right way: carry the code through the install
You don't fight Shopify's redirect — you use the one field it's required to preserve: the OAuth state parameter. It's the CSRF nonce your app already sends, and Shopify hands it back to your callback untouched. So you tuck the affiliate code inside it:
- The affiliate link routes the merchant to your install URL carrying
?ref=CODE. - At install start, you read
refand pack it into the signedstatenonce. - Shopify returns
stateto your OAuth callback intact. - You unpack
refand record the install against the exact affiliate — with the shop domain.
That shop domain + affiliate code pairing is the whole point: it identifies precisely which install came from which affiliate. No guessing, no cookies, no 30-day window. It's deterministic.
One exception: apps on Shopify managed installation / token exchange have no developer-controlled OAuth redirect and no state, and Shopify confirms there is no supported way to carry a custom value through that install. For those apps the deterministic path isn't available, so attribution falls back to the GA4 route below (best-effort). If your app can run its own auth route, use it, the state carry is the only method that credits every install exactly.
What about existing Mantle-style links?
Mantle-style programs use a direct App Store link with ?mref=CODE. Everything keeps working, with one nuance worth understanding. When the merchant goes through a tracked redirect, the mref code reaches your install flow and is credited exactly, the same as ref. When a merchant clicks a raw App Store ?mref= link, Shopify strips the parameter before your callback, so it can only be recovered through GA4 (best-effort, see below). Either way, ref, mref, and utm_source all resolve to one affiliate code, so migrating between tools never breaks a single affiliate's link.
The GA4 route (best-effort fallback)
When the code can't be carried through the install (a raw App Store link, or a managed-installation app), the fallback is GA4. If you connect GA4 to your app listing, Shopify records the referral code on the listing page view and fires a server-side install event for the shop. Joining those two in the GA4 to BigQuery export (by session) maps the code to the shop, which we then match to your Partner API data. Shopify does not guarantee the match rate, and it misses cross-device installs and anyone who blocks tracking, so it is a best-effort signal we surface for review, never an automatic exact match. The state carry above is what makes attribution exact.
How PartnerDock does it
PartnerDock is built around deterministic attribution. Exact matches — where the merchant demonstrably came through the affiliate's link — are credited automatically. Anything uncertain (an install with no forwarded code, matched only by the last-click window) is never auto-approved; it waits for the founder to confirm, so a stray click can't quietly pay out.
Setup is a one-time, ~10-minute integration, with copy-paste examples for Remix, Next.js, Express, Gadget and more — and a dashboard status that flips to Verified the moment a real install carries a code end to end. Existing App Store and redirect links keep working throughout.
Run an affiliate program on numbers you can trust
PartnerDock gives Shopify app founders deterministic attribution, commission tiers, automated payouts, and a done-for-you affiliate portal — with free migration from Mantle.
