# Let users enter a referral code

> Add a code field so people who hear a creator's code — in a podcast, a video or from a friend — are credited to that creator, plus prefill, errors and testing.

Links only work when someone taps them. When a creator says "use code MAYA" in a podcast, a video or a conversation, the listener installs from the store and has nothing to tap. A code field in your app closes that gap: the person types the code, and the creator is credited exactly — no matching involved, and no attribution window.

The same field also redeems free-access codes, so one field covers referrals, creator access and your own comp codes.

## When a code field matters

- Creators who talk about your app rather than link to it: podcasts, YouTube and TikTok videos, livestreams, word of mouth.
- Platforms where links aren't clickable, or audiences who search the store instead of tapping.
- Creators who need to try your premium features first — their `INFLU-` access code goes in the same field ([Creator access codes](https://docs.influ.to/platform/creator-access-codes.md)).

A code must be entered before the user's first purchase. After that, the user stays with whoever acquired them, or stays organic — see [Commissions and fees](https://docs.influ.to/platform/commissions.md#the-first-creator-keeps-the-user).

## Turn on manual code entry

Open **Settings → Advanced**, check **My app has the ReferralCodeInput UI component** and click **Save Changes**. The label names the ready-made component, but your own field counts too.

This setting tells creators they can share their code by voice — their dashboard then suggests "say your code" content — and it's required before you can turn on creator access codes. It doesn't change how codes are checked, so turn it on once the app version with the field is live.

## Where to put the field

- **Onboarding**, as a "Have a code?" step before the paywall. This catches most people, because the code is still fresh in their mind.
- **On the paywall**, as a small "Have a referral code?" link. Last chance before the first purchase.
- **In settings**, for creators redeeming an access code and people who skipped onboarding.

Keep it optional, with a skip button. Prefill it when InfluTo already knows the code (below), so the user only has to confirm.

## Use the ready-made component, or your own field

Each SDK ships a code field that checks the code with InfluTo, applies it and shows a valid or invalid state. Or call the SDK yourself: `applyCode()` checks the code with InfluTo and, if it's valid, applies it in one step. These are the same snippets the dashboard shows on **Setup & SDK**:

<!-- tabs -->

```tsx title="React Native / Expo"
// Validate, then apply a code the user typed
const result = await InfluTo.applyCode('FITGURU30');
if (result.valid && result.applied) {
  // Unlock the offer
}

// Or drop in the ready-made UI:
import { ReferralCodeInput } from '@influto/react-native-sdk/ui';
<ReferralCodeInput onApplied={(result) => {/* ... */}} />

// Free-access codes (INFLU-… or your comp codes): redeem with
// setReferralCode(code) after identifyUser (or pass appUserId) — grantsAccess
// === true means unlock premium now — and gate premium on (await InfluTo.checkAccess()).hasAccess.
```

```swift title="iOS (Swift)"
// Validate + apply a code the user typed
let result = await InfluTo.applyCode("FITGURU30")
if result.valid && result.applied == true {
  // Unlock the offer
}

// Or drop in the SwiftUI field: InfluToReferralCodeInput(onApplied: { result in … })
// Free-access codes (after identifyUser): setReferralCode(code).grantsAccess == true
// → unlock premium, and gate premium on (await InfluTo.checkAccess()).hasAccess.
```

```kotlin title="Android (Kotlin)"
// Validate + apply a code the user typed
val result = InfluTo.applyCode("FITGURU30")   // suspend
if (result.valid && result.applied == true) {
  // Unlock the offer
}

// Or the Compose field (android-sdk-ui): InfluToReferralCodeInput(onApplied = { result -> … })
// Free-access codes (after identifyUser): setReferralCode(code).grantsAccess == true
// → unlock premium, and gate premium on InfluTo.checkAccess().hasAccess.
```

```dart title="Flutter (Dart)"
// Validate + apply a code the user typed
final result = await InfluTo.instance.applyCode('FITGURU30');
if (result.valid && result.applied == true) {
  // Unlock the offer
}

// Or the ready-made widget: ReferralCodeInput(onApplied: (result) { … })
// Free-access codes (after identifyUser): (await setReferralCode(code)).grantsAccess
// == true → unlock premium, and gate premium on (await checkAccess()).hasAccess.
```

```ts title="Web / Capacitor / PWA"
// Validate, then apply a code the user typed
const result = await InfluTo.applyCode('FITGURU30');
if (result.valid && result.applied) {
  // Unlock the offer
}

// React / Ionic React: drop in the ready-made field
import { ReferralCodeInput } from '@influto/web/react';
<ReferralCodeInput onCodeApplied={(code) => {/* ... */}} />

// Free-access codes: (await InfluTo.setReferralCode(code)).grantsAccess → unlock
// premium, and gate premium on (await InfluTo.checkAccess()).hasAccess.
```

<!-- /tabs -->

| SDK | Component | Import / package |
|---|---|---|
| React Native / Expo | `ReferralCodeInput` | `@influto/react-native-sdk/ui` |
| iOS (Swift) | `InfluToReferralCodeInput` (SwiftUI) | module `InfluTo` |
| Android (Kotlin) | `InfluToReferralCodeInput` (Compose) | `to.influ:android-sdk-ui` |
| Flutter (Dart) | `ReferralCodeInput` | `package:influto/influto.dart` |
| Web / Capacitor / PWA | `ReferralCodeInput` (React) | `@influto/web/react` |

All components prefill the code by default and bind it to the user from `identifyUser` (or an `appUserId` you pass). InfluTo then knows which account the code belongs to, which helps match purchases and is required for free-access codes. Props, labels and styling: [UI components](https://docs.influ.to/reference/ui.md).

## Prefill the code

If the user arrived through a creator's link and InfluTo matched the install, `getPrefilledCode()` returns that creator's code (otherwise `null`). The components do this for you; in your own field:

<!-- tabs -->
```tsx title="React Native / Expo"
const code = await InfluTo.getPrefilledCode(); // string | null
```
```swift title="iOS (Swift)"
let code = await InfluTo.getPrefilledCode() // String?
```
```kotlin title="Android (Kotlin)"
val code = InfluTo.getPrefilledCode() // String? — not a suspend function
```
```dart title="Flutter (Dart)"
final code = await InfluTo.instance.getPrefilledCode(); // String?
```
```ts title="Web / Capacitor / PWA"
const code = await InfluTo.getPrefilledCode(); // string | null
```
<!-- /tabs -->

## Handle invalid codes

Input is forgiving: codes are trimmed and uppercased, spaces and invisible characters from copy-paste are removed, and InfluTo also tries common look-alikes (`I` and `L` for `1`, `O` for `0`). When a code still doesn't work, the validation result has `valid: false` and an error code:

| Error code | Meaning | Suggested message |
|---|---|---|
| `INVALID_FORMAT` | Not 4–20 characters after cleaning | "Codes are 4–20 letters and numbers." |
| `CODE_NOT_FOUND` | No such code in this app — or its campaign is paused or the creator is no longer active | "We couldn't find that code." |
| `CODE_EXPIRED` | A free-access code past its expiry date or out of uses | "This code has expired." |
| `NETWORK_ERROR` | The SDK couldn't reach InfluTo, or isn't initialized | "Couldn't check the code. Try again." |

The field is `error_code` in React Native and web, and `errorCode` in iOS, Android and Flutter (an enum on Android). Let users try again or skip; never block onboarding on a failed code.

## Keep creators' names private by default

When a code is valid, the response includes the campaign and, for creator codes, the creator's name. The components show neither unless you opt in with `showCampaignName` or `showReferrerName`. Show a creator's name only if they've agreed to it — a generic "Code applied" is enough for most apps.

## Free-access codes in the same field

`INFLU-` creator codes and your own comp codes from **Free Access Codes** go in the same field. They don't earn commission; they unlock premium. When one is applied, the validation result's campaign type is `FREE_ACCESS`, and `setReferralCode()` returns `grantsAccess: true`. Gate premium on `checkAccess().hasAccess` as well as your store entitlement. Details: [Creator access codes](https://docs.influ.to/platform/creator-access-codes.md).

## Test a code

- Referral codes validate only while their campaign is **Active** and the creator is active, so you need an activated campaign with at least one creator. You can't join your own organization's campaigns, so invite a colleague or a second email address you control. See [Invite creators](https://docs.influ.to/platform/invite-influencers.md).
- To test the field itself without a creator, create a free-access code on **Free Access Codes**. It doesn't need a campaign.
- Watch **Real-Time Events** while you apply the code. Applying a creator's code counts as a click and an install for that creator in your stats, so test with a test creator, not a real one.
- Then make a sandbox purchase and check it arrives attributed: [Verify the integration](https://docs.influ.to/integrations/testing.md).

## Next

<!-- cards -->
- [Give referred users a better offer](https://docs.influ.to/guides/referral-offers.md) — Show a different paywall to people who entered a code.
- [UI components](https://docs.influ.to/reference/ui.md) — Every prop of the ready-made code field.
- [SDK reference](https://docs.influ.to/reference/sdk.md) — `validateCode`, `applyCode`, `setReferralCode` and `getPrefilledCode` on every platform.
<!-- /cards -->
