> ## Documentation Index
> Fetch the complete documentation index at: https://docs.linkrunner.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Google Analytics (GA4)

> Connect Linkrunner with Google Analytics 4 to analyze install and campaign performance

<iframe width="100%" height="420" src="https://www.youtube.com/embed/I8TZAoImPt0" title="Google Analytics (GA4) Integration with Linkrunner" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowFullScreen />

## How does it work?

When a new install occurs, Linkrunner sends the touchpoint details (media source and campaign ID) to GA4.

## Minimum SDK versions

<CardGroup cols={2}>
  <Card title="React Native" icon="react" href="/sdk/react-native">
    rn-linkrunner `2.6.3`
  </Card>

  <Card title="Flutter" icon="flutter" href="/sdk/flutter">
    linkrunner `^3.6.3`
  </Card>

  <Card title="iOS" icon="apple" href="/sdk/ios">
    `3.7.1`
  </Card>

  <Card title="Android" icon="android" href="/sdk/android">
    `3.5.3`
  </Card>
</CardGroup>

## Steps to setup

### 1. Set GA4 Integration in Linkrunner

In the **Integrations** tab, under **Analytics**, click **Configure** under **Google Analytics**. Firebase App ID and a Measurement Protocol API secret will be required. These are different for iOS and Android.

To retrieve the **Firebase App ID** and **Measurement Protocol API secret**:

1. Open **Admin** (settings icon) from the bottom-left of the Google Analytics interface.
   <img src="https://mintcdn.com/linkrunner-01ef8e08/ZtM6Sg9gcHVzxZbZ/images/ga4/ga_integration_1.png?fit=max&auto=format&n=ZtM6Sg9gcHVzxZbZ&q=85&s=073ce0a558af9a7ec65f2e6bcc37a7bf" alt="GA4 Admin" width="2998" height="1694" data-path="images/ga4/ga_integration_1.png" />

2. Under **Property** → **Data collection and modification** → **Data streams**, click your **app data stream** (iOS or Android).
   <img src="https://mintcdn.com/linkrunner-01ef8e08/ZtM6Sg9gcHVzxZbZ/images/ga4/ga_integration_2.png?fit=max&auto=format&n=ZtM6Sg9gcHVzxZbZ&q=85&s=5a22563686ccab6313efeb756bbc4367" alt="GA4 Data streams" width="3008" height="1698" data-path="images/ga4/ga_integration_2.png" />

3. In the **App stream details** panel, copy the **Firebase App ID**.
   <img src="https://mintcdn.com/linkrunner-01ef8e08/ZtM6Sg9gcHVzxZbZ/images/ga4/ga_integration_3.png?fit=max&auto=format&n=ZtM6Sg9gcHVzxZbZ&q=85&s=22187c7acdc97dca9631c6b4074231b9" alt="GA4 App stream details" width="3008" height="1694" data-path="images/ga4/ga_integration_3.png" />

4. Under **Events**, click **Measurement Protocol API secrets**.
   <img src="https://mintcdn.com/linkrunner-01ef8e08/ZtM6Sg9gcHVzxZbZ/images/ga4/ga_integration_4.png?fit=max&auto=format&n=ZtM6Sg9gcHVzxZbZ&q=85&s=9fd73fbbb8335a882b79abebfb81471c" alt="GA4 Measurement Protocol API secrets" width="3010" height="1702" data-path="images/ga4/ga_integration_4.png" />

5. Create (or reuse) an API secret and copy its value.

<Note>
  The Firebase App ID and API secret will be different for your iOS and Android apps, so repeat these steps for each platform.
</Note>

### 2. Retrieve app instance ID in Linkrunner SDK

The app instance ID uniquely identifies a specific installation of a Firebase app. This value needs to be retrieved from the Firebase SDK. After collecting this ID, pass it to `linkrunner.signup` so that Linkrunner can associate GA4 app instance IDs with installs and campaigns.

Use the following examples to pass the app instance ID:

<Tabs>
  <Tab title="Android (Kotlin)">
    ```kotlin theme={null}
    import com.google.firebase.analytics.FirebaseAnalytics
    import io.linkrunner.sdk.LinkRunner
    import io.linkrunner.sdk.models.request.UserDataRequest
    import kotlinx.coroutines.CoroutineScope
    import kotlinx.coroutines.Dispatchers
    import kotlinx.coroutines.launch

    private fun onSignup() {
        CoroutineScope(Dispatchers.IO).launch {
            try {
                val firebaseAnalytics = FirebaseAnalytics.getInstance(context)
                val appInstanceId = firebaseAnalytics.appInstanceId.await() // suspend extension from Kotlin coroutines

                val userData = UserDataRequest(
                    id = "123", // Your user ID
                    // ...other user fields
                    gaAppInstanceId = appInstanceId, // GA4 app instance ID
                )

                LinkRunner.getInstance().signup(
                    userData = userData
                )
            } catch (e: Exception) {
                println("Error during signup with GA4 app instance ID: ${e.message}")
            }
        }
    }
    ```
  </Tab>

  <Tab title="iOS (Swift)">
    ```swift theme={null}
    import FirebaseAnalytics
    import Linkrunner

    func onSignup() async {
        do {
            let appInstanceId = try await Analytics.appInstanceID()

            let userData = UserData(
                id: "123", // Your user ID
                // ...other user fields
                gaAppInstanceId: appInstanceId // GA4 app instance ID
            )

            try await LinkrunnerSDK.shared.signup(
                userData: userData
            )
        } catch {
            print("Error during signup with GA4 app instance ID:", error)
        }
    }
    ```
  </Tab>

  <Tab title="React Native">
    ```javascript theme={null}
    import analytics from "@react-native-firebase/analytics";
    import linkrunner from "rn-linkrunner";

    const onSignup = async () => {
        try {
            const gaAppInstanceId = await analytics().getAppInstanceId();

            await linkrunner.signup({
                user_data: {
                    id: "123", // Your user ID
                    // ...other user fields
                    ga_app_instance_id: gaAppInstanceId, // GA4 app instance ID
                },
                data: {},
            });
        } catch (error) {
            console.error("Error during signup with GA4 app instance ID:", error);
        }
    };
    ```
  </Tab>

  <Tab title="Flutter">
    ```dart theme={null}
    import 'package:firebase_analytics/firebase_analytics.dart';
    import 'package:linkrunner/main.dart';

    Future<void> onSignup() async {
      try {
        final analytics = FirebaseAnalytics.instance;
        final gaAppInstanceId = await analytics.appInstanceId;

        await LinkRunner().signup(
          userData: LRUserData(
            id: '123', // Your user ID
            // ...other user fields
            gaAppInstanceId: gaAppInstanceId, // GA4 app instance ID
          ),
          data: {},
        );
      } catch (e) {
        print('Error during signup with GA4 app instance ID: $e');
      }
    }
    ```
  </Tab>
</Tabs>

### 3. Retrieve GA4 session ID in Linkrunner SDK

The GA4 session ID uniquely identifies a session of a Firebase app. Similar to the app instance ID, this value is retrieved from the Firebase SDK and should be passed to `linkrunner.signup` so that session-level engagement can be connected to installs and campaigns.

Use the following examples to pass the session ID (for example, `ga_session_id` or `gaSessionId`, depending on the SDK's naming convention):

<Tabs>
  <Tab title="Android (Kotlin)">
    ```kotlin theme={null}
    import com.google.firebase.analytics.FirebaseAnalytics
    import io.linkrunner.sdk.LinkRunner
    import io.linkrunner.sdk.models.request.UserDataRequest
    import kotlinx.coroutines.CoroutineScope
    import kotlinx.coroutines.Dispatchers
    import kotlinx.coroutines.launch

    private fun onSignup() {
        CoroutineScope(Dispatchers.IO).launch {
            try {
                val firebaseAnalytics = FirebaseAnalytics.getInstance(context)
                val sessionId = /* Retrieve GA4 session ID from your tracking layer */

                val userData = UserDataRequest(
                    id = "123", // Your user ID
                    // ...other user fields
                    gaSessionId = sessionId, // GA4 session ID
                )

                LinkRunner.getInstance().signup(
                    userData = userData
                )
            } catch (e: Exception) {
                println("Error during signup with GA4 session ID: ${e.message}")
            }
        }
    }
    ```
  </Tab>

  <Tab title="iOS (Swift)">
    ```swift theme={null}
    import Linkrunner

    func onSignup() async {
        do {
            let gaSessionId = /* Retrieve GA4 session ID from your tracking layer */

            let userData = UserData(
                id: "123", // Your user ID
                // ...other user fields
                gaSessionId: gaSessionId // GA4 session ID
            )

            try await LinkrunnerSDK.shared.signup(
                userData: userData
            )
        } catch {
            print("Error during signup with GA4 session ID:", error)
        }
    }
    ```
  </Tab>

  <Tab title="React Native">
    ```javascript theme={null}
    import analytics from "@react-native-firebase/analytics";
    import linkrunner from "rn-linkrunner";

    const onSignup = async () => {
        try {
            const gaSessionId = await analytics().getSessionId();

            await linkrunner.signup({
                user_data: {
                    id: "123", // Your user ID
                    // ...other user fields
                    ga_session_id: gaSessionId, // GA4 session ID
                },
                data: {},
            });
        } catch (error) {
            console.error("Error during signup with GA4 session ID:", error);
        }
    };
    ```
  </Tab>

  <Tab title="Flutter">
    ```dart theme={null}
    import 'package:firebase_analytics/firebase_analytics.dart';
    import 'package:linkrunner/main.dart';

    Future<void> onSignup() async {
      try {
        final analytics = FirebaseAnalytics.instance;
        int? sessionId = await analytics.getSessionId();

        await LinkRunner().signup(
          userData: LRUserData(
            id: '123', // Your user ID
            // ...other user fields
            gaSessionId: sessionId, // GA4 session ID
          ),
          data: {},
        );
      } catch (e) {
        print('Error during signup with GA4 session ID: $e');
      }
    }
    ```
  </Tab>
</Tabs>

### 4. Validate the GA4 Integration

To validate that data is flowing correctly between Linkrunner and GA4:

* Use [BigQuery Export](https://support.google.com/analytics/answer/9823238#zippy=%2Cin-this-article) to explore the raw event data with all associated parameters.
* Using [GA4 Explorations](https://support.google.com/analytics/answer/7579450?hl=en\&ref_topic=12153537,12153943,2986333,\&sjid=20462331341270448-EU\&visit_id=638532662145815538-1056226594\&rd=1#access-analysis\&zippy=%2Cin-this-article).
* The Traffic acquisition report helps you understand where your app visitors are coming from. You can find this under Reports > Lifecycle > Acquisition > Traffic acquisition. For more information on the Traffic acquisition report, see the [Google documentation](https://support.google.com/analytics/answer/12923437?hl=en\&sjid=5454549956257318969-NC#zippy=%2Chow-do-i-filter-out-traffic-sources-from-the-report).

<Info>
  BigQuery data is visible as soon as the event is received by GA4, while it can take 24–48 hours for data to reflect in GA4 reports. [Read more here](https://support.google.com/analytics/answer/11198161?hl=en).
</Info>
