UTM Tracking for AppsFlyer: How to Build and Validate Campaign Links

AppsFlyer is the world's largest mobile attribution platform, used by app marketers to measure installs, re-engagements, and in-app events across every major ad network. AppsFlyer's OneLink technology — hosted at app.appsflyer.com or a custom domain — is the click-tracking backbone for every campaign using AppsFlyer as the mobile measurement partner. The core attribution gap: AppsFlyer uses its own parameter format (af_channel, af_ad, af_adset, af_campaign) to record attribution in the AppsFlyer dashboard. These are AppsFlyer's internal parameters and do not populate GA4 web session attribution. When an AppsFlyer OneLink redirects to a web destination — which happens for web-to-app campaigns, desktop fallbacks, and retargeting campaigns with both mobile and web traffic — GA4 records the session as Direct unless standard UTM parameters are present in the destination URL. Build your tracked destination URL with mlz build --source "appsflyer" --medium "[channel]" --campaign "your-slug" --validate, set the resulting tracked_url as the af_web_dp parameter in your OneLink, and run mlz check on the full OneLink URL to confirm UTM parameters survive the AppsFlyer redirect chain before launch.

Terminal showing mlz build generating utm_source=appsflyer tracked URL, redirect chain from OneLink to af_web_dp destination with UTM parameters intact, warning panel distinguishing af_channel from utm_medium, and validated URL pill at the bottom.

Why AppsFlyer campaigns need separate UTM parameters for GA4

AppsFlyer and GA4 are parallel measurement systems that operate at different levels of the attribution stack. AppsFlyer measures mobile attribution: which ad networks, campaigns, and creatives drove app installs and re-engagements, attributed using device fingerprinting, SKAN 4.0 (for iOS), and probabilistic matching. GA4 measures web session behavior: how users interact with web pages and complete web-based conversions. The two systems intersect whenever an AppsFlyer OneLink redirects traffic to a web destination rather than directly to the app store.

When a user on desktop clicks an ad that uses AppsFlyer OneLink tracking, AppsFlyer cannot redirect to the App Store — there is no App Store on desktop. Instead, OneLink redirects to the af_web_dp (web destination parameter) URL you configured. If that URL does not contain UTM parameters, GA4 sees a web session with no referrer information and attributes it as Direct. The AppsFlyer parameters that record the click (af_channel, af_ad) are in the OneLink URL itself — they are not forwarded to the destination URL by AppsFlyer and are not readable by GA4. The same problem occurs on mobile for users who don't have the app installed: OneLink serves the web fallback URL, and without UTM parameters on that fallback URL, the GA4 session is unattributed.

The solution is to build UTM-tagged destination URLs and use them as the af_web_dp value in OneLink. This way, GA4 reads the UTM parameters from the destination URL query string and attributes the web session correctly, while AppsFlyer reads its own parameters from the OneLink URL and records mobile attribution independently. Both measurement systems work simultaneously without any conflict.

Parameter type Where it appears What it tracks Used by
af_channel AppsFlyer OneLink URL Channel in AppsFlyer dashboard AppsFlyer SDK (mobile)
af_campaign AppsFlyer OneLink URL Campaign name in AppsFlyer AppsFlyer SDK (mobile)
utm_source=appsflyer af_web_dp destination URL Web session source in GA4 GA4 (web)
utm_medium af_web_dp destination URL Channel classification in GA4 GA4 (web)
utm_campaign af_web_dp destination URL Campaign grouping in GA4 reports GA4 (web)

AppsFlyer's documentation recommends adding UTM parameters to the af_web_dp destination URL for exactly this reason. The two parameter sets coexist on the same session without conflict: AppsFlyer reads its own parameters from the OneLink URL and assigns mobile attribution; GA4 reads UTM parameters from the destination URL and assigns web session attribution.

Building tracked AppsFlyer destination URLs with mlz build

In AppsFlyer OneLink, the af_web_dp parameter specifies the web destination URL for desktop users and mobile users who don't have the app installed. This is where UTM parameters belong. Build your tracked destination URL with mlz build, then set the resulting tracked_url as the af_web_dp value in your OneLink configuration. Use --validate to confirm the destination resolves correctly and the redirect chain preserves UTM parameters. After configuring the OneLink, run mlz check on the full OneLink URL to verify end-to-end UTM preservation across the complete redirect chain.

mlz build — AppsFlyer campaign destination URLs by channel
# Paid social campaign (desktop fallback web destination)
$ mlz build \
  --url "https://example.com/install" \
  --source "appsflyer" \
  --medium "paid-social" \
  --campaign "ios-ua-jun-2026" \
  --validate

{
  "tracked_url": "https://example.com/install?utm_source=appsflyer&utm_medium=paid-social&utm_campaign=ios-ua-jun-2026",
  "params": {
    "utm_source": "appsflyer",
    "utm_medium": "paid-social",
    "utm_campaign": "ios-ua-jun-2026"
  },
  "stored": true
}

# Paid search campaign (CPC, desktop users redirect to web)
$ mlz build \
  --url "https://example.com/offer" \
  --source "appsflyer" \
  --medium "cpc" \
  --campaign "search-brand-jun-2026" \
  --content "headline-a" \
  --validate

{
  "tracked_url": "https://example.com/offer?utm_source=appsflyer&utm_medium=cpc&utm_campaign=search-brand-jun-2026&utm_content=headline-a"
}

# Retargeting campaign (email re-engagement via AppsFlyer email partner)
$ mlz build \
  --url "https://example.com/come-back" \
  --source "appsflyer" \
  --medium "email" \
  --campaign "retargeting-lapsed-jun-2026" \
  --validate

{
  "tracked_url": "https://example.com/come-back?utm_source=appsflyer&utm_medium=email&utm_campaign=retargeting-lapsed-jun-2026"
}

Set the tracked_url as the af_web_dp parameter in your AppsFlyer OneLink template. In the AppsFlyer dashboard, navigate to your OneLink template, find the "Web fallback" or "af_web_dp" field, and paste the tracked URL as the value. When a desktop user or a mobile user without the app clicks the OneLink, AppsFlyer records the attribution event and redirects to this tracked URL. GA4 reads the UTM parameters and correctly attributes the web session.

Validating UTM parameters survive the AppsFlyer OneLink redirect

AppsFlyer OneLink redirects route clicks through AppsFlyer's click-recording servers before sending the user to the final destination. On mobile, OneLink evaluates whether to redirect to the app store (for new users), launch the app directly (for existing users), or fall back to the web destination. On desktop, OneLink redirects directly to the af_web_dp URL. Each redirect hop is an opportunity for UTM parameters to be stripped — particularly if the af_web_dp value is not correctly URL-encoded in the OneLink URL, or if an intermediate server in your destination stack rewrites URLs.

After configuring the OneLink with your tracked destination URL, validate the full OneLink URL to confirm UTM parameters arrive intact at the final destination.

mlz check — validate UTM parameters survive AppsFlyer OneLink redirect
# Check the complete OneLink URL (not just the destination)
# Confirms UTM parameters survive the OneLink redirect chain
$ mlz check "https://yourapp.onelink.me/aBcD?pid=paid_social&af_channel=facebook&af_web_dp=https%3A%2F%2Fexample.com%2Finstall%3Futm_source%3Dappsflyer%26utm_medium%3Dpaid-social%26utm_campaign%3Dios-ua-jun-2026"

{
  "url": "https://yourapp.onelink.me/aBcD?pid=paid_social&af_channel=facebook&af_web_dp=...",
  "valid": true,
  "checks": [
    { "check": "ssl", "status": "pass", "message": "URL uses HTTPS." },
    { "check": "resolution", "status": "pass", "message": "Destination responded with 200." },
    { "check": "redirects", "status": "pass", "message": "2 redirects detected. UTM parameters present at final destination." }
  ],
  "status_code": 200
}

If the redirect check reports missing UTM parameters at the final destination, verify that the af_web_dp value in the OneLink URL is correctly URL-encoded (the & between UTM parameters must be encoded as %26 within the af_web_dp query parameter value). Also check whether any CDN, load balancer, or server-side URL rewriting in your destination stack strips query parameters on redirect. See the guide to detecting redirect-based UTM stripping for step-by-step diagnosis.

AppsFlyer UTM tracking gotchas

AppsFlyer's af_channel and af_campaign parameters are not UTM parameters and are not read by GA4
AppsFlyer uses its own parameter naming convention for attribution: pid (media source), af_channel, af_campaign, af_ad, af_adset, af_sub1 through af_sub5. These parameters are in the OneLink URL itself and are read by the AppsFlyer SDK after app install via the install referrer or SKAN attribution. GA4 does not understand AppsFlyer's parameter format. Only standard utm_source, utm_medium, and utm_campaign parameters in the destination URL's query string affect GA4 channel grouping and campaign attribution. This is why you need UTM parameters on the af_web_dp destination URL even though you already have af_channel and af_campaign in the OneLink URL.
AppsFlyer's Smart Script can auto-inject UTM parameters from the referrer — but it's not reliable for all traffic types
AppsFlyer offers a "Smart Script" that can automatically pass UTM parameters from the referring page's URL into the OneLink. If a user lands on your website from a Google Ads click with utm_source=google and then clicks a OneLink, Smart Script can forward those UTM parameters to the af_web_dp destination. However, Smart Script only works for web-to-app flows where the referring page has UTM parameters — it does not work for direct app store links, it does not generate UTM parameters for direct clicks without a UTM-tagged referrer, and it requires JavaScript on the referring page. For programmatic, multi-channel campaigns where you control the OneLink parameters directly, building explicit UTM-tagged destination URLs with mlz build is more reliable and auditable than relying on Smart Script auto-injection.
OneLink templates serve multiple ad networks — you need separate UTM medium values per network
A single AppsFlyer OneLink template is typically used across multiple ad networks — Facebook, Google Ads, TikTok, and other partners all use the same OneLink domain but with different pid and af_channel values. If you set a single af_web_dp URL with a fixed utm_medium=paid-social across all networks, GA4 will attribute Google Ads clicks as "paid-social" when they redirect to the web destination. Build separate tracked destination URLs per medium with mlz build and configure them as separate af_web_dp values per network in your OneLink template, or use AppsFlyer's dynamic parameters to inject the correct medium into the destination URL at click time.
AppsFlyer's SKAN 4.0 (iOS privacy framework) changes click routing — UTM parameters on the web destination still work
iOS 14.5 and later require app marketers to use Apple's SKAN (StoreKit Ad Network) framework for iOS attribution. Under SKAN 4.0, AppsFlyer cannot use device-level identifiers for attribution and instead relies on SKAN's probabilistic attribution model. SKAN attribution affects how AppsFlyer attributes iOS app installs in its dashboard — it does not affect the web redirect behavior of OneLink. When an iOS user without the app clicks a OneLink, the OneLink still redirects to the App Store or to the af_web_dp URL depending on device state. UTM parameters on the af_web_dp URL continue to work normally for GA4 web session attribution regardless of iOS privacy restrictions, since UTM parameters are in the URL and do not rely on device identifiers.
URL-encoding the af_web_dp value is critical when building OneLink URLs programmatically
The af_web_dp parameter in the OneLink URL must contain a URL-encoded version of the destination URL. The & character separating UTM parameters in the destination URL must be encoded as %26 within the af_web_dp value. If it is not encoded, AppsFlyer's URL parser may interpret the & as a separator between OneLink parameters, breaking both the destination URL and the OneLink parameter parsing. After constructing the complete OneLink URL with the af_web_dp value, always run mlz check on the complete OneLink URL to verify that the redirect chain resolves to the correct destination with UTM parameters intact.

AppsFlyer UTM naming conventions

Recommended UTM parameter values for AppsFlyer campaigns, aligned with GA4 channel reporting and a lowercase-hyphenated taxonomy:

  • utm_source: appsflyer for all campaigns where AppsFlyer is the measurement platform. Some teams prefer to use the underlying ad network name (facebook, google, tiktok) as the UTM source, matching the pid parameter in the OneLink. Using appsflyer as the source makes it immediately clear in GA4 that these web sessions originated from AppsFlyer-tracked campaigns — useful when you have both AppsFlyer-tracked campaigns and campaigns tracked without an MMP running simultaneously. Choose one convention and apply it consistently. If you use network names, maintain a clear mapping between AppsFlyer pid values and your utm_source values in your campaign taxonomy documentation.
  • utm_medium: Use the channel type of the campaign, not "appsflyer" — AppsFlyer is the measurement platform, not the channel. For Meta/Facebook campaigns: paid-social. For Google UAC and App campaigns: cpc or paid-search. For TikTok campaigns: paid-social. For programmatic/display: display. For email re-engagement campaigns via AppsFlyer email partner integrations: email. For push notification retargeting campaigns: push. Align utm_medium with GA4's default channel groupings to ensure web sessions from AppsFlyer campaigns are grouped into the correct channel buckets in GA4 reports.
  • utm_campaign: A consistent lowercase-hyphenated campaign name that mirrors your AppsFlyer campaign name where possible. For user acquisition: ios-ua-jun-2026, android-acquisition-jun-2026. For retargeting: retargeting-cart-abandon-jun-2026, retargeting-lapsed-30d. For loyalty/retention: retention-power-users-jun-2026. Aligning utm_campaign values with AppsFlyer af_campaign values makes cross-referencing GA4 web data with AppsFlyer install data much easier.
  • utm_content: Creative or ad variant identifier. For A/B tested creative variants: utm_content=creative-a, utm_content=creative-b. For campaigns with multiple ad sizes or formats: utm_content=video-15s, utm_content=static-square. Mirrors the af_ad or af_ad_id parameter in the OneLink for cross-system creative performance analysis.
  • utm_term: Keyword or audience segment identifier. For Apple Search Ads campaigns tracked via AppsFlyer (where keyword-level data is available): the search keyword. For audience-targeted retargeting campaigns: the audience segment identifier. Omit for campaigns where keyword-level attribution is not relevant (most mobile UA campaigns).

See the UTM naming conventions guide for the full cross-platform taxonomy reference, and the UTM tracking for developers guide for programmatic generation workflows at scale.

FAQ

Does AppsFlyer automatically add UTM parameters to the web destination URL?
No, not by default. AppsFlyer's Smart Script feature can auto-inject UTM parameters from the referring page's URL into the af_web_dp destination for web-to-app flows, but Smart Script only works when the referring page already has UTM parameters and requires JavaScript on the referring page. For programmatic campaigns where you control the OneLink parameters directly, build explicit UTM-tagged destination URLs with mlz build --source "appsflyer" --medium "[channel]" --campaign "your-slug" --validate and set those tracked URLs as the af_web_dp value in your OneLink configuration. Explicit UTM construction is more reliable and auditable than Smart Script auto-injection.
Why do my AppsFlyer campaign clicks show as Direct in GA4?
If AppsFlyer is recording clicks and attributing installs correctly but GA4 shows the resulting web sessions as Direct, UTM parameters are missing from the af_web_dp destination URL. This is the most common scenario for teams new to running AppsFlyer alongside GA4. The fix: generate a UTM-tagged destination URL with mlz build --source "appsflyer" --medium "[channel]" --campaign "your-campaign" --validate, then update your OneLink's af_web_dp value to that tracked URL. Run mlz check on the full OneLink URL afterward to confirm UTM parameters survive the redirect chain.
Can I use AppsFlyer attribution and UTM parameters on the same campaign?
Yes, and this is the recommended approach. AppsFlyer attribution parameters (pid, af_channel, af_campaign) are in the OneLink URL and are read by the AppsFlyer SDK after app install. UTM parameters (utm_source, utm_medium, utm_campaign) are in the af_web_dp destination URL and are read by GA4 when the user lands on the web page. The two systems are completely independent. Use both simultaneously: AppsFlyer measures mobile attribution, GA4 measures web session behavior. Cross-reference in AppsFlyer's Cohort Analysis or via BigQuery for full-funnel performance.
What is the difference between using utm_source=appsflyer vs. the network name (e.g., utm_source=facebook)?
Both are valid and functional in GA4. Using utm_source=appsflyer groups all AppsFlyer-tracked web sessions together in GA4, regardless of the underlying ad network — useful for understanding the overall volume of web traffic from AppsFlyer campaigns. Using the network name (utm_source=facebook, utm_source=google) makes GA4 channel groupings match the actual ad network, which is helpful if you compare campaigns across networks in GA4 directly. The tradeoff: if you use network names, you need different af_web_dp URLs per network in your OneLink template, or AppsFlyer dynamic parameters to inject the correct source. Using utm_source=appsflyer allows a single af_web_dp URL with network differentiation via utm_medium and utm_campaign. Pick the approach that matches your GA4 reporting requirements and apply it consistently.
How do I validate UTM parameters survive the full OneLink redirect chain?
Run mlz check "https://yourapp.onelink.me/aBcD?pid=...&af_web_dp=your-encoded-tracked-url" on the full OneLink URL. The redirect chain check confirms that UTM parameters present in the af_web_dp value arrive intact at the final destination after all OneLink redirect hops. If UTM parameters are being stripped, verify that the af_web_dp value is properly URL-encoded (especially that & is encoded as %26) and check whether any server-side URL rewriting at your destination strips query strings. See the redirect UTM stripping guide for diagnosis steps.

Build AppsFlyer campaign destination URLs from the terminal

Use mlz build --source "appsflyer" --medium "[channel]" --campaign "your-slug" --validate to generate validated tracked URLs for each AppsFlyer campaign. Set the resulting tracked_url as the af_web_dp parameter in your OneLink configuration. After setup, run mlz check on the complete OneLink URL to confirm UTM parameters survive the redirect chain to the final destination before the campaign goes live.

npm install -g missinglinkz

Free plan: 1,000 links/month. No credit card. See the UTM tracking for developers guide for the full programmatic workflow including API and MCP integration.