Skip to main content

iOS SDK

The Inhouse iOS SDK provides comprehensive tracking and analytics capabilities for your native iOS applications, including shortlink tracking, install attribution, and deep linking support.

Deep Linking Flow

The iOS SDK enables seamless deep linking between web and mobile experiences:

Installation

Swift Package Manager

Add the SDK using Swift Package Manager:
  1. In Xcode, go to File > Add Package Dependencies
  2. Enter the repository URL: https://github.com/tryinhouse/ios-sdk
  3. Select the latest version and click Add Package

CocoaPods

Add the SDK to your Podfile:
pod 'InhouseTrackingSDK', '~> 1.0.6'
Then run:
pod install

Manual Installation

Download the framework and add it to your project:
  1. Download the latest InhouseTrackingSDK.framework
  2. Drag the framework into your Xcode project
  3. Ensure “Copy items if needed” is checked
  4. Add the framework to your target’s “Frameworks, Libraries, and Embedded Content”

Quick Start

Basic Setup

Initialize the SDK in your app:
import InhouseTrackingSDK

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

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

        // Initialize the SDK
        InhouseTrackingSDK.shared.initialize(
            tokenId: "YOUR_TOKEN_ID",
            projectToken: "YOUR_PROJECT_TOKEN",
            shortLinkDomain: "yourdomain.com",
            serverUrl: "https://api.tryinhouse.com", // Optional
            enableDebugLogging: false, // Optional
            callback: { callbackType, jsonData in
                // Handle SDK callbacks
                switch callbackType {
                case "shortlink_click":
                    self.handleShortlinkClick(jsonData)
                case "app_install_from_shortlink":
                    self.handleAppInstall(jsonData)
                case "session_start_from_shortlink":
                    self.handleSessionStart(jsonData)
                default:
                    break
                }
            }
        )

        return true
    }

    private func handleShortlinkClick(_ jsonData: String) {
        // Handle shortlink click response
        print("Shortlink clicked: \(jsonData)")
    }

    private func handleAppInstall(_ jsonData: String) {
        // Handle app install attribution
        print("App installed from shortlink: \(jsonData)")
    }

    private func handleSessionStart(_ jsonData: String) {
        // Handle session start from shortlink
        print("Session started from shortlink: \(jsonData)")
    }
}

View Controller Integration

For proper deep link handling, set the current view controller:
import InhouseTrackingSDK

class ViewController: UIViewController {

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // Set current view controller for SDK
        InhouseTrackingSDK.shared.setCurrentViewController(self)

        // Track screen view if needed
        trackScreenView()
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        // Clear current view controller
        InhouseTrackingSDK.shared.setCurrentViewController(nil)
    }

    private func trackScreenView() {
        InhouseTrackingSDK.shared.trackCustomEvent(
            eventType: "screen_view",
            shortLink: nil,
            additionalData: [
                "screen": String(describing: type(of: self)),
                "timestamp": String(Int(Date().timeIntervalSince1970))
            ]
        ) { responseJson in
            print("Screen view tracked: \(responseJson)")
        }
    }
}

Event Tracking

App Open Tracking

Track when users open your app:
import InhouseTrackingSDK

// Track regular app open
InhouseTrackingSDK.shared.trackAppOpen { responseJson in
    print("App open tracked: \(responseJson)")
}

// Track app open from shortlink (automatically called by SDK)
InhouseTrackingSDK.shared.trackAppOpenFromShortLink(shortLink: "https://yourdomain.com/abc123") { responseJson in
    print("App open from shortlink tracked: \(responseJson)")
}

Session Tracking

Track user sessions:
// Track session start
InhouseTrackingSDK.shared.trackSessionStart { responseJson in
    print("Session started: \(responseJson)")
}

// Track session start from shortlink (automatically called by SDK)
InhouseTrackingSDK.shared.trackSessionStartFromShortLink(shortLink: "https://yourdomain.com/abc123") { responseJson in
    print("Session from shortlink started: \(responseJson)")
}
Track shortlink interactions:
// Track shortlink click
let shortLink = "https://yourdomain.com/abc123"
let deepLink = "yourapp://product?id=123"

InhouseTrackingSDK.shared.trackShortLinkClick(shortLink: shortLink, deepLink: deepLink) { responseJson in
    print("Shortlink click tracked: \(responseJson)")
}

Custom Event Tracking

Track custom business events:
// Track custom event without shortlink
InhouseTrackingSDK.shared.trackCustomEvent(
    eventType: "product_view",
    shortLink: nil,
    additionalData: [
        "product_id": "123",
        "category": "electronics",
        "price": "299.99"
    ]
) { responseJson in
    print("Custom event tracked: \(responseJson)")
}

// Track custom event with shortlink
InhouseTrackingSDK.shared.trackCustomEvent(
    eventType: "purchase_completed",
    shortLink: "https://yourdomain.com/promo123",
    additionalData: [
        "order_id": "order_456",
        "total": "599.99",
        "currency": "USD"
    ]
) { responseJson in
    print("Purchase event tracked: \(responseJson)")
}

Install Attribution

Install Referrer Tracking

The SDK automatically handles install attribution through App Store referrers:
// Get stored install referrer
if let installReferrer = InhouseTrackingSDK.shared.getInstallReferrer() {
    print("Install referrer: \(installReferrer)")
}

// Fetch install referrer asynchronously
InhouseTrackingSDK.shared.fetchInstallReferrer { referrer in
    if let referrer = referrer {
        print("Fetched install referrer: \(referrer)")
    } else {
        print("No install referrer available")
    }
}
Track app installs attributed to shortlinks:
let shortLink = "https://yourdomain.com/install123"

InhouseTrackingSDK.shared.trackAppInstallFromShortLink(shortLink: shortLink) { responseJson in
    print("Install from shortlink tracked: \(responseJson)")
}

Fingerprint-Based Install Tracking

Track app installs using device fingerprinting (no shortlink required):
// Track install via fingerprint identification
// The backend will identify the associated link via device fingerprinting
InhouseTrackingSDK.shared.trackAppInstallViaFingerprint { responseJson in
    print("Install via fingerprint tracked: \(responseJson)")
}

Deep Linking

Configure universal links in your iOS app:
// Add to your AppDelegate.swift
import InhouseTrackingSDK

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {

        if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
            if let url = userActivity.webpageURL {
                // Handle the universal link with SDK
                handleUniversalLink(url)
                return true
            }
        }

        return false
    }

    private func handleUniversalLink(_ url: URL) {
        // Let SDK handle shortlink detection and tracking
        InhouseTrackingSDK.shared.onNewURL(url)

        // Add your custom deep link routing here
        handleCustomDeepLink(url)
    }

    private func handleCustomDeepLink(_ url: URL) {
        guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else { return }

        let path = components.path
        let queryItems = components.queryItems ?? []

        // Parse query parameters
        var params: [String: String] = [:]
        for item in queryItems {
            params[item.name] = item.value
        }

        // Navigate based on path
        switch path {
        case "/product":
            if let productId = params["id"] {
                navigateToProduct(productId: productId)
            }
        case "/category":
            if let categoryId = params["id"] {
                navigateToCategory(categoryId: categoryId)
            }
        default:
            navigateToHome()
        }
    }
}

Custom URL Schemes

Handle custom URL schemes:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {

    // Let SDK handle shortlink detection and tracking
    InhouseTrackingSDK.shared.onNewURL(url)

    // Handle the custom scheme
    handleCustomScheme(url)
    return true
}

private func handleCustomScheme(_ url: URL) {
    guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else { return }

    let path = components.path
    let queryItems = components.queryItems ?? []

    // Parse query parameters
    var params: [String: String] = [:]
    for item in queryItems {
        params[item.name] = item.value
    }

    // Navigate based on path
    switch path {
    case "/product":
        if let productId = params["id"] {
            navigateToProduct(productId: productId)
        }
    case "/category":
        if let categoryId = params["id"] {
            navigateToCategory(categoryId: categoryId)
        }
    case "/search":
        if let query = params["q"] {
            navigateToSearch(query: query)
        }
    default:
        navigateToHome()
    }
}

App Lifecycle Integration

Handle app state changes for proper tracking:
class AppDelegate: UIResponder, UIApplicationDelegate {

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Notify SDK that app became active
        InhouseTrackingSDK.shared.onAppResume()
    }

    func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
        // Handle universal links
        if userActivity.activityType == NSUserActivityTypeBrowsingWeb,
           let url = userActivity.webpageURL {
            InhouseTrackingSDK.shared.onNewURL(url)
            handleCustomDeepLink(url)
            return true
        }
        return false
    }

    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        // Handle custom schemes
        InhouseTrackingSDK.shared.onNewURL(url)
        handleCustomScheme(url)
        return true
    }
}

SDK Information

Device and Session Information

Access SDK-generated identifiers:
// Get device ID
let deviceId = InhouseTrackingSDK.shared.getDeviceId()
print("Device ID: \(deviceId)")

// Get session ID
let sessionId = InhouseTrackingSDK.shared.getSessionId()
print("Session ID: \(sessionId)")

Debug and Testing

For development and testing:
// Reset first install flag for testing
InhouseTrackingSDK.shared.resetFirstInstall()

// Debug first install state
InhouseTrackingSDK.shared.debugFirstInstallState()

// Enable debug logging during initialization
InhouseTrackingSDK.shared.initialize(
    tokenId: "YOUR_TOKEN_ID",
    projectToken: "YOUR_PROJECT_TOKEN",
    shortLinkDomain: "yourdomain.com",
    enableDebugLogging: true // Enable for development
)

Privacy and Compliance

Data Collection

The SDK collects the following data automatically:
  • Device Information: Device ID (generated), user agent, IP address
  • Event Data: Timestamps, event types, shortlink URLs
  • Install Attribution: Install referrer data from App Store
  • Session Data: Session IDs, app open/close events
Implement user consent before initializing the SDK:
class AppDelegate: UIResponder, UIApplicationDelegate {

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

        // Check user consent before initializing
        if hasUserConsent() {
            initializeTrackingSDK()
        } else {
            // Show consent dialog or skip tracking
            showConsentDialog { granted in
                if granted {
                    self.initializeTrackingSDK()
                }
            }
        }

        return true
    }

    private func hasUserConsent() -> Bool {
        // Check your app's consent mechanism
        return UserDefaults.standard.bool(forKey: "analytics_consent")
    }

    private func initializeTrackingSDK() {
        InhouseTrackingSDK.shared.initialize(
            tokenId: "YOUR_TOKEN_ID",
            projectToken: "YOUR_PROJECT_TOKEN",
            shortLinkDomain: "yourdomain.com"
        )
    }
}

Advanced Features

Network Configuration

The SDK uses URLSession for network requests with the following defaults:
  • Timeout: 30 seconds connection timeout
  • Retry: Up to 3 retry attempts
  • HTTPS: All data transmitted over HTTPS

Error Handling

Handle SDK errors in your callback:
InhouseTrackingSDK.shared.trackCustomEvent(
    eventType: "user_action",
    shortLink: nil,
    additionalData: ["action": "button_click"]
) { responseJson in
    do {
        // Parse response
        if let data = responseJson.data(using: .utf8),
           let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
           let error = json["error"] as? String {
            print("SDK Error: \(error)")
        } else {
            print("Event tracked successfully")
        }
    } catch {
        print("Failed to parse SDK response: \(error)")
    }
}

Integration Examples

E-commerce Integration

class ProductViewController: UIViewController {

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // Set current view controller
        InhouseTrackingSDK.shared.setCurrentViewController(self)

        // Track product view
        trackProductView()
    }

    private func trackProductView() {
        guard let productId = self.productId else { return }

        InhouseTrackingSDK.shared.trackCustomEvent(
            eventType: "product_view",
            shortLink: nil,
            additionalData: [
                "product_id": productId,
                "category": "electronics",
                "price": "299.99",
                "currency": "USD"
            ]
        ) { responseJson in
            print("Product view tracked: \(responseJson)")
        }
    }

    @IBAction func addToCartTapped(_ sender: UIButton) {
        InhouseTrackingSDK.shared.trackCustomEvent(
            eventType: "add_to_cart",
            shortLink: nil,
            additionalData: [
                "product_id": "123",
                "quantity": "1",
                "total_value": "299.99"
            ]
        ) { responseJson in
            print("Add to cart tracked: \(responseJson)")
        }
    }
}

Marketing Campaign Tracking

class CampaignTracker {

    func trackCampaignConversion(campaignId: String, shortLink: String?) {
        InhouseTrackingSDK.shared.trackCustomEvent(
            eventType: "campaign_conversion",
            shortLink: shortLink,
            additionalData: [
                "campaign_id": campaignId,
                "conversion_type": "signup",
                "timestamp": String(Int(Date().timeIntervalSince1970))
            ]
        ) { responseJson in
            print("Campaign conversion tracked: \(responseJson)")
        }
    }

    func trackReferralEvent(referrerUserId: String) {
        InhouseTrackingSDK.shared.trackCustomEvent(
            eventType: "referral_signup",
            shortLink: nil,
            additionalData: [
                "referrer_user_id": referrerUserId,
                "referral_type": "friend_invite"
            ]
        ) { responseJson in
            print("Referral tracked: \(responseJson)")
        }
    }
}

Best Practices

Event Naming

  1. Use Descriptive Names: Use clear, descriptive event names like product_view, add_to_cart
  2. Consistent Naming: Use snake_case for event names consistently
  3. Meaningful Categories: Group related events with prefixes (user_action, ecommerce_event)

Data Management

  1. Minimal Data: Only include necessary data in additional properties
  2. Consistent Properties: Use consistent property names across events
  3. Valid Data Types: Ensure property values are strings

Performance Optimization

  1. Async Tracking: All SDK methods are asynchronous by default
  2. Batch Processing: SDK automatically batches events for efficiency
  3. Network Optimization: SDK handles network retries and timeouts

Privacy and Security

  1. User Consent: Always respect user privacy preferences
  2. Data Minimization: Only collect data necessary for your use case
  3. Secure Transmission: SDK uses HTTPS for all data transmission

Troubleshooting

Common Issues

Events Not Sending
  • Verify token ID and project token are correct
  • Check network connectivity
  • Enable debug logging to see detailed logs
  • Verify server URL configuration
Deep Links Not Working
  • Check iOS app configuration for universal links
  • Verify associated domains in your app’s entitlements
  • Test deep links using Simulator or device
  • Check URL scheme registration
Missing Attribution Data
  • Ensure install referrer is properly configured
  • Check App Store install referrer setup
  • Verify first install detection logic

Debug Commands

// Enable detailed logging
InhouseTrackingSDK.shared.initialize(
    tokenId: "YOUR_TOKEN_ID",
    projectToken: "YOUR_PROJECT_TOKEN",
    shortLinkDomain: "yourdomain.com",
    enableDebugLogging: true
)

// Check SDK state
print("Device ID: \(InhouseTrackingSDK.shared.getDeviceId())")
print("Session ID: \(InhouseTrackingSDK.shared.getSessionId())")
if let referrer = InhouseTrackingSDK.shared.getInstallReferrer() {
    print("Install Referrer: \(referrer)")
}

// Reset for testing
InhouseTrackingSDK.shared.resetFirstInstall()
InhouseTrackingSDK.shared.debugFirstInstallState()

Next Steps

Android SDK

Integrate with native Android apps.

API Reference

Use the REST API for advanced integration.

Deep Linking

Set up deep linking for seamless navigation.

Analytics

Understand your analytics data.
Need help with the iOS SDK? Check our API documentation or contact [email protected].