Docs/Determinism
Documentation

Determinism

A first-class classification of how a payload reached the app — reported with every session resolution.

Why determinism matters

Attribution SDKs that use probabilistic device matching often present a confidence score but default to matching anyway. When confidence is low, a mislabeled attribution creates a false record: a referred user who wasn't referred, a partner offer shown to someone who didn't come from that partner, a referral credit paid for nothing.

Forwarded makes determinism a property of the session, not an afterthought. Every resolved session includes a mechanism field (smart_app_banner, install_referrer, universal_link, app_link, explicit_token) and a determinism field (deterministic, lower_confidence, unknown).

You decide how to act on each tier. Gate referral credit on deterministic sessions only. Accept lower_confidence for informational welcome screens. Log unknowns without taking any business action. Forwarded reports honestly — what you do with the classification is your call.

Deterministic paths

These mechanisms guarantee one-to-one binding between the web visit and the app open: iOS Smart App Banner (app-argument passed by Safari through the App Store install), Universal Links (domain-verified HTTPS URLs that open the app directly), Android Install Referrer API (Google Play delivers a custom string to the app on the first post-install launch), App Links (domain-verified intent filters on Android).

Each of these is a native OS feature that exists specifically to connect web context to native apps. Forwarded uses them as the transport layer, adding session management, HMAC signing, and expiry on top.

When a session resolves via one of these paths, Forwarded marks it deterministic and records the exact mechanism. No confidence score — deterministic means one-to-one.

Lower confidence paths

Some paths are lower confidence: generic App Store redirects (where app-argument may not be preserved by the OS), in-app browsers that suppress Smart App Banner (Instagram, Facebook, many WebViews), and fallback device-matching (opt-in only).

Forwarded marks these sessions lower_confidence and includes the reason in the mechanism field. Your code can choose to use the payload for informational purposes, or discard it for irreversible business actions.

Forwarded will never label a lower-confidence resolution as deterministic. The classification is honest by design, even when honesty means a lower attribution rate.

Reading determinism in your app

The resolved session object exposes mechanism and determinism properties. Check them before taking irreversible actions — crediting a referral, applying a discount, or joining a team.

// iOS (Swift)
if let session = await Forwarded.resolvePending() {
  switch session.determinism {
  case .deterministic:
    applyPayload(session.payload)   // credit referral, show offer, etc.
  case .lowerConfidence:
    showGenericWelcome()            // informational only
  default:
    break                           // log and skip
  }
}

// Android (Kotlin)
val session = Forwarded.resolvePending()
when (session?.determinism) {
  Determinism.DETERMINISTIC    -> applyPayload(session.payload)
  Determinism.LOWER_CONFIDENCE -> showGenericWelcome()
  else                         -> Unit
}