Prerequisites
- Unity 2021.3 LTS or newer
- Android: Android 5.0+ (API 21), Gradle 8.0+
- iOS: iOS 15.0+, Xcode 14.0+, Swift 5.9+
- A Linkrunner project token — get it from Dashboard → Documentation
Architecture Overview
The integration uses Unity’s native plugin system:- Android: A Java bridge class calls
LinkrunnerJava(the SDK’s callback-based Java API) and communicates results back to Unity viaUnitySendMessage. - iOS: A Swift bridge file wraps the Linkrunner iOS SDK’s
asyncmethods into C-callable functions (via@_cdecl), which Unity calls through[DllImport("__Internal")]. - C#: A
LinkrunnerSDK.cswrapper provides a unified cross-platform API.
Android Setup
Step 1: Add the SDK Dependency
In your Unity project, create or edit the fileAssets/Plugins/Android/mainTemplate.gradle (or your custom Gradle template) and add:
Assets/Plugins/Android/settingsTemplate.gradle:
Step 2: Permissions
Add the following to yourAssets/Plugins/Android/AndroidManifest.xml:
AD_ID permission:
Step 3: Create the Java Bridge
CreateAssets/Plugins/Android/LinkrunnerBridge.java:
iOS Setup
Step 1: Add the SDK
After building your Unity project for iOS and opening the generated Xcode project:- In Xcode, select File → Add Package Dependencies…
- Enter the repository URL:
- Select the latest version (3.8.0+)
- Click Add Package and choose the LinkrunnerStatic library
Step 2: Info.plist Configuration
Add to yourInfo.plist (can also be done via Unity’s Assets/Plugins/iOS/Info.plist additions):
Step 3: Create the Swift Bridge
The Linkrunner iOS SDK is a pure Swift module — it does not inherit fromNSObject and has no @objc annotations, so it cannot be called directly from Objective-C. We use a Swift bridge file with @_cdecl to expose C-callable functions that Unity can invoke via [DllImport("__Internal")].
Create Assets/Plugins/iOS/LinkrunnerUnityBridge.swift:
C# Wrapper
CreateAssets/Scripts/LinkrunnerSDK.cs in your Unity project:
Usage
Scene Setup
- Create an empty
GameObjectin your first scene - Name it
LinkrunnerCallbackHandler(must match exactly) - Attach the
LinkrunnerSDK.csscript to it
Initialization (Required)
CallInitialize as early as possible — typically in your startup scene:
User Identification (Required)
CallSignup 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.
Handle Deeplinks
CallHandleDeeplink when your app is opened via a deeplink — both cold start (app was closed) and warm start (app was in background):
deeplink from OnDeeplinkHandled as the resolved destination instead of the original tracking URL.
The
is_linkrunner field indicates whether the deeplink was created through Linkrunner. Use this to determine if you should apply Linkrunner-specific attribution logic.- Android
- iOS
Create a custom Update your
UnityPlayerActivity to capture deeplinks:AndroidManifest.xml to use this activity and add intent filters for your deeplink scheme.Set User Data on App Open
Call every 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.Get Attribution Data
OnAttributionData event. With the reference bridge code in this guide, the shape differs by platform.
iOS
Track Events
When tracking revenue-related events, the
amount field must be a number (not a string) for ad network revenue optimization to work correctly.Capture Payment
paymentId is required and must be unique for each payment. It is used for idempotent deduplication, so retries cannot double count revenue.
Payment types: FIRST_PAYMENT, SECOND_PAYMENT, WALLET_TOPUP, FUNDS_WITHDRAWAL, SUBSCRIPTION_CREATED, SUBSCRIPTION_RENEWED, ONE_TIME, RECURRING, DEFAULT
Payment statuses: PAYMENT_INITIATED, PAYMENT_COMPLETED, PAYMENT_FAILED, PAYMENT_CANCELLED
Remove Payment (Refunds)
Push Token
Privacy Controls
Function Placement Guide
| Function | Where to Call | When |
|---|---|---|
Initialize | First scene / App startup | Once at launch |
GetAttributionData | After init completes | When you need campaign/deeplink info |
Signup | After onboarding | Once per user |
SetUserData | Auth/session logic | Every app open with logged-in user |
TrackEvent | Throughout the app | On user actions |
CapturePayment | Payment flow | When payment succeeds |
RemovePayment | Refund flow | When payment is reversed |
SetPushToken | After token refresh | When push token changes |
HandleDeeplink | Deeplink entry points | When app is opened via a deeplink |
Automating iOS Dependency with a Post-Build Script
Since Unity regenerates the Xcode project on each build, you can automate the SPM dependency addition using a Unity Editor script: CreateAssets/Editor/LinkrunnerPostBuild.cs:
Unity’s
PBXProject API does not natively support adding SPM packages. After the Xcode project is generated, you will need to add the LinkrunnerKit SPM dependency manually in Xcode, or use a third-party tool like unity-spm to automate it.Testing
- Enable debug mode:
LinkrunnerSDK.Initialize(token, debug: true) - Create a test campaign at Dashboard → Create Campaign
- Uninstall the app from your test device
- Click the campaign link on the device (opens in browser)
- Install and open the app build within 3 minutes
- Verify in the dashboard that click count, install count, and signup count increase
- Call
GetAttributionData()to confirm attribution is returned
Troubleshooting
Android
- ProGuard/R8 issues: Add to your ProGuard rules:
- Duplicate classes: If another plugin includes Kotlin stdlib, use Gradle’s
excludeto avoid conflicts.
iOS
- Swift file not compiling: Unity does not automatically compile
.swiftfiles. After generating the Xcode project, addLinkrunnerUnityBridge.swiftto the UnityFramework target’s Compile Sources build phase manually. - “Use of unresolved identifier ‘LinkrunnerSDK’”: The LinkrunnerKit SPM package hasn’t been added to the Xcode project. Add it via File → Add Package Dependencies.
- Bridging header issues: When Xcode prompts to create a bridging header after adding the first Swift file, accept it. Ensure
SWIFT_VERSIONis set to5.0or higher in UnityFramework build settings. - Linker errors: Ensure you selected LinkrunnerStatic (not the dynamic variant) when adding the SPM package.
- ATT dialog not showing: The
NSUserTrackingUsageDescriptionkey must be present in Info.plist. The SDK handles requesting permission automatically during initialization.
General
- Callbacks not received: Verify the
GameObjectis named exactlyLinkrunnerCallbackHandlerand has theLinkrunnerSDK.csscript attached. It must exist in the scene when native code callsUnitySendMessage. - Editor testing: All SDK calls are no-ops in the Unity Editor and log to the console instead. Test on actual Android/iOS devices.