Skip to main content
Prefer to let your AI coding agent do this? Install the Linkrunner skill and Claude Code, Cursor, GitHub Copilot, or Windsurf will wire up the SDK and deep links for you:
Then ask your agent to “integrate Linkrunner”. See Linkrunner Agent Skills.

Requirements

  • iOS 15.0 or higher
  • Swift 5.9 or higher
  • Xcode 14.0 or higher

Installation

Swift Package Manager

The Linkrunner SDK can be installed via Swift Package Manager (SPM), which is integrated directly into Xcode.
  1. In Xcode, select FileAdd Package Dependencies…
  2. Enter the following repository URL:
  3. Select the version you want to use (we recommend using the latest version)
  4. Click Add Package
  5. Choose the library type LinkrunnerKitStatic
Alternatively, you can add the package dependency to your Package.swift file:
And add the dependency to your target:

Importing in Swift

After installation, you can import the SDK in your Swift files:
Use import LinkrunnerKit for v3.0.0 and later. The public API remains LinkrunnerSDK.shared.

Required Permissions

App Tracking Transparency

If you plan to use IDFA (Identifier for Advertisers), you need to request permission from the user through App Tracking Transparency. Add the following to your Info.plist file:

SKAdNetwork Configuration

To enable SKAdNetwork postback copies to be sent to Linkrunner, add the following keys to your Info.plist file:
For complete SKAdNetwork integration details, see the SKAdNetwork Integration Guide.

Network Access

The SDK requires network access to communicate with Linkrunner services. Make sure your app has the appropriate permissions for network access.

Google Integrated Conversion Measurement (Optional)

Prefer to let your AI coding agent do this? The iOS skill already covers ICM — adding Google’s ODM SDK and wiring setConsent:
See Linkrunner Agent Skills.
Integrated Conversion Measurement (ICM) recovers Google App Campaign installs that Google cannot attribute because there is no click identifier and no IDFA to match on. Google’s On-Device Measurement (ODM) SDK turns the click context into an encrypted signal that never leaves the device, and Linkrunner sends it with the install. See Google ICM for how it works. Set this up if you run Google App Campaigns for your iOS app. Requires LinkrunnerKit 4.1.0 or later.
Google keeps ODM inactive for users in the European Economic Area, the United Kingdom, and Switzerland, so ICM recovers nothing for that traffic. Elsewhere, Google reports improved coverage for iOS 14+ users.
ICM also needs an iOS link ID configured in your Google Ads integration. Google has nowhere to send the conversion without one. See Prerequisites.
1

Add Google's On-Device Measurement SDK

Already using the Firebase iOS SDK 11.14.0 or later? The FirebaseAnalytics pod brings this SDK in for you. Skip to the next step.
Linkrunner does not bundle this SDK, so apps that skip ICM carry none of its weight. Add it to your app yourself.
Add https://github.com/googleads/google-ads-on-device-conversion-ios-sdk in FileAdd Package Dependencies… and select the GoogleAdsOnDeviceConversion product.
2

Add the -ObjC linker flag (Swift Package Manager only)

Using CocoaPods? Skip this step. CocoaPods adds -ObjC and -lc++ for you when it links Google’s static framework. The one exception is an app target whose Other Linker Flags no longer contain $(inherited), in which case add -ObjC yourself.
If you added Google’s SDK with Swift Package Manager, add this to Build SettingsOther Linker Flags on your app target:
Without it, ICM silently does nothing and your build still succeeds. Linkrunner finds Google’s class through the Objective-C runtime, so nothing references it at link time, and the linker drops it from Google’s static library.
3

Provide consent

Google reads consent signals when it matches your installs. See Consent below.
That is the whole integration. Linkrunner detects the SDK at runtime and there is no API to call. Attribution comes back through getAttributionData as usual.
ODM matches on the time of first launch, which Linkrunner records when you call initialize.
ICM complements SKAdNetwork, it does not replace it. Keep your existing SKAdNetwork integration in place.
Google needs to know whether European regulations apply to a user and what that user agreed to. Set the values with setConsent before you call initialize, and again whenever the user changes their choice.
Each takes .granted, .denied, or .unknown. Anything left .unknown is omitted rather than reported as a denial, so Linkrunner never reports a choice your user did not make. Google treats these as required whenever their value is known. hasConsentForDataUsage decides whether Google may use the conversion at all, hasConsentForAdsPersonalization decides whether it may feed audiences and remarketing, and isEEA tells Google which rules apply. Set them from your app’s real consent state rather than hardcoding them. For users outside the EEA, the UK, and Switzerland, report isEEA as denied and leave the other two unset. See Send Consent. App Tracking Transparency is not a substitute, because it governs IDFA access only and is reported separately.
Consent is stored between launches. Call setConsent again whenever the user’s consent state changes, otherwise the previous value keeps being sent after your user has withdrawn it.

Verifying your setup

Initialize with debug: true and look for this line in the Xcode console:
odm_available=false with odm_fetch_result=unavailable means Google’s SDK is not linked. On Swift Package Manager, check the -ObjC flag first, because a missing flag strips the class with no build warning.

Initialization (Required)

Initialize the Linkrunner SDK in your app’s startup code, typically in your AppDelegate or SceneDelegate: You can find your project token here. Note: The initialization method doesn’t return any value. To get attribution data and deeplink information, use the getAttributionData method.

SDK Signing Parameters (Optional)

For enhanced security, the LinkRunner SDK requires the following signing parameters during initialization:
  • secretKey: A unique secret key used for request signing and authentication
  • keyId: A unique identifier for the key pair used in the signing process
  • disableIdfa (optional): Boolean flag to disable IDFA collection (defaults to false)
  • debug (optional): Boolean flag to enable debug mode for development (defaults to false)
You can find your project token, secret key, and key ID here.

Setting the Customer User ID

Use setCustomerUserId to attach your own user identifier to the device right after init. Once set, the identifier is stored securely on-device and automatically included in every event you track, so you never have to pass it on each trackEvent call. Call it as early as the user’s ID is available. This guarantees every event carries a user_id from the very first event, and is especially useful for existing users who were already onboarded before this feature shipped.
Available from iOS SDK v3.11.0.
Best practice: set the Customer User ID as early as possible. The user_id is only attached to events tracked after it’s set, and is not applied retroactively. Use a stable, unique identifier from your own system (for example your internal user ID or a UUID) rather than an email address or other PII.
The identifier is stored in the Keychain and persists across app restarts. Calling setCustomerUserId again with a different identifier updates the stored value; passing the same identifier is a no-op. signup() / setUserData() also update it.

User Identification (Required)

Call the signup method as soon as the user is identified — whether through signup or login. This is the moment Linkrunner ties the install (and any future events) to a user identifier. It is strongly recommended to use the integrated platform’s identify function to set a persistent user_id once it becomes available (typically after signup or login). If the platform’s identifier function is not called, you must provide a user identifier for Mixpanel, PostHog, and Amplitude integration.
  • mixpanelDistinctId for Mixpanel
  • amplitudeDeviceId for Amplitude
  • posthogDistinctId for PostHog
To enable remarketing and reattribution, you need to capture deep links and pass them to the Linkrunner SDK. This allows Linkrunner to detect returning users who open the app via a deep link. Add the following to your SceneDelegate.swift:
Linkrunner sends the updated deeplink back after processing. For Linkrunner campaign links, use the returned deeplink as the resolved destination instead of the original tracking URL.

Getting Attribution Data

To get attribution data and deeplink information for the current installation, use the getAttributionData function:
Example response (raw values — type/adNetwork decode to enums, installedAt/storeClickAt to Date):

Setting User Data

Call setUserData each time the app opens and the user is logged in:
setUserData is optional and is not a replacement for signup. Always call signup first as soon as the user is identified (signup or login). Use setUserData afterwards only when additional user details become available later — for example, when the user adds a phone number, email, or completes their profile after identification.

Setting CleverTap ID

Use setAdditionalData to add CleverTap ID to the SDK:

Revenue Tracking

Revenue data is only stored and displayed for attributed users. Make sure you have implemented the .signup function before capturing payments. To attribute a test user, follow the Integration Testing guide. You can verify your events are being captured on the Events Settings page.

Capturing Payments

Track payment information:

Available Payment Types

Available Payment Statuses

Removing Payments

Remove payment records (for refunds or cancellations):

Tracking Custom Events

From iOS SDK v3.11.0, custom events automatically include the user_id you set during signup() / setUserData(). The SDK stores this identifier securely on-device (Keychain) and attaches it to every trackEvent call, so you no longer need to pass it manually. Events tracked before signup are sent without a user_id.
Events are only stored and displayed for attributed users. Make sure you have implemented the .signup function before tracking events. To attribute a test user, follow the Integration Testing guide. You can verify your events are being captured on the Events Settings page. For capturing revenue, it is recommended to use the .capturePayment method instead of .trackEvent.
Track custom events in your app:

Parameters for LinkrunnerSDK.shared.trackEvent

  • eventName: String (required) - Name of the event to track
  • eventData: [String: Any] (optional) - Key-value pairs for additional event data, including Meta ecommerce properties
  • eventId: String (optional) - Your own unique identifier for the event, useful for deduplication and correlating with your backend

Revenue Sharing with Ad Networks

To enable revenue sharing with ad networks like Google Ads and Meta, include an amount parameter as a number in your custom event data. This allows the ad networks to optimize campaigns based on the revenue value of conversions:
For revenue sharing with ad networks to work properly, ensure the amount parameter is passed as a number (Double or Int), not as a string.

Ecommerce Events

Minimum SDK Version: Ecommerce Event Manager requires linkrunner-ios v3.8.0 or above. Please ensure your SDK is updated before using this feature.
If you are tracking Ecommerce events to sync with Meta Catalog Sales, you must format your eventData to include Meta’s required fields. You also need to map your custom event to the standard commerce event in the Linkrunner Dashboard. For detailed explanations of the required fields like content_ids, contents, and value, refer to our Meta Commerce Manager documentation.

Add To Cart Example

Use the trackEvent method to send an AddToCart event:

View Content Example

Use the trackEvent method to send a ViewContent event:

Payment / Purchase Example

Use the capturePayment method to send a Purchase event containing the ecommerce payload:
Note: For more information on testing and verifying your ecommerce events, please see our Testing Ecommerce Events guide.

Enhanced Privacy Controls

The SDK offers options to enhance user privacy:
When PII hashing is enabled, sensitive user data like name, email, and phone number are hashed using SHA-256 before being sent to Linkrunner servers.

Uninstall Tracking

Before you begin

Here’s what you need to know before getting started: Requirements:

iOS

Connect APNs with Linkrunner
Get the required credentials from the Apple Developer Portal:APNs Authentication Key (p8) and Key ID:
  • Go to the Apple Developer Portal.
  • Select Identifiers under Certificates, IDs & Profiles.
  • Click on the app you want to track uninstalls for. Then, under Capabilities, search for Push Notifications and enable it.
  • Under Certificates, IDs & Profiles, select Keys and click on plus (+) icon to create a key. Enable APNs when creating the key and download the key file (p8).
  • The Key ID can be found in the Keys tab.
Bundle ID and Team ID:
  • Under Identifiers, click on your app and you will see the Bundle ID and Team ID (App ID Prefix).
  1. In Linkrunner, go to Settings > Uninstall Tracking.
  2. Under the iOS tab, upload the APNs Authentication Key (p8) file and enter the Key ID, Bundle ID and Team ID (App ID Prefix) that you copied from the Apple Developer Portal. Uninstall Tracking
Follow these instructions to integrate APNs with the Linkrunner SDK:
  1. Set up Push Notifications:
Enable push notifications in your Xcode project by adding the Push Notifications capability.
  1. Configure your app to provide the device’s APNs token to the Linkrunner SDK.
For SwiftUI apps using the new app lifecycle:

Function Placement Guide

Complete Example

Here’s a simplified example showing how to integrate Linkrunner in a SwiftUI iOS app: You can find your project token here.

Next Steps

Test Your Integration

Validate your setup end-to-end

Set Up Deep Linking

Configure deep links for your app

Support

If you encounter issues during integration, contact us at support@linkrunner.io.