> For the complete documentation index, see [llms.txt](https://docs.growsurf.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.growsurf.com/developer-tools/ios-sdk/attribution-providers.md).

# Attribution Providers

On iOS, GrowSurf relies on your app or attribution provider to return the referral payload after install. Pass that payload into the SDK before calling `addReferredParticipant()`.

Unlike Android (which reads the Play Install Referrer for native deferred attribution via `handleDeferredDeepLink()`), iOS has no native deferred deep link equivalent, so deferred attribution is delegated to your attribution provider (e.g., Branch, AppsFlyer).

### Why iOS deferred is provider-specific

For a referral program, the deferred / cold-install path is the **primary** one — a referral targets people who don't yet have your app. When a friend taps a referral link, installs your app, then opens it for the first time (a **deferred** / cold install), iOS has no reliable native way to carry the referral across the install. iOS 14 (App Tracking Transparency removed the IDFA) and iOS 15 (Private Relay masks the Safari IP) broke the probabilistic device matching attribution providers previously relied on. Each provider now solves this differently, so **deferred setup is not interchangeable between providers** — follow the integration guide for yours.

| Provider                                                                           | iOS deferred mechanism                          | On by default?                  | What you must turn on                                                                                                                                                                        |
| ---------------------------------------------------------------------------------- | ----------------------------------------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [**Branch**](/integrations/branch.md#ios-deferred-deep-linking-new-installs)       | NativeLink (encrypted clipboard token)          | Yes, once NativeLink is enabled | Branch dashboard **Enable NativeLink** + a non-web-only link; call `checkPasteboardOnInstall()` before `initSession()` (iOS 16+: consider `BranchPasteControl`).                             |
| [**Adjust**](/integrations/adjust.md#ios-deferred-deep-linking-new-installs)       | LinkMe (clipboard token)                        | No (optional)                   | `ADJConfig.enableLinkMe()` (v5) / `setLinkMeEnabled(true)` (v4) + link tag `adj_linkme=1` or `linkme=1`; otherwise deferred is server-side/probabilistic.                                    |
| [**Singular**](/integrations/singular.md#ios-deferred-deep-linking-new-installs)   | Clipboard-Based DDL (clipboard token)           | No (optional, enterprise)       | `SingularConfig.clipboardAttribution = true` + Singular WebSDK on the landing page (ask your Singular CSM to enable); otherwise server-side/probabilistic.                                   |
| [**AppsFlyer**](/integrations/appsflyer.md#ios-deferred-deep-linking-new-installs) | Server-side Unified Deep Linking (no clipboard) | Yes                             | Implement the `deepLinkDelegate` / `didResolveDeepLink(_:)` callback; new installs receive `deep_link_value` + `deep_link_sub1`–`deep_link_sub10` within a \~15-min click-to-install window. |

In every case the GrowSurf SDK simply reads `grsf` out of whatever deep link your provider hands back. So GrowSurf deferred attribution survives a cold install only when (1) your provider's deferred path is enabled (above) **and** (2) the link your participants share carries `grsf`. The integration guides cover keeping `grsf` on the link; this table covers turning on the provider's deferred path.

{% hint style="info" %}
Any **clipboard-based** path (Branch NativeLink, Adjust LinkMe, Singular Clipboard-Based DDL) triggers Apple's one-time "Pasted from …" prompt on first launch on iOS 16+. AppsFlyer's server-side UDL does not use the clipboard and shows no prompt. Provider SDK APIs are version-specific — confirm exact method names against your installed provider SDK.

iOS deferred is **best-effort even when configured** — the user can decline the paste prompt, overwrite the clipboard before first launch, or tap from an in-app/non-Safari browser (AppsFlyer also has a \~15-minute click-to-install window) — so always pair it with a fallback such as manual referral-code entry. Android's Play Install Referrer is deterministic and not subject to these.
{% endhint %}

***

## Direct deep links

Use `handleDeepLink(_:)` when the installed app opens from a link that already contains `grsf`, which contains the referral code.

```swift
if let url {
    let attribution = try await growsurf.handleDeepLink(url)
}
```

{% hint style="info" %}
**Example accepted links:**

* `your-app://open?grsf=referrer_id`
* `https://example.com/app?grsf=referrer_id`
  {% endhint %}

{% hint style="info" %}
**Already support deep links?** If you use an attribution provider (Branch, AppsFlyer, Adjust, Singular) or otherwise open your app from links, this is already set up — just forward the opened URL to `handleDeepLink(url)`.

**Starting from scratch?** Register a custom URL scheme (`CFBundleURLSchemes` in `Info.plist`) — the quickest path, no domain needed — and/or configure Universal Links (Associated Domains entitlement) for nicer `https` links, which require a domain you control. Then call `handleDeepLink(url)` from your app's URL-open handler (SwiftUI `.onOpenURL` or `application(_:open:options:)`).
{% endhint %}

***

## Adapters

GrowSurf provides adapters for popular attribution providers. Choose your provider below, or use **Other** to pass a dictionary of attribution values from any other provider.

{% tabs %}
{% tab title="Adjust" %}

## Adjust adapter

Add the Adjust adapter:

{% tabs %}
{% tab title="CocoaPods" %}

```ruby
pod 'GrowSurfSDK/AdjustAttribution',
    :podspec => 'https://raw.githubusercontent.com/growsurf/growsurf-ios-sdk-distribution/v0.3.0/GrowSurfSDK.podspec'
```

{% endtab %}

{% tab title="Swift Package Manager" %}
Add the `GrowSurfAdjustAttribution` product alongside `GrowSurfSDK` from the public binary package repository:

```
https://github.com/growsurf/growsurf-ios-sdk-distribution.git
```

For a `Package.swift` target:

```swift
dependencies: [
    .package(url: "https://github.com/growsurf/growsurf-ios-sdk-distribution.git", from: "0.3.0"),
],
targets: [
    .target(
        name: "YourApp",
        dependencies: [
            .product(name: "GrowSurfSDK", package: "growsurf-ios-sdk-distribution"),
            .product(name: "GrowSurfAdjustAttribution", package: "growsurf-ios-sdk-distribution"),
        ]
    ),
]
```

{% endtab %}

{% tab title="Manual" %}
Download `GrowSurfAdjustAttribution.xcframework.zip` from the public release:

```
https://github.com/growsurf/growsurf-ios-sdk-distribution/releases/tag/v0.3.0
```

Unzip it, drag `GrowSurfAdjustAttribution.xcframework` into your Xcode project alongside `GrowSurfSDK.xcframework`, and set it to **Embed & Sign** in your app target.
{% endtab %}
{% endtabs %}

Then pass the Adjust deferred deep link into GrowSurf:

```swift
import GrowSurfAdjustAttribution

try await GrowSurfAdjustAttribution.handle(adjustDeferredDeepLinkURL, sdk: growsurf)
```

The adapter accepts `URL` and `String` deep link values.

{% hint style="warning" %}
For **deferred** (no-app-installed) referrals on iOS, Adjust's clipboard path (**LinkMe**) is optional and off by default — enable it with `ADJConfig.enableLinkMe()` (v5) / `setLinkMeEnabled(true)` (v4) and tag your link `adj_linkme=1`/`linkme=1`; without it, deferred falls back to Adjust's server-side matching. See [Adjust - iOS Deferred Deep Linking](/integrations/adjust.md#ios-deferred-deep-linking-new-installs) for detailed instructions.
{% endhint %}
{% endtab %}

{% tab title="AppsFlyer" %}

## AppsFlyer adapter

Add the AppsFlyer adapter:

{% tabs %}
{% tab title="CocoaPods" %}

```ruby
pod 'GrowSurfSDK/AppsFlyerAttribution',
    :podspec => 'https://raw.githubusercontent.com/growsurf/growsurf-ios-sdk-distribution/v0.3.0/GrowSurfSDK.podspec'
```

{% endtab %}

{% tab title="Swift Package Manager" %}
Add the `GrowSurfAppsFlyerAttribution` product alongside `GrowSurfSDK` from the public binary package repository:

```
https://github.com/growsurf/growsurf-ios-sdk-distribution.git
```

For a `Package.swift` target:

```swift
dependencies: [
    .package(url: "https://github.com/growsurf/growsurf-ios-sdk-distribution.git", from: "0.3.0"),
],
targets: [
    .target(
        name: "YourApp",
        dependencies: [
            .product(name: "GrowSurfSDK", package: "growsurf-ios-sdk-distribution"),
            .product(name: "GrowSurfAppsFlyerAttribution", package: "growsurf-ios-sdk-distribution"),
        ]
    ),
]
```

{% endtab %}

{% tab title="Manual" %}
Download `GrowSurfAppsFlyerAttribution.xcframework.zip` from the public release:

```
https://github.com/growsurf/growsurf-ios-sdk-distribution/releases/tag/v0.3.0
```

Unzip it, drag `GrowSurfAppsFlyerAttribution.xcframework` into your Xcode project alongside `GrowSurfSDK.xcframework`, and set it to **Embed & Sign** in your app target.
{% endtab %}
{% endtabs %}

Then pass AppsFlyer conversion data into GrowSurf:

```swift
import GrowSurfAppsFlyerAttribution

try await GrowSurfAppsFlyerAttribution.handle(appsFlyerParams, sdk: growsurf)
```

The adapter accepts `[String: String]`, `[String: Any]`, and `[AnyHashable: Any]` payloads.

{% hint style="warning" %}
For **deferred** (no-app-installed) referrals on iOS, AppsFlyer has **no clipboard path** — the referral arrives via server-side **Unified Deep Linking** (`deepLinkDelegate` / `didResolveDeepLink(_:)`) within a \~15-minute lookback, carrying `deep_link_value` and `deep_link_sub1`–`deep_link_sub10`. See [AppsFlyer - iOS Deferred Deep Linking](/integrations/appsflyer.md#ios-deferred-deep-linking-new-installs) for detailed instructions.
{% endhint %}
{% endtab %}

{% tab title="Branch" %}

## Branch adapter

Add the Branch adapter:

{% tabs %}
{% tab title="CocoaPods" %}

```ruby
pod 'GrowSurfSDK/BranchAttribution',
    :podspec => 'https://raw.githubusercontent.com/growsurf/growsurf-ios-sdk-distribution/v0.3.0/GrowSurfSDK.podspec'
```

{% endtab %}

{% tab title="Swift Package Manager" %}
Add the `GrowSurfBranchAttribution` product alongside `GrowSurfSDK` from the public binary package repository:

```
https://github.com/growsurf/growsurf-ios-sdk-distribution.git
```

For a `Package.swift` target:

```swift
dependencies: [
    .package(url: "https://github.com/growsurf/growsurf-ios-sdk-distribution.git", from: "0.3.0"),
],
targets: [
    .target(
        name: "YourApp",
        dependencies: [
            .product(name: "GrowSurfSDK", package: "growsurf-ios-sdk-distribution"),
            .product(name: "GrowSurfBranchAttribution", package: "growsurf-ios-sdk-distribution"),
        ]
    ),
]
```

{% endtab %}

{% tab title="Manual" %}
Download `GrowSurfBranchAttribution.xcframework.zip` from the public release:

```
https://github.com/growsurf/growsurf-ios-sdk-distribution/releases/tag/v0.3.0
```

Unzip it, drag `GrowSurfBranchAttribution.xcframework` into your Xcode project alongside `GrowSurfSDK.xcframework`, and set it to **Embed & Sign** in your app target.
{% endtab %}
{% endtabs %}

Then pass Branch callback data into GrowSurf:

```swift
import GrowSurfBranchAttribution

try await GrowSurfBranchAttribution.handle(branchParams, sdk: growsurf)
```

The adapter accepts `[String: String]`, `[String: Any]`, and `[AnyHashable: Any]` payloads.

{% hint style="warning" %}
For **deferred** (no-app-installed) referrals on iOS, Branch requires **NativeLink**: enable it in the Branch dashboard (Configuration → Enable NativeLink) with a non-web-only link, and call `Branch.getInstance().checkPasteboardOnInstall()` **before** `initSession()` so the SDK reads the NativeLink clipboard token on first launch (iOS 14+ removed the fingerprint matching used previously; on iOS 16+ Branch also offers `BranchPasteControl` as a user-tappable alternative to the silent read). See [Branch - iOS Deferred Deep Linking](/integrations/branch.md#ios-deferred-deep-linking-new-installs) for detailed instructions.
{% endhint %}
{% endtab %}

{% tab title="Singular" %}

## Singular adapter

Add the Singular adapter:

{% tabs %}
{% tab title="CocoaPods" %}

```ruby
pod 'GrowSurfSDK/SingularAttribution',
    :podspec => 'https://raw.githubusercontent.com/growsurf/growsurf-ios-sdk-distribution/v0.3.0/GrowSurfSDK.podspec'
```

{% endtab %}

{% tab title="Swift Package Manager" %}
Add the `GrowSurfSingularAttribution` product alongside `GrowSurfSDK` from the public binary package repository:

```
https://github.com/growsurf/growsurf-ios-sdk-distribution.git
```

For a `Package.swift` target:

```swift
dependencies: [
    .package(url: "https://github.com/growsurf/growsurf-ios-sdk-distribution.git", from: "0.3.0"),
],
targets: [
    .target(
        name: "YourApp",
        dependencies: [
            .product(name: "GrowSurfSDK", package: "growsurf-ios-sdk-distribution"),
            .product(name: "GrowSurfSingularAttribution", package: "growsurf-ios-sdk-distribution"),
        ]
    ),
]
```

{% endtab %}

{% tab title="Manual" %}
Download `GrowSurfSingularAttribution.xcframework.zip` from the public release:

```
https://github.com/growsurf/growsurf-ios-sdk-distribution/releases/tag/v0.3.0
```

Unzip it, drag `GrowSurfSingularAttribution.xcframework` into your Xcode project alongside `GrowSurfSDK.xcframework`, and set it to **Embed & Sign** in your app target.
{% endtab %}
{% endtabs %}

Then pass Singular callback data into GrowSurf:

```swift
import GrowSurfSingularAttribution

try await GrowSurfSingularAttribution.handle(singularParams, sdk: growsurf)
```

The adapter accepts `[String: String]`, `[String: Any]`, `[AnyHashable: Any]`, `URL`, and `String` payloads. It parses GrowSurf referral keys from Singular deep link, deferred deep link, and passthrough fields such as `_dl`, `_ddl`, and `_p`.

{% hint style="warning" %}
For **deferred** (no-app-installed) referrals on iOS, Singular **Clipboard-Based DDL** is an optional, enterprise feature requiring `SingularConfig.clipboardAttribution = true` and the Singular WebSDK on your landing page (enabled via your Singular CSM); otherwise deferred is server-side/probabilistic. See [Singular - iOS Deferred Deep Linking](/integrations/singular.md#ios-deferred-deep-linking-new-installs) for detailed instructions.
{% endhint %}
{% endtab %}

{% tab title="Other" %}

## Manual attribution parameters

Use `handleAttributionParameters(_:provider:)` for any other provider that can return a dictionary of attribution values. No extra adapter install is required.

```swift
try await growsurf.handleAttributionParameters(
    [
        "grsf": "referrer_id",
        "click_id": "click_123",
    ],
    provider: "your-provider-name"
)
```

{% endtab %}
{% endtabs %}

***

## Accepted attribution keys

| Key          | Description                                                                                      |
| ------------ | ------------------------------------------------------------------------------------------------ |
| `grsf`       | Preferred GrowSurf referrer ID.                                                                  |
| `ref`        | Alternate referrer ID.                                                                           |
| `referredBy` | Alternate referrer ID.                                                                           |
| `provider`   | Attribution provider name. Ignored when the SDK method receives an explicit `provider` argument. |
| `clickId`    | Provider click ID metadata.                                                                      |
| `click_id`   | Provider click ID metadata.                                                                      |
| `unique`     | Optional boolean string: `true` or `false`.                                                      |

The SDK also parses values nested inside URL-like payload fields. For example, a provider value of `https://example.com/?grsf=referrer_id&click_id=click_123` can still produce GrowSurf attribution. If a provider returns a GrowSurf-hosted share URL such as `https://grow.surf/share/:campaignId/:referrerId`, the SDK uses the participant value from the path.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.growsurf.com/developer-tools/ios-sdk/attribution-providers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
