Skip to content

Commit 1aeaf42

Browse files
yosriadyclaude
andauthored
docs(catalog): add user_profiles_mv and user_labels tables (#88)
Document two new warehouse tables in the data catalog: - user_profiles_mv: project-scoped, first-party identify traits, placed next to identities as the identity-data counterpart to wallet_profiles_mv. Flagged as an AggregatingMergeTree with a -Merge / argMaxIfMerge querying note. - user_labels: project-scoped labels you assign to addresses, placed next to wallet_profiles_labels (its global counterpart). Omits the internal _is_deleted column to match the wallet_profiles_labels entry. Also list user_profiles_mv in the aggregate-tables section and add an argMaxIf row to the quick reference. Claude-Session: https://claude.ai/code/session_01XeF9u7YLwBCXtsADz9esGH Co-authored-by: Claude <noreply@anthropic.com>
1 parent f2c1d97 commit 1aeaf42

1 file changed

Lines changed: 56 additions & 1 deletion

File tree

data/catalog.mdx

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,43 @@ LIMIT 20
364364

365365
---
366366

367+
### user_profiles_mv
368+
369+
Project-scoped, first-party **user profile traits** captured from `identify` events. One row per `address`, holding the latest value of each trait. This is the identity-data counterpart to `wallet_profiles_mv` (which holds public onchain profile data); `user_profiles_mv` holds the traits *you* send.
370+
371+
**Use cases:** User enrichment, first-party identity resolution, personalization, outreach
372+
373+
<Warning>
374+
This is an **aggregate table** (`AggregatingMergeTree`). Each trait is stored as an aggregate state, so read it with `-Merge` functions (e.g. `argMaxIfMerge(email)`) and always `GROUP BY address`. Never use `SELECT *`. See [Working with Aggregate Tables](#working-with-aggregate-tables).
375+
</Warning>
376+
377+
| Column | Type | Description |
378+
|--------|------|-------------|
379+
| `address` | String | Wallet address (primary key within your project) |
380+
| `user_id` | String | Your own external user identifier |
381+
| `display_name` | String | Display name |
382+
| `email` | String | Email address |
383+
| `farcaster`, `discord`, `twitter`, `telegram`, `instagram`, `github`, `linkedin`, `facebook`, `tiktok`, `youtube`, `reddit` | String | Social handles |
384+
| `website` | String | Website URL |
385+
| `ens`, `lens`, `basenames`, `linea` | String | Web3 name-service handles |
386+
| `avatar` | String | Avatar image URL |
387+
| `description` | String | Bio / description |
388+
| `location` | String | Location |
389+
| `updated_at` | DateTime | Last time any trait was updated |
390+
391+
**Example:**
392+
393+
```sql
394+
SELECT
395+
address,
396+
argMaxIfMerge(display_name) AS display_name,
397+
argMaxIfMerge(email) AS email
398+
FROM user_profiles_mv
399+
GROUP BY address
400+
```
401+
402+
---
403+
367404
### wallet_profiles_mv
368405

369406
Global wallet profile data aggregated across all chains. One row per wallet address with social profiles, contact info, and net worth.
@@ -509,6 +546,23 @@ Wallet labels and tags for categorizing and filtering wallet addresses. Each row
509546

510547
---
511548

549+
### user_labels
550+
551+
Project-scoped **labels and tags you assign to wallet addresses** (e.g. your own segments, scores, or categories). The latest value per `(tag_id, address, chain_id)` is kept automatically. This is the project-specific counterpart to `wallet_profiles_labels`, which holds **global** labels supplied by Formo's wallet profiler.
552+
553+
**Use cases:** Custom segmentation, scoring, audience building, tagging
554+
555+
| Column | Type | Description |
556+
|--------|------|-------------|
557+
| `address` | String | Labeled wallet address |
558+
| `chain_id` | String | Chain the label applies to (`-` for all chains) |
559+
| `tag_id` | String | Label / tag identifier |
560+
| `value` | String | Optional label value or score |
561+
| `source` | String | System that supplied the label |
562+
| `timestamp` | DateTime | When the label was last updated |
563+
564+
---
565+
512566
## Table relationships
513567

514568
```
@@ -646,7 +700,7 @@ ORDER BY date
646700

647701
## Working with aggregate tables
648702

649-
Several tables (`users`, `anonymous_users`, `sessions`, `sources`, `identities`) use ClickHouse [AggregateFunction](https://clickhouse.com/docs/en/sql-reference/data-types/aggregatefunction) types. These store intermediate aggregation states, not final values.
703+
Several tables (`users`, `anonymous_users`, `sessions`, `sources`, `identities`, `user_profiles_mv`) use ClickHouse [AggregateFunction](https://clickhouse.com/docs/en/sql-reference/data-types/aggregatefunction) types. These store intermediate aggregation states, not final values.
650704

651705
### Rules
652706

@@ -660,6 +714,7 @@ Several tables (`users`, `anonymous_users`, `sessions`, `sources`, `identities`)
660714
| Aggregate Type | Query Pattern | Example |
661715
|---------------|--------------|---------|
662716
| `AggregateFunction(argMax, T, DateTime)` | `argMaxMerge(col)` | `argMaxMerge(location)` |
717+
| `AggregateFunction(argMaxIf, T, DateTime, UInt8)` | `argMaxIfMerge(col)` | `argMaxIfMerge(email)` |
663718
| `AggregateFunction(argMin, T, DateTime)` | `argMinMerge(col)` | `argMinMerge(first_utm_source)` |
664719
| `AggregateFunction(uniq, T)` | `uniqMerge(col)` | `uniqMerge(num_sessions)` |
665720
| `AggregateFunction(count)` | `countMerge(col)` | `countMerge(hits)` |

0 commit comments

Comments
 (0)