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

# User Profile Data Model

> How Cryptique structures, builds, and enriches user profiles

<Info>
  This page explains the User Profile data model — what a profile contains and how it's built. For the SDK methods used to set and update profile properties, see the [People SDK Reference](/data-in/sdk-reference/people).
</Info>

## Overview

A user profile in Cryptique is the unified record for a single person. It aggregates three streams of data: off-chain behavioral events, connected wallet addresses, and on-chain transactions. Every profile is keyed on a `distinct_id`.

## Profile Structure

```javascript theme={null}
{
  // Identity
  "distinct_id": "user_12345",
  "user_identity_id": "uuid-xxx-xxx",
  
  // Core properties
  "email": "user@example.com",
  "name": "John Doe",
  
  // Lifecycle (auto-computed)
  "first_seen": "2024-01-01T00:00:00Z",
  "last_seen": "2024-01-15T10:30:00Z",
  "session_count": 47,
  "event_count": 1250,
  
  // Custom properties (set via SDK)
  "plan": "pro",
  "referral_source": "twitter",
  "onboarding_completed": true,
  
  // Web3 identity
  "is_web3_user": true,
  "wallets": [
    "0x1234567890abcdef1234567890abcdef12345678",
    "0xabcdef1234567890abcdef1234567890abcdef12"
  ],
  "primary_wallet": "0x1234567890abcdef1234567890abcdef12345678",
  
  // Wallet enrichment (auto-added from on-chain data)
  "wallet_age_days": 847,
  "total_transaction_count": 523,
  "net_worth_usd": 42500,
  "eth_balance": 15.5,
  "is_whale": true,
  "dapps_used": ["uniswap", "aave", "opensea"]
}
```

## How Profiles Are Created

### Step 1 — Anonymous profile

When a user first visits your site, Cryptique creates an anonymous profile with a generated `distinct_id` (e.g. `anon_abc123`). This profile immediately starts accumulating behavioral events.

### Step 2 — Identity resolution

When you call `Cryptique.identify('your_user_id')`, the anonymous profile is merged into (or converted to) an identified profile keyed on your ID. See the [Identify SDK Reference](/data-in/sdk-reference/identify) for full merge behavior.

### Step 3 — Property enrichment

Profile properties are added from these sources:

| Source                        | How                                                                                         |
| ----------------------------- | ------------------------------------------------------------------------------------------- |
| `identify()`                  | Sets the `distinct_id`                                                                      |
| `people.set/increment/append` | Sets custom properties via SDK                                                              |
| `Cryptique.walletAddress()`   | Links a wallet address to the profile                                                       |
| Wallet enrichment (automatic) | Adds on-chain properties once a wallet is linked                                            |
| `identify()` response         | Can restore **group memberships** server-side (see [Groups](/data-in/sdk-reference/groups)) |

**Groups** (companies, workspaces, etc.) are modeled separately from the user profile: you assign the user with `set_group` and set entity-level properties with `get_group(key, id).set(...)`.

## Wallet Enrichment

Once a wallet address is linked to a profile, Cryptique automatically queries the blockchain and adds the following properties:

| Property                                  | Description                                         |
| ----------------------------------------- | --------------------------------------------------- |
| `wallet_age_days`                         | Days since the wallet's first transaction           |
| `total_transaction_count`                 | Total transactions across all tracked chains        |
| `net_worth_usd`                           | Approximate portfolio value across supported chains |
| `eth_balance` (and per-chain equivalents) | Native token balance per chain                      |
| `dapps_used`                              | List of dApps the wallet has interacted with        |
| `is_whale`                                | Boolean, derived from net worth threshold           |

Enrichment runs automatically — no additional SDK calls are required. Data covers all 35+ supported chains.

## Profile Timeline

In the dashboard, each profile displays a unified timeline of all off-chain events and on-chain transactions:

```
user_12345 Timeline
───────────────────
Jan 1, 10:00  │ page_view         │ Landing page
Jan 1, 10:02  │ element_click     │ "Learn More" button
Jan 2, 14:30  │ wallet_connected  │ custom event + walletAddress()
Jan 2, 14:35  │ swap_initiated    │ ETH → USDC
Jan 2, 14:36  │ [Transaction]     │ swapExactTokensForTokens
Jan 5, 09:00  │ identify          │ email: user@example.com
Jan 5, 09:05  │ people.set        │ plan: pro
```

## Searching Profiles

Find any profile by:

* `distinct_id` — direct lookup
* `wallet_address` — finds any profile with that wallet linked
* `email` — if set via `identify()` or `people.set()`
* Any custom property — e.g. `plan = 'enterprise'`

## Profile Properties vs Event Properties

|             | Profile Properties                         | Event Properties                       |
| ----------- | ------------------------------------------ | -------------------------------------- |
| Scope       | User-level                                 | Single event                           |
| Persistence | Stored on profile, mutable                 | Immutable, stored with event           |
| How to set  | `people.set()`, `people.increment()`, etc. | Second argument to `Cryptique.track()` |
| Use case    | Who the user is                            | What happened in this event            |

## Privacy

Wallet addresses are stored as-is and are pseudonymous — they are not inherently linked to a real-world identity unless the user explicitly provides identifying information (e.g. via `identify()` with an email). See [Privacy & Compliance](/admin/privacy-and-compliance) for full details on how wallet data is handled.

## Next Steps

<CardGroup cols={2}>
  <Card title="People SDK Reference" icon="code" href="/data-in/sdk-reference/people">
    Set and manage profile properties
  </Card>

  <Card title="Groups" icon="users" href="/data-in/sdk-reference/groups">
    Companies, teams, and group profiles
  </Card>

  <Card title="Wallet Methods" icon="wallet" href="/data-in/sdk-reference/wallet">
    Link wallet addresses to profiles
  </Card>
</CardGroup>
