Attribr SDK Docs

Attribr is a 3-line install attribution SDK for iOS and Android. It tracks where your installs come from, measures day-1/7/30 retention, and supports referral attribution - all with zero permissions and zero App Store rejection risk.

Zero permissionsWorks in TestFlight< 50 KBNo IDFANo ATT promptiOS + Android

Native Swift (iOS) and Kotlin (Android) integration is available today, and a public, installable React Native / Expo package (@mrvltechnologies/attribr-react-native) shipped as of v0.2.3 - see the React Native section below.

Attribr is used across every app in MRVL Technologies' own portfolio, and those apps have passed Apple App Review with the SDK included. The Swift SDK's v1.4.0 was its first public GitHub release (now at v1.4.1), so public/third-party adoption of the Swift and React Native packages is still early - validated internally across MRVL's own apps, not yet claimed at external scale.

iOS Integration (Swift)

Add the Swift package, paste 3 lines, ship. No AppDelegate hooks, no URL schemes, no AASA file.

The Swift SDK is the strongest native iOS surface Attribr offers today - it includes StoreKit 2 transaction reporting with AppAccountTokensupport, SKAdNetwork, and push-token uninstall detection, none of which the React Native package has. It's public, documented (see SECURITY.mdand the Client-key guidance in the repo), and every app in the MRVL portfolio builds against this exact source today via a local Swift Package path - the same code that's tagged and pushed publicly. Moving individual apps to a pinned public git tag instead of that local path is a future build-reproducibility decision, not something blocking you from using the public package now.

1

Add the Swift package

In Xcode: File → Add Package Dependencies, paste the URL below, and select Up to Next Major Version starting at 1.4.1.

text
https://github.com/mrvltechnologies/attribr-ios

Or in Package.swift:

swift
dependencies: [
    .package(url: "https://github.com/mrvltechnologies/attribr-ios", from: "1.4.1")
]

Requires iOS 15+ and a Swift 6.0 toolchain (Xcode 16+).

Concurrency: the entire public API is @MainActor-isolated. Calling it from SwiftUI view bodies/lifecycle methods or any other main-actor context needs no extra annotation. If you wrap Attribr calls in your own type, mark that type @MainActor too - otherwise Swift 6 rejects the call at compile time:

swift
@MainActor
enum MyAttribrWrapper {
    static func start(apiKey: String) {
        Attribr.initialize(apiKey: apiKey)
        Attribr.setConsent(.granted)
        Attribr.trackLaunch()
    }
}

For local/internal development against a source checkout (not recommended for production - it won't track releases), you can use a local path with XcodeGen instead:

yaml
packages:
  Attribr:
    path: /path/to/Attribr-by-MRVL/sdk/swift

targets:
  YourApp:
    dependencies:
      - package: Attribr
        product: Attribr
2

Initialise in App.swift

swift
import SwiftUI
import Attribr

@main
struct YourApp: App {
    init() {
        Attribr.initialize(apiKey: "attr_live_yourkey…")
        Attribr.setConsent(.granted)
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
                .onChange(of: scenePhase) { _, phase in
                    if phase == .active {
                        Attribr.trackLaunch()
                    }
                }
        }
    }

    @Environment(\.scenePhase) private var scenePhase
}
3

That's it

Build and run. Installs and retention pings start flowing immediately. Check your dashboard within a few seconds of the first launch.

No NSUserTrackingUsageDescription required
No PrivacyInfo.xcprivacy manual edits - SDK ships its own
Works in TestFlight sandbox builds
Works on simulators

Android Integration (Kotlin)

The Kotlin SDK mirrors the Swift API exactly. Same 3-line pattern, same zero-dependency philosophy.

1

Include the local SDK build

In settings.gradle.kts:

kotlin
includeBuild("/path/to/Attribr-by-MRVL/sdk/kotlin")
2

Add the dependency

In app/build.gradle.kts:

kotlin
dependencies {
    implementation("com.mrvltechnologies:attribr:1.0.0")
}
3

Initialise in Application.onCreate()

kotlin
import com.mrvltechnologies.attribr.Attribr
import com.mrvltechnologies.attribr.ConsentState

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        Attribr.initialize(this, apiKey = "attr_live_yourkey…")
        Attribr.setConsent(ConsentState.GRANTED)
    }
}
4

Track launches

In your base Activity or using ProcessLifecycleOwner:

kotlin
// Option A — Base Activity
override fun onResume() {
    super.onResume()
    Attribr.trackLaunch()
}

// Option B — ProcessLifecycleOwner (recommended for multi-activity apps)
ProcessLifecycleOwner.get().lifecycle.addObserver(
    LifecycleEventObserver { _, event ->
        if (event == Lifecycle.Event.ON_START) Attribr.trackLaunch()
    }
)

React Native / Expo

A JS-only client for React Native / Expo apps - no native module, no CocoaPods or Gradle dependency. Public on npm and GitHub, MIT licensed.

Public on npmPublic on GitHubMIT licensedCurrent: v0.2.3
1

Install

text
npm install @mrvltechnologies/attribr-react-native

Optional peer dependencies for the default device-hash strategy:

text
npx expo install expo-application expo-crypto
2

Initialise, then track

ts
import * as Attribr from '@mrvltechnologies/attribr-react-native';

Attribr.initialize({
  apiKey: 'attr_live_yourkey…',   // Client key (sdk_ingest scope) - see "API Key Format" below
  appId: 'com.yourcompany.yourapp',
});
Attribr.setConsent('granted');

await Attribr.trackLaunch();

Also supports trackEvent, trackRevenue, and attributeInstall - the same request shapes as the native SDKs, over a plain REST client. Full API reference and source: github.com/mrvltechnologies/attribr-react-native.

Validated by migrating and running in production across multiple MRVL React Native/Expo apps - this is internal-portfolio validation, not a claim of external developer adoption.

API Key Format

text
attr_live_<appcode><32-char-hex>

Example: attr_live_hawk00xd1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6
Auth headerX-Attribr-Key: attr_live_… (NOT Authorization: Bearer)
Key lengthExactly 50 characters
Prefix storedOnly the first 18 characters are stored in the dashboard
Full keyShown once at creation - copy it immediately

Generate keys in your dashboard at Settings → API Keys. Create one key per app so you can revoke individual apps without affecting others. If a key is ever compromised, revoke it immediately — every endpoint rejects a revoked key right away. To replace a key without downtime, use Rotate instead of Revoke: it issues a new key first and only revokes the old one once the replacement exists, so you can update your app/server configuration before the old key stops working.

Client key vs. Full key - pick the right scope

Every key ships in one of two scopes. Any code that runs on a device you don't control - a mobile app binary, a React Native bundle, or a browser page - is publicly extractable, so that code must only ever carry a Client key.

sdk_ingest (Client key) - write-only. Can call track/click/web-visit/push-token/identify-style ingest endpoints. Cannot read installs, revenue, cohorts, retention, sources, or export data, even if the key is extracted from a decompiled app or page source. Use this for Attribr.initialize(apiKey:) in your iOS/Android app, in any React Native bundle, and in the Web SDK snippet.
full - read + write. Can read your dashboard analytics. Server-side use only: your own backend, CI, or scripts calling the dashboard API. Never embed a full key in an app binary, RN bundle, or web page.

When generating a key in Settings → API Keys, choose Client key unless the key is only ever used server-side.

Web SDK

Attribr's web support covers marketing-site visit and click attribution - it links a landing-page visit (with UTM params) to a later mobile app install or a signed-in web user, via /api/v1/web-visit and /api/v1/click. It is not a general-purpose, GA4-style web analytics product yet - there is no arbitrary pageview/event tracking, funnels, or session analytics for a website on its own.

The attribr-web.jssnippet runs in the visitor's browser, so its key is visible in page source to anyone who views it - this is true of any client-side script, not an Attribr limitation. Only use a Client key (sdk_ingest scope) in a web snippet. A full-scope key in page source would let anyone who views source read your entire Attribr dashboard, not just submit visits.

This is not yet published as a standalone, versioned package - it's the internal visit/click pixel described above, used today for smart-banner attribution. Before we'd package and release it publicly, it needs consent gating (it does not currently check for cookie/tracking consent before firing) and the same identity foundation described in Roadmap below, so that a web visit can be linked to an app install and a known user safely and consistently.

1

Add the script tag

html
<script
  src="https://attribr.dev/attribr-web.js"
  data-api-key="YOUR_ATTRIBR_KEY"   <!-- must be a Client key (sdk_ingest scope) -->
  data-app-id="com.yourcompany.yourapp"
  async
></script>

Events & Revenue

Track custom events, purchases/subscriptions, and push tokens for uninstall detection - all after Attribr.initialize() and consent has been granted.

1

Custom events (Swift)

swift
Attribr.trackEvent(
    name: "level_complete",
    value: 5,
    currency: nil,
    metadata: ["level": "5"]
)
2

Revenue (Swift)

Call after every successful StoreKit/Play Billing transaction. Idempotent by transactionId - duplicate calls for the same transaction are ignored server-side.

swift
Attribr.trackRevenue(
    amount: 9.99,
    currency: "GBP",
    productId: "com.yourapp.pro_monthly",
    transactionId: transaction.originalID.description,  // StoreKit 2
    store: "apple",
    eventType: "initial_purchase"
)
3

Push token (uninstall detection, Swift)

swift
// AppDelegate.application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
Attribr.registerPushToken(deviceToken)
4

GDPR erasure (Swift)

swift
Attribr.deleteAllData { success in
    // handle result
}

The Kotlin SDK mirrors all of the above (trackEvent, trackRevenue, trackSubscriptionEvent, registerPushToken, deleteAllData) with the same parameter names.

Deep Linking

Attribr resolves Universal Links (iOS) and App Links (Android) via handleDeepLink. Available on Growth plans and above.

1

iOS - Universal Links (Swift)

Add the Associated Domains entitlement and pass incoming URLs to handleDeepLink, which returns a result you switch on directly - there is no separate callback-registration step:

swift
// 1. Add Associated Domains entitlement in Xcode:
//    applinks:yourapp.attribr.dev

// 2. Handle deep links in your App.swift:
import Attribr

@main
struct YourApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onOpenURL { url in
                    Task {
                        switch await Attribr.handleDeepLink(url) {
                        case .resolved(let destination, let metadata):
                            NavigationManager.shared.navigate(to: destination, metadata: metadata)
                        case .attributed(let destination):
                            NavigationManager.shared.navigate(to: destination)
                        case .notAttribrLink:
                            break // pass to your own URL handling
                        case .error(let message):
                            print("Attribr deep link error: \(message)")
                        }
                    }
                }
        }
    }
}
2

Android - App Links (Kotlin)

Add intent filters and pass incoming intents to handleDeepLink:

kotlin
// 1. Add intent filter in AndroidManifest.xml:
// <intent-filter android:autoVerify="true">
//     <action android:name="android.intent.action.VIEW" />
//     <category android:name="android.intent.category.DEFAULT" />
//     <category android:name="android.intent.category.BROWSABLE" />
//     <data android:scheme="https" android:host="yourapp.attribr.dev" />
// </intent-filter>

// 2. Handle deep links in your Activity:
import com.mrvltechnologies.attribr.Attribr

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    intent?.data?.let { uri ->
        val result = Attribr.handleDeepLink(uri)
        // handle result the same way as onNewIntent below
    }
}

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    intent.data?.let { uri -> Attribr.handleDeepLink(uri) }
}

Ad Network Integrations

Connect your ad accounts to Attribr and receive server-to-server postbacks when an install is attributed to a paid campaign. Available on Pro plans and above.

1

Supported networks

Facebook / Meta Ads
Google Ads (UAC)
TikTok Ads
Snapchat Ads
Apple Search Ads
2

Connect an ad network

Go to Ad Networks in your dashboard, select a network, and paste your account credentials. Attribr will begin receiving postbacks automatically.

text
Dashboard → Ad Networks → Add Network → Select provider
→ Paste API token / App ID → Save

Attribr sends server-to-server postbacks for:
  • install (attributed to a campaign)
  • retention.day1 / day7 / day30
  • custom events (if configured)
3

Apple Search Ads (iOS only) - planned, not yet available

Client-side Apple Search Ads attribution (via Apple's AdServices framework) is not yet implemented in the Swift SDK - there is no enableAppleSearchAdsAttribution() or equivalent call today. The other networks above (Facebook, Google, TikTok, Snapchat) work via server-to-server postbacks configured entirely in the dashboard, with no SDK code required; Apple Search Ads will follow the same pattern once implemented.

SKAdNetwork (SKAN 4.0)

SKAdNetwork is Apple's privacy-preserving attribution framework. Attribr handles SKAN registration, conversion value updates, and postback decoding automatically. Available on Pro plans and above.

1

Register for SKAN attribution (iOS)

swift
import Attribr
import StoreKit

// In your App.init(), after Attribr.initialize():
Attribr.registerSKAN()

// This calls SKAdNetwork.registerAppForAdNetworkAttribution()
// and sets up conversion value management.
2

Update conversion values

Report user engagement milestones. Attribr maps these to SKAN 4.0 fine + coarse conversion values automatically.

swift
// Report a conversion event (e.g. after a purchase):
Attribr.updateConversionValue(eventName: "purchase", value: 4.99)

// Report engagement milestones (value is optional):
Attribr.updateConversionValue(eventName: "registration")
Attribr.updateConversionValue(eventName: "tutorial_complete")

// SKAN 4.0 coarse values (low / medium / high) are mapped
// automatically based on your conversion value schema,
// which you configure in the dashboard under SKAN settings.
3

Configure in the dashboard

Go to SKAN in your dashboard to configure conversion value mappings, view decoded postbacks, and monitor SKAN attribution alongside your other data sources. No Info.plist changes required - the SDK handles SKAdNetworkItems registration.

TestFlight Attribution

Attribr is the only attribution SDK that works in TestFlight builds. AppsFlyer, Branch, and Adjust all require App Store distribution to attribute installs. Attribr doesn't - it uses device fingerprinting at the API level, which works identically in TestFlight and production.

How to use it: give each beta channel a different code and pass it to attributeInstall after initialisation and consent:

swift
// After Attribr.initialize() + Attribr.setConsent(.granted):
Attribr.attributeInstall(code: "discord-beta-v1", source: .custom)

The Sources tab in your dashboard will break down which beta channel drove the most engaged testers - before you've even launched on the App Store.

Referral Codes

Referral attribution links a new install to the person or channel that drove it. Use it to run influencer campaigns, reward promoters, or measure which communities convert best.

swift
// When the app opens with a referral code in the URL:
Attribr.attributeInstall(code: "influencer-username", source: .custom)

// Attribr stores this against the install.
// You'll see it in the Promoters and Sources tabs.

Creator Attribution

Track installs, D30 retention, and revenue per creator or influencer. Each creator gets a unique deep link  when their audience installs your app through that link, the install is automatically attributed to the creator. No SDK changes needed.

1

Create a creator campaign

Go to Creators in your dashboard and click "Add Creator". Attribr generates a unique link for each creator.

text
Dashboard → Creators → Add Creator → Fill name + platform
→ Link generated: https://attribr.dev/l/cr_a3b7x9

Share this link with the creator. Every install from
this link is attributed to them automatically.
2

iOS - Share the creator's link

Share the generated link with the creator. They can post it on their platform, add it to their bio, or use it in sponsored content.

swift
// Share the creator's unique link
let creatorLink = "https://attribr.dev/l/cr_a3b7x9"

// Option A — UIActivityViewController
let vc = UIActivityViewController(
    activityItems: [URL(string: creatorLink)!],
    applicationActivities: nil
)
present(vc, animated: true)

// Option B — In-app sharing (copy to clipboard)
UIPasteboard.general.string = creatorLink
3

Android - Share the creator's link

kotlin
// Share the creator's unique link
val creatorLink = "https://attribr.dev/l/cr_a3b7x9"

val sendIntent = Intent().apply {
    action = Intent.ACTION_SEND
    putExtra(Intent.EXTRA_TEXT, creatorLink)
    type = "text/plain"
}
startActivity(Intent.createChooser(sendIntent, "Share link"))
4

Via the API (Growth+ plan)

Create and list creators programmatically:

bash
# Create a creator campaign
curl -X POST https://your-dashboard.vercel.app/api/v1/creators \
  -H "X-Attribr-Key: attr_live_yourkey..." \
  -H "Content-Type: application/json" \
  -d '{"app_id": "com.yourapp", "name": "Sarah Tech Reviews", "platform": "youtube", "handle": "sarahtechreviews"}'

# Response includes the generated link:
# { "creator": { "link_url": "https://attribr.dev/l/cr_a3b7x9", ... } }

# List all creators with stats
curl https://your-dashboard.vercel.app/api/v1/creators?app_id=com.yourapp \
  -H "X-Attribr-Key: attr_live_yourkey..."

The Creators dashboard shows clicks, installs, D30 retention, and revenue per creator  all updated in real time.

Security & Trust

Attribr is open where developers need transparency, and private where customer data and attribution logic need protection.

Every client SDK - Swift, Kotlin, React Native, and the web snippet - is designed to carry only a sdk_ingest (Client) key, which can submit events but cannot read your dashboard even if extracted from a shipped app or page source. Full/server keys are never meant to be embedded in an app or website - see API Key Format above.

The public SDK code is not the secret - backend validation, key scoping, and server-side attribution logic are the actual security boundary. Attribr's backend (ingest functions, database, dashboard/admin routes) stays private; only the client SDKs that talk to it are open source.

Verifiable, not just claimed

Public npm package: @mrvltechnologies/attribr-react-native
Public GitHub repositories for iOS, Android, and React Native SDKs
MIT license on every client SDK
Published changelog for every SDK
Security policy with a responsible-disclosure route on every SDK repo
Installable and inspectable today - not a private beta

Roadmap

An honest status, not a marketing timeline - we'd rather under-promise here.

Shipped

React Native / Expo SDK is public and installable (@mrvltechnologies/attribr-react-native). Swift SDK public-readiness hardening is complete - SECURITY.md, Client-key guidance, and a verified match between the public package and what every MRVL app actually builds against.

In progress

Identity foundation - the groundwork a public Web SDK needs before it can safely link a web visit to an app install and a known user.

Planned

A public Web SDK, once consent gating and Identity are ready - neither is live yet. Attribr's Identity layer is being designed to connect anonymous visits, app installs, known users, and revenue events safely and privacy-consciously. This foundation will power future web-to-app and revenue attribution workflows - it does not exist yet, and we won't describe it as live until it does.

Ready to integrate?

Sign up free - no credit card needed. Free up to 10,000 installs/month forever.

Get started free