Skip to main content

Referral Tracking

Growth

Understand how referral attribution works, configure conversion windows, and debug tracking issues.

Link Tracking

URL parameter attribution

Conversion Window

Time-based attribution

Deep Links

Mobile app integration

Cross-Device

Multi-device attribution

How Referral Attribution Works

Sylphx uses a multi-layered attribution system to accurately track referrals across devices and sessions.

1

Link Click

User clicks a referral link containing the referral code (e.g., ?ref=ABC123). The click is logged and the code is stored.

2

Code Storage

The referral code is stored in multiple places: URL parameter, first-party cookie, and localStorage. This ensures attribution survives redirects and session changes.

3

Attribution Window

If the user signs up within the attribution window (default: 7 days), they're linked to the referrer. The window starts from the first click.

4

Conversion Tracking

On signup, the stored code is retrieved and validated. If valid, the referral is recorded and rewards are triggered.

Attribution flow
// 1. User arrives via referral link
// URL: https://myapp.com/signup?ref=ABC123

// 2. SDK automatically captures the code
// On page load, the SDK:
// - Reads ?ref parameter
// - Stores in cookie (sylphx_ref=ABC123, expires: 7 days)
// - Stores in localStorage (sylphx_referral_code)
// - Logs click event

// 3. During signup, retrieve the code
import { platform } from '@/lib/platform'

const referralCode = await platform.referrals.getStoredCode()
// Returns: 'ABC123' or null

// 4. Redeem on successful signup
if (referralCode) {
  await platform.referrals.redeem({
    code: referralCode,
    newUserId: newUser.id,
  })
}

First Touch vs Last Touch

Sylphx uses first-touch attribution by default. If a user clicks multiple referral links, only the first one counts. This can be changed to last-touch in settings.

Conversion Window Configuration

The conversion window determines how long after a click a signup can be attributed to the referrer.

PropertyTypeDescription
windowDaysnumber= 7Days a referral code remains valid after first click
attributionModel"first_touch" | "last_touch"= "first_touch"Which click gets credit when multiple referrers involved
extendOnActivityboolean= falseExtend window when user returns to site
crossDeviceboolean= trueEnable cross-device attribution via email link
Configuration
// Dashboard: App Settings → Growth → Referrals → Attribution

{
  "attribution": {
    "windowDays": 7,
    "attributionModel": "first_touch",
    "extendOnActivity": false,
    "crossDevice": true,

    // Advanced options
    "cookieSettings": {
      "name": "sylphx_ref",
      "secure": true,
      "sameSite": "lax",
      "domain": ".myapp.com"  // Include subdomains
    },

    // Custom expiration rules
    "customRules": [
      {
        "condition": "campaign == 'holiday2024'",
        "windowDays": 14  // Extended window for campaigns
      }
    ]
  }
}

Window Best Practices

3 days

Quick-decision products, impulse purchases

7 days

Standard SaaS, most consumer apps (recommended)

14 days

High-consideration purchases, B2B products

30 days

Enterprise sales, long sales cycles

Deep Linking for Mobile

Enable seamless referral tracking in native mobile apps with deep linking support.

Universal Links & App Links

Sylphx supports both iOS Universal Links and Android App Links for a seamless mobile experience.
// 1. Configure apple-app-site-association
// Host at: https://myapp.com/.well-known/apple-app-site-association

{
  "applinks": {
    "apps": [],
    "details": [{
      "appID": "TEAM_ID.com.myapp.app",
      "paths": ["/invite/*", "/?ref=*"]
    }]
  }
}

// 2. Handle incoming link in AppDelegate
func application(_ application: UIApplication,
                 continue userActivity: NSUserActivity,
                 restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {

    guard let url = userActivity.webpageURL else { return false }

    // Extract referral code
    if let code = URLComponents(url: url, resolvingAgainstBaseURL: true)?
        .queryItems?
        .first(where: { $0.name == "ref" })?
        .value {

        // Store and track
        SylphxSDK.referrals.handleDeepLink(code: code)
    }

    return true
}

Deferred Deep Linking

Handle cases where the app isn't installed yet. The referral code is preserved through the app store.

Deferred deep link flow
// Flow:
// 1. User clicks referral link on mobile
// 2. App not installed → redirect to App Store
// 3. User installs and opens app
// 4. SDK retrieves deferred referral code

// iOS - Handle in AppDelegate
func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    // Check for deferred deep link
    SylphxSDK.referrals.checkDeferredDeepLink { result in
        switch result {
        case .success(let code):
            // Referral code retrieved from install attribution
            print("Deferred referral code: \(code)")
        case .failure(let error):
            print("No deferred link: \(error)")
        }
    }

    return true
}

Cross-Device Attribution

Track referrals when users start on one device and sign up on another.

Mobile click → Desktop signup → Attribution preserved
Cross-device tracking
// Cross-device attribution methods:

// 1. Email-based linking (recommended)
// When user enters email during checkout/signup flow:
await platform.referrals.linkEmail({
  email: 'user@example.com',
  referralCode: storedCode,  // From current device
})

// Later, when same email signs up on different device:
const attribution = await platform.referrals.getAttributionByEmail('user@example.com')
// Returns the stored referral code if within attribution window

// 2. Logged-in user detection
// If user logs into existing account on new device:
await platform.referrals.syncCrossDevice({
  userId: user.id,
  currentDeviceId: getDeviceId(),
})

// 3. Probabilistic matching (when enabled)
// Uses device characteristics, IP, and timing to match users
// Less accurate but works without email/login

// Configuration:
{
  "crossDevice": {
    "enabled": true,
    "methods": ["email", "login", "probabilistic"],
    "probabilisticThreshold": 0.85  // Confidence threshold
  }
}

UTM Parameter Integration

Combine referral tracking with UTM parameters for comprehensive campaign analytics.

UTM integration
// Referral links can include UTM parameters
const referralUrl = await platform.referrals.createLink({
  userId: user.id,
  utm: {
    source: 'referral',
    medium: 'share',
    campaign: 'launch-2024',
    content: 'sidebar-widget',
    term: 'premium-trial',
  },
})
// https://myapp.com/?ref=ABC123&utm_source=referral&utm_medium=share&...

// UTM data is captured alongside referral attribution
const attribution = await platform.referrals.getAttribution(userId)
// {
//   referralCode: 'ABC123',
//   referrerId: 'user_456',
//   clickedAt: '2024-01-15T10:30:00Z',
//   signedUpAt: '2024-01-16T14:20:00Z',
//   utm: {
//     source: 'referral',
//     medium: 'share',
//     campaign: 'launch-2024',
//     content: 'sidebar-widget'
//   },
//   device: 'mobile',
//   browser: 'safari'
// }

// Query referrals by UTM campaign
const campaignReferrals = await platform.referrals.query({
  filter: {
    'utm.campaign': 'launch-2024',
  },
  groupBy: 'utm.content',
})
// See which share buttons/placements drive most referrals
PropertyTypeDescription
utm_sourcestringTraffic source (e.g., "referral", "twitter")
utm_mediumstringMarketing medium (e.g., "share", "email")
utm_campaignstringCampaign name for grouping
utm_contentstringSpecific content/placement identifier
utm_termstringKeywords or variant identifier

Debugging Attribution Issues

Tools and techniques for troubleshooting referral attribution problems.

Debug Mode

Enable debug mode
// Enable debug mode in development
import { SylphxSDK } from '@sylphx/sdk'

SylphxSDK.configure({
  debug: true,  // Enables verbose logging
  debugReferrals: true,  // Extra referral-specific logging
})

// Console output:
// [Sylphx Referrals] Code detected in URL: ABC123
// [Sylphx Referrals] Storing code in cookie (expires: 7d)
// [Sylphx Referrals] Storing code in localStorage
// [Sylphx Referrals] Click tracked: { code: ABC123, timestamp: ... }

// Test attribution without affecting production data
await platform.referrals.testRedeem({
  code: 'ABC123',
  testUserId: 'test_user_1',
  dryRun: true,  // Don't actually create referral
})
// Returns what would happen, including any errors

Common Issues

Code not captured

Cause: Ad blocker or privacy extension blocking cookies/localStorage

Solution: Use server-side parameter extraction as fallback

Attribution lost on redirect

Cause: Code not persisted before redirect to OAuth provider

Solution: Store code before redirect, retrieve after callback

Wrong referrer attributed

Cause: Multiple referral links clicked, attribution model mismatch

Solution: Check attribution model settings (first vs last touch)

Cross-device not working

Cause: Email not linked or probabilistic matching disabled

Solution: Ensure email capture before signup completes

Attribution Inspector

Inspect attribution state
// Get detailed attribution state for debugging
const debugInfo = await platform.referrals.debug({
  userId: 'user_123',  // Optional: for specific user
})

// Response:
{
  // Current session state
  session: {
    storedCode: 'ABC123',
    storageLocations: ['cookie', 'localStorage'],
    cookieExpires: '2024-01-22T10:30:00Z',
    firstClickAt: '2024-01-15T10:30:00Z',
  },

  // Attribution history
  history: [
    {
      code: 'ABC123',
      clickedAt: '2024-01-15T10:30:00Z',
      source: 'url_parameter',
      device: 'mobile',
      ip: '192.168.x.x',
    },
    {
      code: 'XYZ789',
      clickedAt: '2024-01-10T08:00:00Z',
      source: 'url_parameter',
      device: 'desktop',
      overwritten: true,  // Was replaced by ABC123
    },
  ],

  // Validation
  validation: {
    codeValid: true,
    codeExpired: false,
    referrerExists: true,
    referrerMaxedOut: false,
    withinWindow: true,
  },

  // Potential issues
  warnings: [
    'Multiple referral codes detected - using first_touch model',
  ],
}

// Check specific code validity
const codeCheck = await platform.referrals.validateCode('ABC123')
// {
//   valid: true,
//   referrerId: 'user_456',
//   createdAt: '2024-01-01',
//   expiresAt: '2024-01-31',
//   usageCount: 12,
//   usageLimit: 50,
// }

Dashboard Tools

The Sylphx dashboard includes a visual attribution debugger. Enter a user ID or referral code to see the full attribution chain and identify issues.

Ready to analyze your referral performance?

Learn how to measure viral coefficient, optimize your funnel, and identify top referrers.

Referral Analytics