Skip to main content

Installation

Step 1: Install the Package

# Using npm
npm install rn-linkrunner

# Using yarn
yarn add rn-linkrunner

Step 2: iOS Configuration

If you’re developing for iOS, follow these additional steps:
  1. Install pods for the package:
cd ios && pod install
  1. Add the following code to your info.plist file:
<key>NSUserTrackingUsageDescription</key>
<string>This identifier will be used to deliver personalized ads and improve your app experience.</string>

Step 3: SKAdNetwork Configuration

To enable SKAdNetwork postback copies to be sent to Linkrunner, add the following keys to your Info.plist file:
<key>NSAdvertisingAttributionReportEndpoint</key>
<string>https://linkrunner-skan.com</string>
<key>AttributionCopyEndpoint</key>
<string>https://linkrunner-skan.com</string>
For complete SKAdNetwork integration details, see the SKAdNetwork Integration Guide.

Step 4: Android Backup Configuration

For Android apps, the SDK provides backup rules to exclude Shared Preferences data from backup. This prevents the retention of the Linkrunner install ID during reinstallation, ensuring accurate detection of new installs and re-installs. For detailed backup configuration instructions, please refer to the Android SDK Backup Configuration.

Expo Support

If you are using Expo, follow the above steps to install the required packages. After this, you will need to use development builds since the Linkrunner SDK relies on native libraries. Follow the Expo Development Builds Documentation to get started.

Initialization

To initialize the Linkrunner SDK, add this code to your App.tsx component: You can find your project token here.

SDK Signing Parameters (Optional)

For enhanced security, the LinkRunner SDK requires the following signing parameters during initialization:
  • secretKey: A unique secret key used for request signing and authentication
  • keyId: A unique identifier for the key pair used in the signing process
You can find your project token, secret key, and key ID here. Note: The initialization method doesn’t return any value. To get attribution data and deeplink information, use the getAttributionData method.
import linkrunner from "rn-linkrunner";

// Inside your React component
useEffect(() => {
    init();
}, []); // Empty dependency array ensures it runs only once

const init = async () => {
    await linkrunner.init(
        "YOUR_PROJECT_TOKEN",
        "YOUR_SECRET_KEY", // Optional: Required for SDK signing
        "YOUR_KEY_ID", // Optional: Required for SDK signing
        false, // Optional: Set to true to disable IDFA collection for iOS devices (defaults to false)
        true // Optional: Enable debug mode for development (defaults to false)
    );
    console.log("Linkrunner initialized");
};

User Registration

Call the signup method once after the user has completed your app’s onboarding process: It is strongly recommended to use the integrated platform’s identify function to set a persistent user_id once it becomes available (typically after signup or login). If the platform’s identifier function is not called, you must provide a user identifier for Mixpanel, PostHog, and Amplitude integration.
  • mixpanel_distinct_id for Mixpanel
  • posthog_distinct_id for PostHog
  • amplitude_device_id for Amplitude
const onSignup = async () => {
    try {
        await linkrunner.signup({
            user_data: {
                id: "123", // Required: User ID
                name: "John Doe", // Optional
                phone: "9876543210", // Optional
                email: "user@example.com", // Optional
                // These properties are used to track reinstalls
                user_created_at: "2024-01-01T00:00:00Z", // Optional
                is_first_time_user: true, // Optional
                mixpanel_distinct_id: "mixpanel_distinct_id", // Optional - Mixpanel Distinct ID
                amplitude_device_id: "amplitude_device_id", // Optional - Amplitude User ID
                posthog_distinct_id: "posthog_distinct_id", // Optional - PostHog Distinct ID
            },
            data: {}, // Optional: Any additional data
        });
        console.log("Signup successful");
    } catch (error) {
        console.error("Error during signup:", error);
    }
};

Getting Attribution Data

To get attribution data and deeplink information for the current installation, use the getAttributionData function:
const getAttributionInfo = async () => {
    try {
        const attributionData = await linkrunner.getAttributionData();
        console.log("Attribution data:", attributionData);
    } catch (error) {
        console.error("Error getting attribution data:", error);
    }
};
The getAttributionData function returns:
{
    deeplink: string | null;
    campaign_data: {
        id: string;
        name: string;
        type: string; // "ORGANIC" | "INORGANIC"
        ad_network: string | null; // "META" | "GOOGLE" | null
        installed_at: string;
        store_click_at: string | null;
        group_name: string;
        asset_name: string;
        asset_group_name: string;
    }
    attribution_source: string;
}

Setting User Data

Call setUserData each time the app opens and the user is logged in:
const setUserData = async () => {
    await linkrunner.setUserData({
        id: "123", // Required: User ID
        name: "John Doe", // Optional
        phone: "9876543210", // Optional
        email: "user@example.com", // Optional
        mixpanel_distinct_id: "mixpanel_distinct_id", // Optional - Mixpanel Distinct ID
        amplitude_device_id: "amplitude_device_id", // Optional - Amplitude User ID
        posthog_distinct_id: "posthog_distinct_id", // Optional - PostHog Distinct ID
    });
};

Setting CleverTap ID

Use the setAdditionalData method to set CleverTap ID:
const setIntegrationData = async () => {
    await linkrunner.setAdditionalData({
        clevertapId: "YOUR_CLEVERTAP_USER_ID", // CleverTap user identifier
    });
};

Parameters for linkrunner.setAdditionalData

  • clevertapId: string (optional) - CleverTap user identifier
This method allows you to connect user identities across different analytics and marketing platforms.

Revenue Tracking

Revenue data is only stored and displayed for attributed users. Make sure you have implemented the .signup function before capturing payments. To attribute a test user, follow the Integration Testing guide. You can verify your events are being captured on the Events Settings page.

Capture Payment

Use this method to capture payment information:
const capturePayment = async () => {
  await linkrunner.capturePayment({
    amount: 100, // Payment amount
    userId: "user123", // User identifier
    paymentId: "payment456", // Optional: Unique payment identifier
    type: "FIRST_PAYMENT", // Optional: Payment type
    // type: "SECOND_PAYMENT", // Optional: Payment type
    status: "PAYMENT_COMPLETED", // Optional: Payment status
    eventData: {
      // Optional: Ecommerce/custom event data
      content_ids: ["product_123"],
      content_type: "product",
      currency: "USD",
      value: 99.99,
      num_items: 1,
      order_id: "order_12345",
      contents: [
        {
          id: "product_123",
          quantity: 1,
          item_price: 99.99,
        },
      ],
    },
  });
};

Parameters for linkrunner.capturePayment

  • amount: number (required) - The payment amount
  • userId: string (required) - Identifier for the user making the payment
  • paymentId: string (optional) - Unique identifier for the payment
  • type: string (optional) - Type of payment. Available options:
    • FIRST_PAYMENT - First payment made by the user
    • SECOND_PAYMENT - Second payment made by the user
    • WALLET_TOPUP - Adding funds to a wallet
    • FUNDS_WITHDRAWAL - Withdrawing funds
    • SUBSCRIPTION_CREATED - New subscription created
    • SUBSCRIPTION_RENEWED - Subscription renewal
    • ONE_TIME - One-time payment
    • RECURRING - Recurring payment
    • DEFAULT - Default type (used if not specified)
  • status: string (optional) - Status of the payment. Available options:
    • PAYMENT_INITIATED - Payment has been initiated
    • PAYMENT_COMPLETED - Payment completed successfully (default if not specified)
    • PAYMENT_FAILED - Payment attempt failed
    • PAYMENT_CANCELLED - Payment was cancelled
  • eventData: object (optional) - Key-value pairs for additional event data, including Meta ecommerce properties.

Removing Payments

Remove payment records (for refunds or cancellations):
const removePayment = async () => {
    await linkrunner.removePayment({
        userId: "user123", // User identifier
        paymentId: "payment456", // Optional: Unique payment identifier
    });
};

Parameters for Linkrunner.removePayment

  • userId: String (required) - Identifier for the user whose payment is being removed
  • paymentId: String (optional) - Unique identifier for the payment to be removed
Note: Either paymentId or userId must be provided when calling removePayment. If only userId is provided, all payments for that user will be removed.

Ecommerce Events

Minimum SDK Version: Ecommerce Event Manager requires react-native-linkrunner v2.7.0 or above. Please ensure your SDK is updated before using this feature.
If you are tracking Ecommerce events to sync with Meta Catalog Sales, you must format your eventData to include Meta’s required fields. You also need to map your custom event to the standard commerce event in the Linkrunner Dashboard. For detailed explanations of the required fields like content_ids, contents, and value, refer to our Meta Commerce Manager documentation.

Add To Cart Example

Use the trackEvent method to send an AddToCart event:
const trackAddToCart = async () => {
  try {
    await linkrunner.trackEvent(
      "add_to_cart", // Map this custom event to "AddToCart" in the Linkrunner Dashboard
      {
        content_ids: ["product_123"],
        contents: [
          {
            id: "product_123", // Matches content_ids
            quantity: 1,
            item_price: 49.99,
          },
        ],
        content_type: "product",
        currency: "USD",
        value: 49.99,
        num_items: 1,
      },
    );
    console.log("Add To Cart event tracked successfully");
  } catch (error) {
    console.error("Error tracking Add To Cart event:", error);
  }
};

View Content Example

Use the trackEvent method to send a ViewContent event:
const trackViewContent = async () => {
  try {
    await linkrunner.trackEvent(
      "view_item", // Map this custom event to "ViewContent" in the Linkrunner Dashboard
      {
        content_ids: ["product_123"],
        contents: [
          {
            id: "product_123", // Matches content_ids
            quantity: 1,
            item_price: 49.99,
          },
        ],
        content_type: "product",
        currency: "USD",
        value: 49.99,
        num_items: 1,
      },
    );
    console.log("View Content event tracked successfully");
  } catch (error) {
    console.error("Error tracking View Content event:", error);
  }
};

Payment / Purchase Example

Use the capturePayment method to send a Purchase event containing the ecommerce payload:
const capturePurchase = async () => {
  try {
    await linkrunner.capturePayment({
      amount: 49.99,
      userId: "user123",
      paymentId: "payment_456",
      type: "FIRST_PAYMENT", // Map this payment type to "Purchase" in the Linkrunner Dashboard
      status: "PAYMENT_COMPLETED",
      eventData: {
        content_ids: ["product_123"],
        contents: [
          {
            id: "product_123", // Matches content_ids
            quantity: 1,
            item_price: 49.99,
          },
        ],
        content_type: "product",
        currency: "USD",
        value: 49.99,
        num_items: 1,
        order_id: "order_abc123", // Required for Purchase events
      },
    });
    console.log("Purchase captured successfully");
  } catch (error) {
    console.error("Error capturing purchase:", error);
  }
};
Note: For more information on testing and verifying your ecommerce events, please see our Testing Ecommerce Events guide.

Tracking Custom Events

Events are only stored and displayed for attributed users. Make sure you have implemented the .signup function before tracking events. To attribute a test user, follow the Integration Testing guide. You can verify your events are being captured on the Events Settings page. For capturing revenue, it is recommended to use the .capturePayment method instead of .trackEvent.
Track custom events in your app:
const trackEvent = async () => {
    await linkrunner.trackEvent(
        "purchase_initiated", // Event name
        { product_id: "12345", category: "electronics", amount: 99.99 } // Optional: Event data, include amount as a number for revenue sharing with ad networks like Google and Meta
    );
};

Revenue Sharing with Ad Networks

To enable revenue sharing with ad networks like Google Ads and Meta, include an amount parameter as a number in your custom event data. This allows the ad networks to optimize campaigns based on the revenue value of conversions:
const trackPurchaseEvent = async () => {
    await linkrunner.trackEvent("purchase_completed", {
        product_id: "12345",
        category: "electronics",
        amount: 149.99, // Revenue amount as a number
    });
};
For revenue sharing with ad networks to work properly, ensure the amount parameter is passed as a number, not as a string.

Enhanced Privacy Controls

The SDK offers options to enhance user privacy:
// Enable PII (Personally Identifiable Information) hashing
linkrunner.enablePIIHashing(true);
When PII hashing is enabled, sensitive user data like name, email, and phone number are hashed using SHA-256 before being sent to Linkrunner servers.

Function Placement Guide

FunctionWhere to PlaceWhen to Call
linkrunner.initApp.tsx within useEffectOnce when app starts
linkrunner.getAttributionDataAttribution data handling flowWhenever the attribution data is needed
linkrunner.setAdditionalDataIntegration codeWhen third-party integration IDs are available
linkrunner.signupOnboarding flowOnce after user completes onboarding
linkrunner.setUserDataAuthentication logicEvery time app opens with logged-in user
linkrunner.trackEventThroughout appWhen specific user actions occur
linkrunner.capturePaymentPayment processingWhen user makes a payment
linkrunner.removePaymentRefund flowWhen payment needs to be removed

Next Steps

Support

If you encounter issues during integration, contact us at darshil@linkrunner.io.