# Sprig Device Mode Integration


Send your events to Sprig in web and mobile [device mode]({{< ref "destinations/rudderstack-connection-modes.md#device-mode" >}}) using the native Sprig SDK.

Find the open source code for this integration below: 

- [Web device mode](https://github.com/rudderlabs/rudder-sdk-js/tree/develop/packages/analytics-js-integrations/src/integrations/Sprig)
- [Sprig-Kotlin](https://github.com/rudderlabs/rudder-sdk-kotlin/tree/main/integrations/sprig)
- [Sprig-Swift](https://github.com/rudderlabs/integration-swift-sprig)
- [Sprig-React-Native](https://github.com/rudderlabs/rudder-sdk-react-native/tree/master/libs/rudder-integration-sprig-react-native)
- [Sprig-Android (Java) — Legacy](https://github.com/rudderlabs/rudder-integration-sprig-android)
- [Sprig-iOS (Obj-C) — Legacy](https://github.com/rudderlabs/rudder-integration-sprig-ios)

## Add mobile device mode integration

Once you add Sprig as a destination in the [RudderStack dashboard](https://app.rudderstack.com/), follow these steps to add it to your mobile project depending on your integration platform:

{{< tabs tabTotal="5" >}}
{{% tab tabName="Android (Kotlin)" %}}

Follow the steps in this section to add Sprig to your Android project using the new Android (Kotlin) SDK:

{{< version-badge registry="maven" package="com.rudderstack.integration.kotlin/sprig" label="Maven Central" fallback="1.0.1" href="https://central.sonatype.com/artifact/com.rudderstack.integration.kotlin/sprig" >}}

#### 1. Add dependencies

In your module (app-level) Gradle file (usually `<project>/<app-module>/build.gradle.kts` or `<project>/<app-module>/build.gradle`), add the following dependencies:

```kotlin
dependencies {
    // RudderStack Kotlin SDK
    implementation("com.rudderstack.sdk.kotlin:android:<latest_version>")

    // RudderStack Sprig integration
    implementation("com.rudderstack.integration.kotlin:sprig:<latest_version>")
}
```

{{< info >}}
This integration pulls in the Sprig (UserLeap) Android SDK in the version range 2.23.0 to 3.0.0.
{{< /info >}}

#### 2. Intialize the SDK and the integration

1. Keep a reference to the `SprigIntegration` instance — it is needed to present the in-app surveys (explained in [Step 3](#3-present-in-app-surveys)):

```kotlin
import android.app.Application
import com.rudderstack.integration.kotlin.sprig.SprigIntegration
import com.rudderstack.sdk.kotlin.android.Analytics
import com.rudderstack.sdk.kotlin.android.Configuration

object RudderAnalyticsUtils {

    lateinit var analytics: Analytics
    val sprigIntegration = SprigIntegration()

    fun initialize(application: Application) {
        analytics = Analytics(
            configuration = Configuration(
                writeKey = "<WRITE_KEY>",
                application = application,
                dataPlaneUrl = "<DATA_PLANE_URL>",
            )
        )
        analytics.add(sprigIntegration)
    }
}
```

2. Call `RudderAnalyticsUtils.initialize(this)` from your `Application.onCreate()`:

```kotlin
class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        RudderAnalyticsUtils.initialize(this)
    }
}
```

#### 3. Present in-app surveys

Sprig presents in-app surveys on a `FragmentActivity` instance. For surveys to render, you need to tell the integration which activity is currently in the foreground, from the activity's lifecycle callbacks:

{{< info >}}
If no activity is set, the integration falls back to `Sprig.track` and the survey is not presented — the event is still delivered to Sprig.
{{< /info >}}

```kotlin
import android.os.Bundle
import androidx.fragment.app.FragmentActivity
import com.rudderstack.sampleapp.analytics.RudderAnalyticsUtils

class MainActivity : FragmentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    override fun onResume() {
        super.onResume()
        RudderAnalyticsUtils.sprigIntegration.setFragmentActivity(this)
    }

    override fun onPause() {
        RudderAnalyticsUtils.sprigIntegration.setFragmentActivity(null)
        super.onPause()
    }
}
```
{{% /tab %}}
{{% tab tabName="iOS (Swift)" %}}

Follow the steps in this section to add Sprig to your iOS project using the iOS (Swift) SDK. Note that the integration supports both Swift and Objective-C consumers.

{{< version-badge registry="github-release" package="rudderlabs/integration-swift-sprig" label="Swift Package Manager" fallback="1.0.0" href="https://github.com/rudderlabs/integration-swift-sprig/" >}}

#### 1. Add the package

Add the Sprig integration using the Swift Package Manager:

1. In Xcode, select **File > Add Package Dependencies...**.
2. Enter the package repository URL:

```text
https://github.com/rudderlabs/integration-swift-sprig
```

3. Select the latest version and target. Then, click **Add Package**.

You can also add the integration to your `Package.swift` file, as shown:

```swift
dependencies: [
    .package(
        url: "https://github.com/rudderlabs/integration-swift-sprig.git",
        .upToNextMajor(from: "<latest_version>")
    )
]
```

#### 2. Initialize the SDK and the integration

1. Create a shared `AnalyticsManager` that owns the `Analytics` instance and the `SprigIntegration`. Keep a reference to `sprigIntegration` — it is needed to present the in-app surveys (explained in Step 3):

```swift
import RudderStackAnalytics
import RudderIntegrationSprig

final class AnalyticsManager {

    static let shared = AnalyticsManager()

    private init() {}

    let analytics: Analytics
    let sprigIntegration: SprigIntegration

    func initialize() {
        let configuration = Configuration(
            writeKey: "<WRITE_KEY>",
            dataPlaneUrl: "<DATA_PLANE_URL>"
        )
        analytics = Analytics(configuration: configuration)

        sprigIntegration = SprigIntegration()
        analytics.add(plugin: sprigIntegration)
    }
}
```

2. Trigger initialization from your `AppDelegate` so the SDK is ready before the first view loads:

```swift
import UIKit

class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        AnalyticsManager.shared.initialize()
        return true
    }
}
```

#### 3. Present in-app surveys

The Sprig SDK requires a `UIViewController` to present in-app surveys. Hand the integration the active view controller via `setViewController(_:)`. The most common pattern is set-on-appear/clear-on-disappear:

```swift
import UIKit
import RudderIntegrationSprig

class MainViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        AnalyticsManager.shared.sprigIntegration.setViewController(self)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        AnalyticsManager.shared.sprigIntegration.setViewController(nil)
    }
}
```

{{< info >}}
The integration holds the view controller weakly, so the explicit `nil` clear is optional. If no view controller is set, the integration calls `Sprig.track` instead of `Sprig.trackAndPresent` and the event is still delivered.
{{< /info >}}

{{% /tab %}}
{{% tab tabName="React Native" %}}

Follow these steps to add the Sprig integration to your React Native project.

{{< warning >}}
Set up the RudderStack [React Native SDK]({{< ref "sources/event-streams/sdks/rudderstack-react-native-sdk.md" >}}) first. 

This integration requires: 

- `@rudderstack/rudder-sdk-react-native` v3.1.0 and above
- React Native v0.74 and above
- For iOS, a deployment target of iOS v15.0 and above
{{< /warning >}}

1. Add the RudderStack-Sprig module to your app:

```bash
npm install @rudderstack/rudder-integration-sprig-react-native
```

OR

```bash
yarn add @rudderstack/rudder-integration-sprig-react-native
```

2. Import the module and add it to your SDK initialization code:

```javascript
import rudderClient from "@rudderstack/rudder-sdk-react-native";
import sprig from "@rudderstack/rudder-integration-sprig-react-native";

const config = {
    dataPlaneUrl: "<DATA_PLANE_URL>",
    trackAppLifecycleEvents: true,
    withFactories: [sprig],
};

rudderClient.setup("<WRITE_KEY>", config);
```

#### Present in-app surveys

The React Native integration tracks the foreground `Activity` (Android) and the key window's root `UIViewController` (iOS) automatically and forwards it to the Sprig SDK, so `Sprig.trackAndPresent` is invoked whenever a foreground host is available. No additional code is needed in your React Native components or in the host native code.

If no foreground host is available at the moment an event is tracked (for example, during cold-start before the first screen renders), the integration falls back to `Sprig.track` and the event is still delivered to Sprig — only the in-app survey UI is skipped for that event.

{{% /tab %}}
{{% tab tabName="Android (Java) — Legacy" %}}

1. Add the following under the dependencies section:

```groovy
implementation 'com.rudderstack.android.sdk:core:[1.0,2.0)'
implementation 'com.rudderstack.android.integration:sprig:[1.0.0,)'
```

2. Change the SDK initialization to the following:

```kotlin
// initialize Rudder SDK
val rudderClient: RudderClient =
    RudderClient.getInstance(
        this,
        WRITE_KEY,
        RudderConfig.Builder()
            .withDataPlaneUrl(DATA_PLANE_URL)
            .withFactory(SprigIntegrationFactory.FACTORY)
            .build()
    )
```

3. Import the dependencies for Sprig:

```kotlin
import com.rudderstack.android.integration.sprig.SprigIntegrationFactory
```

4. Pass the `FragmentActivity` instance as shown:

{{< info >}}
Sprig requires this step to display the survey. You can also set it as `null` to clear the values.
{{< /info >}}

```kotlin
class MainActivity: AppCompatActivity() {

    override fun onStart() {
        super.onStart()
        // pass the FragmentActivity instance, it is required by Sprig to display the survey.
        SprigIntegrationFactory.FACTORY.setFragmentActivity(this@MainActivity)
    }
}
```
{{% /tab %}}
{{% tab tabName="iOS (Obj-C) — Legacy" %}}

1. Add the following line to your `Podfile`:

```ruby
pod 'Rudder-Sprig'
```
2. Run the `pod install` command.
3. Change the SDK initialization to the following:

```swift
let configBuilder = RSConfigBuilder()
    .withDataPlaneUrl(DATA_PLANE_URL)
    .withFactory(RudderSprigFactory.instance)

RSClient.getInstance(WRITE_KEY, config: configBuilder.build())
```

4. Import `Rudder_Sprig` into `ViewController`:

```swift
import Rudder_Sprig
```

5. Pass the instance of `ViewController` to `RudderSprigFactory` as shown:

{{< info >}}
Sprig requires this step to display the survey. You can also set it as `nil` to clear the values.
{{< /info >}}
  
```swift
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    
        // Do any additional setup after loading the view.
        
        // Pass ViewController instance to RudderSprigFactory. As Sprig SDK requires this to display the survey.
        RudderSprigFactory.instance.setViewController(self)
    }
}
```

{{% /tab %}}
{{< /tabs >}}

## Identify

You can use the [`identify`]({{< ref "event-spec/standard-events/identify.md" >}}) call to identify a user in Sprig. 

A sample `identify` call is shown:

```javascript
rudderanalytics.identify('1hKOmRA4GRlm', {
  firstName: 'Alex',
  lastName: 'Keener',
  email: "alex@example.com"
});
```

### Supported mappings

RudderStack maps the following **optional** user attributes in the `identify` events to the corresponding Sprig fields:

| RudderStack property | Sprig property |
| :----| :-----|
| `userId` | `userId` |
| `context.traits` | `attributes` |
| `context.traits.email` | `email` | 

## Track

The [`track`]({{< ref "event-spec/standard-events/track.md" >}}) call lets you record any user actions along with the associated properties.

A sample `track` call is shown:

```javascript
rudderanalytics.track('Sample Survey', {
  plan: "Annual",
  accountType: "Pro"
});
```

If you send a `track` event called `Signed Out`, then RudderStack automatically maps it to the `logoutUser` event before sending it to Sprig. Otherwise, it maps the following event/properties to the corresponding Sprig fields:

| RudderStack property | Sprig property |
| :----| :-----|
| `event` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | `eventName` |
| `userId` | `userId` |
| `properties` | `properties` | 

Sprig expects the event name to be present in the `eventName` key. Hence, if you send a `track` event named `Product Added`, RudderStack maps it to Sprig's `eventName` key before sending it across to Sprig.

{{< info >}}
To display the survey, you must pass the `ViewController` instance for iOS and the `FragmentActivity` instance for Android, otherwise the survey won't be displayed. 

If you do not want to display the survey, you can skip setting `FragmentActivity` or `ViewController`. RudderStack then forwards the call to the `Sprig.track` API instead of `Sprig.trackAndPresent`.
{{< /info >}}

## Reset

The `reset` method resets the previously identified user and related information.

A sample `reset` call is shown:

{{< tabs tabTotal="4" >}}
{{% tab tabName="Android (Kotlin)" %}}
```kotlin
analytics.reset()
```
{{% /tab %}}
{{% tab tabName="iOS (Swift)" %}}
```swift
analytics.reset()
```
{{% /tab %}}
{{% tab tabName="Android (Java) — Legacy" %}}
```java
RudderClient.getInstance()?.reset()
```
{{% /tab %}}
{{% tab tabName="iOS (Obj-C) — Legacy" %}}
```objectivec
RSClient.getInstance().reset()
```
{{% /tab %}}
{{< /tabs >}}

## Logging

Both the Android (Kotlin) and iOS (Swift) SDK integrations forward the Sprig SDK's internal log messages to the RudderStack logger, so they appear alongside the rest of your SDK output.

### Android (Kotlin)

The Sprig Android SDK emits log messages with a severity (`DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`). The integration forwards each message to the RudderStack logger at the mapped severity, so Sprig output honours the log level you configure on the SDK.

Set the log level in `Configuration` when you initialize the SDK:

```kotlin
import com.rudderstack.sdk.kotlin.android.Configuration
import com.rudderstack.sdk.kotlin.core.internals.logger.Logger

val config = Configuration(
    writeKey = "<WRITE_KEY>",
    dataPlaneUrl = "<DATA_PLANE_URL>",
    logLevel = Logger.LogLevel.VERBOSE,
)
```

When the log level is `Logger.LogLevel.NONE`, the integration skips listener registration entirely and no Sprig output is forwarded.

### iOS (Swift)

The Sprig iOS SDK emits log messages **without** a severity (its `loggingEvent` callback only carries a message string), so the integration forwards every Sprig message at the `verbose` level. 

To see Sprig output, set the RudderStack log level to anything other than `.none`:

```swift
LoggerAnalytics.logLevel = .verbose
```

When the log level is set to `.none`, the integration skips listener registration entirely and no Sprig output is forwarded.

<br />

