# @linkhopp/react-native

Official React Native SDK for [LinkHopp](https://linkhopp.com) deep linking.

## Installation

```bash
npm install @linkhopp/react-native @react-native-clipboard/clipboard @react-native-async-storage/async-storage
```

For iOS, install pods:

```bash
cd ios && pod install
```

## Quick Start

### 1. Initialize the SDK

Call `init()` once at app startup, before any other LinkHopp method:

```ts
import { LinkHopp } from '@linkhopp/react-native';

LinkHopp.init({ apiKey: 'YOUR_API_KEY' });
```

To use a custom backend URL:

```ts
LinkHopp.init({
  apiKey: 'YOUR_API_KEY',
  baseUrl: 'https://custom.example.com',
});
```

### 2. Check for Deferred Deep Links

After a fresh install, call `checkDeferredLink()` to detect whether the user
arrived via a LinkHopp link. This runs at most once per installation.

```ts
const link = await LinkHopp.checkDeferredLink();

if (link) {
  console.log('Deferred link found:', link.destinationUrl);
  console.log('Campaign:', link.campaign);
  console.log('Match method:', link.matchMethod);
  // Navigate the user to the intended screen
}
```

### 3. Handle Incoming Links (Warm Start)

Register a listener for links that arrive while the app is already running:

```ts
LinkHopp.handleLink((link) => {
  console.log('Incoming link:', link.destinationUrl);
  // Navigate to the target screen
});
```

### 4. Get the Initial Link (Cold Start)

Check whether the app was opened via a deep link:

```ts
const initialLink = await LinkHopp.getInitialLink();

if (initialLink) {
  console.log('App opened via:', initialLink.destinationUrl);
}
```

### 5. Full Example

```tsx
import React, { useEffect } from 'react';
import { LinkHopp } from '@linkhopp/react-native';

function App() {
  useEffect(() => {
    LinkHopp.init({ apiKey: 'YOUR_API_KEY' });

    (async () => {
      // Cold start link
      const initialLink = await LinkHopp.getInitialLink();
      if (initialLink) {
        navigateTo(initialLink.destinationUrl);
        return;
      }

      // Deferred deep link (post-install)
      const deferred = await LinkHopp.checkDeferredLink();
      if (deferred) {
        navigateTo(deferred.destinationUrl);
      }
    })();

    // Warm start links
    LinkHopp.handleLink((link) => {
      navigateTo(link.destinationUrl);
    });

    return () => {
      LinkHopp.dispose();
    };
  }, []);

  return <YourApp />;
}
```

### 6. Cleanup

Call `dispose()` when the root component unmounts to remove link listeners:

```ts
LinkHopp.dispose();
```

## LinkHoppLink Type

Every resolved link has the following shape:

| Field            | Type                      | Description                              |
| ---------------- | ------------------------- | ---------------------------------------- |
| `destinationUrl` | `string`                  | The target URL / deep link               |
| `metadata`       | `Record<string, unknown>` | Free-form metadata from the dashboard    |
| `campaign`       | `string \| null`          | Campaign name                            |
| `utmSource`      | `string \| null`          | UTM source parameter                     |
| `utmMedium`      | `string \| null`          | UTM medium parameter                     |
| `utmCampaign`    | `string \| null`          | UTM campaign parameter                   |
| `matchMethod`    | `string \| null`          | How the match was established            |

## Android: Install Referrer

To support Play Install Referrer on Android, create a native module named
`LinkHoppInstallReferrer` that exposes a `getInstallReferrer(): Promise<string>`
method. The SDK will pick it up automatically if linked. Without it, the SDK
gracefully falls back to fingerprint matching.

## License

MIT
