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

# Identity mapping

> How FloKit joins users across acquisition, subscription, and product systems.

FloKit joins identifiers from your MMP, subscription platform, and product event stream to build a complete user timeline — from first ad touch to subscription revenue. A well-configured identity graph is the foundation of accurate payback analysis.

***

## The identity graph

FloKit maintains a deterministic identity graph. When two identifiers are associated with the same user — for example, an `anonymous_id` linked to a `user_id` at login, or a `user_id` matched to an `app_user_id` in RevenueCat — FloKit merges their event histories into a single unified timeline. All payback calculations, cohort assignments, and LTV projections operate on the merged view.

***

## Identifiers

| Identifier                 | Source                                    | Purpose                                                    |
| -------------------------- | ----------------------------------------- | ---------------------------------------------------------- |
| `anonymous_id`             | Your app / Events API                     | Pre-login events; linked to `user_id` at account creation  |
| `user_id`                  | Your backend                              | Primary user identifier across your product                |
| `email_hash`               | Your backend (SHA-256 of lowercase email) | Cross-device matching; privacy-safe                        |
| `device_id`                | MMP (IDFA / GAID)                         | Device-level attribution join                              |
| `app_user_id`              | RevenueCat                                | RevenueCat's subscriber identifier; should match `user_id` |
| `mmp_customer_user_id`     | AppsFlyer / Adjust                        | MMP's customer ID; should match `user_id`                  |
| `subscription_customer_id` | Stripe                                    | Stripe customer object ID                                  |
| `campaign_id`              | MMP / ad platform                         | Campaign grouping                                          |
| `ad_set_id`                | MMP / ad platform                         | Ad set / ad group grouping                                 |
| `creative_id`              | MMP / ad platform                         | Creative-level attribution                                 |
| `paywall_id`               | Your app / Events API                     | Which paywall was shown                                    |
| `offer_id`                 | RevenueCat / Adapty / Events API          | Which promotional offer was applied                        |
| `transaction_id`           | App Store / Google Play / Stripe          | Revenue transaction; deduplicates refunds                  |

***

## Linking anonymous to identified

Send `user_id` alongside `anonymous_id` in any event after the user logs in or creates an account. FloKit retroactively attributes all prior pre-login events to the identified user.

```json theme={null}
{
  "event": "user_created",
  "user_id": "usr_abc123",
  "anonymous_id": "anon_xyz789",
  "timestamp": "2024-03-15T14:10:00Z",
  "properties": {
    "platform": "ios",
    "country": "US"
  }
}
```

After FloKit processes this event, all previous events carrying `anon_xyz789` — including install attribution — are merged into the `usr_abc123` identity.

***

## Identity validation

Go to **FloKit → Data → Identity** to inspect join rates across your user base. A healthy integration should show:

* **>90%** of install-attributed users joining to a subscription record within 7 days
* **Less than 5%** of subscription events with an unknown or unmapped `user_id`
* **>95%** anonymous-to-identified link rate within the session

***

## Common join gaps

**RevenueCat `app_user_id` does not match MMP `customer_user_id`**

Set the RevenueCat `app_user_id` to your backend `user_id` during authentication. Both the MMP and RevenueCat should use the same stable identifier so FloKit can join the two systems.

```swift theme={null}
// iOS — set during or immediately after authentication
Purchases.shared.logIn(yourBackendUserId) { customerInfo, created, error in
  // handle result
}
```

**Anonymous pre-install events not linking**

Send the same `anonymous_id` in both your pre-install product events and your MMP install callback. If the MMP fires an install event with a different or missing `anonymous_id`, FloKit cannot link pre-install behavior to the attributed install.

**Stripe customer not joining**

Include your backend `user_id` in the Stripe customer `metadata` object at customer creation time. FloKit reads this field when syncing Stripe webhook data.

```typescript theme={null}
const customer = await stripe.customers.create({
  email: user.email,
  metadata: {
    user_id: user.id,  // your backend user_id
  },
});
```
