Skip to content

feat: Profile identification#593

Open
Blaumaus wants to merge 2 commits into
mainfrom
feature/profile-identification
Open

feat: Profile identification#593
Blaumaus wants to merge 2 commits into
mainfrom
feature/profile-identification

Conversation

@Blaumaus

@Blaumaus Blaumaus commented Jul 17, 2026

Copy link
Copy Markdown
Member

Changes

If applicable, please describe what changes were made in this pull request.

Community Edition support

  • Your feature is implemented for the Swetrix Community Edition
  • This PR only updates the Cloud (Enterprise) Edition code (e.g. Paddle webhooks, blog, payouts, etc.)

Database migrations

  • Clickhouse / MySQL migrations added for this PR
  • No table schemas changed in this PR

Documentation

  • You have updated the documentation according to your PR
  • This PR did not change any publicly documented endpoints

Summary by CodeRabbit

  • New Features
    • Added visitor identification for browser and server-side tracking, including a new identify flow and endpoint support.
    • Links anonymous activity to a stable identified profile and updates session attribution accordingly (including linked-history visibility).
    • Adds safer handling for invalid/unsafe profile identifiers and deduplicates repeated identify calls.
  • Documentation
    • Expanded identification, reset/logout behavior, and API usage with examples.
    • Clarified anonymous vs identified profile ID formats and how attribution changes after identification.

@Blaumaus Blaumaus self-assigned this Jul 17, 2026
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. πŸŽ‰

ℹ️ Recent review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e69705aa-22d0-44ac-9c5c-47791a0d541f

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 71d77e5 and 7fb7874.

πŸ“’ Files selected for processing (6)
  • backend/apps/cloud/src/analytics/analytics.controller.ts
  • backend/apps/cloud/src/analytics/analytics.service.ts
  • backend/apps/cloud/src/analytics/bot-detection.service.ts
  • backend/apps/community/src/analytics/analytics.controller.ts
  • backend/apps/community/src/analytics/analytics.service.ts
  • backend/apps/community/src/analytics/bot-detection.service.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • backend/apps/community/src/analytics/analytics.controller.ts
  • backend/apps/cloud/src/analytics/analytics.controller.ts
  • backend/apps/community/src/analytics/analytics.service.ts
  • backend/apps/cloud/src/analytics/analytics.service.ts

πŸ“ Walkthrough

Walkthrough

Adds visitor identification through public analytics endpoints, ClickHouse profile aliases, canonicalized analytics queries, JavaScript and Node tracker APIs, and documentation for identify/reset behavior.

Changes

Visitor identity linking

Layer / File(s) Summary
Identity ingestion and alias persistence
backend/apps/*/src/analytics/..., backend/migrations/clickhouse/*
Adds validated identify payloads, public identify endpoints, profile ID safeguards, alias resolution helpers, bot endpoint support, and the profile_aliases ClickHouse table.
Canonical identity in analytics queries
backend/apps/*/src/analytics/analytics.service.ts
Applies anonymous-to-identified alias resolution across session, replay, profile, activity, pageflow, funnel, and journey queries.
Tracker identity APIs
packages/tracker-js/src/*, packages/tracker-node/src/index.ts
Adds identify() and reset() behavior, server-side identify requests, deduplication, cache clearing, and identified profile ID retrieval.
Identity API documentation
docs/content/docs/*, packages/tracker-*/README.md
Documents identify/reset usage, payloads, linking rules, profile behavior, endpoint responses, and identifier requirements.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Visitor
  participant Tracker
  participant IdentifyAPI
  participant AnalyticsService
  participant AnalyticsStore
  Visitor->>Tracker: identify(profileId)
  Tracker->>IdentifyAPI: POST identify
  IdentifyAPI->>AnalyticsService: validate request and resolve identities
  AnalyticsService->>AnalyticsStore: link anonymous and identified profiles
  IdentifyAPI-->>Tracker: return canonical profileId
  Tracker-->>Visitor: use identified profile for tracking
Loading

Possibly related PRs

  • Swetrix/swetrix#549: Both changes modify session profile ID normalization in analytics services.
πŸš₯ Pre-merge checks | βœ… 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The template is present, but the Changes section is still a placeholder and lacks an actual summary of the work. Replace the placeholder with a brief change summary and keep the completed support, migrations, and documentation checklists.
βœ… Passed checks (4 passed)
Check name Status Explanation
Title check βœ… Passed The title matches the main change: adding profile identification support.
Docstring Coverage βœ… Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check βœ… Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check βœ… Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
πŸ“ Generate docstrings
  • Create stacked PR
  • Commit on current branch
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/profile-identification

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
backend/apps/cloud/src/analytics/analytics.service.ts (1)

2466-2499: πŸš€ Performance & Scalability | πŸ”΅ Trivial | ⚑ Quick win

Consider negative caching for unlinked anon lookups.

getUserProfileForAnon only writes to Redis on a positive hit (Line 2494-2496). The overwhelmingly common case β€” an anonymous profile that was never identified β€” falls through to a profile_aliases ClickHouse query on every call. This runs on hot read paths (getSessionDetails, resolveProfileIdentity), so a short-lived negative cache (e.g. a sentinel value with a small TTL) would remove a per-request CH round-trip.

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/apps/cloud/src/analytics/analytics.service.ts` around lines 2466 -
2499, Update getUserProfileForAnon to cache unlinked lookups using a dedicated
sentinel value with a short TTL, return null when that sentinel is read, and
continue returning cached userProfileId values normally. Store the sentinel when
ClickHouse finds no userProfileId while preserving the existing positive-cache
behavior.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/apps/cloud/src/analytics/analytics.controller.ts`:
- Around line 3308-3320: Add the same rate-limit and bot checks used by the
other public ingestion routes to the identify handlers in
backend/apps/cloud/src/analytics/analytics.controller.ts (lines 3308-3320) and
backend/apps/community/src/analytics/analytics.controller.ts (lines 2799-2811),
applying them before validation or the profile-linking flow in identify. Ensure
both public endpoints invoke checkRateLimit and checkBot consistently.

---

Nitpick comments:
In `@backend/apps/cloud/src/analytics/analytics.service.ts`:
- Around line 2466-2499: Update getUserProfileForAnon to cache unlinked lookups
using a dedicated sentinel value with a short TTL, return null when that
sentinel is read, and continue returning cached userProfileId values normally.
Store the sentinel when ClickHouse finds no userProfileId while preserving the
existing positive-cache behavior.
πŸͺ„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c03edfbe-1647-4222-9c36-f7fe7ee91ce5

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 731744f and 71d77e5.

πŸ“’ Files selected for processing (17)
  • backend/apps/cloud/src/analytics/analytics.controller.ts
  • backend/apps/cloud/src/analytics/analytics.service.ts
  • backend/apps/cloud/src/analytics/dto/identify.dto.ts
  • backend/apps/community/src/analytics/analytics.controller.ts
  • backend/apps/community/src/analytics/analytics.service.ts
  • backend/apps/community/src/analytics/dto/identify.dto.ts
  • backend/migrations/clickhouse/2026_07_17_profile_aliases.js
  • backend/migrations/clickhouse/initialise_database.js
  • docs/content/docs/analytics-dashboard/profiles-and-sessions.mdx
  • docs/content/docs/api/events.mdx
  • docs/content/docs/script-reference.mdx
  • docs/content/docs/visitor-identification.mdx
  • packages/tracker-js/README.md
  • packages/tracker-js/src/Lib.ts
  • packages/tracker-js/src/index.ts
  • packages/tracker-node/README.md
  • packages/tracker-node/src/index.ts

Comment thread backend/apps/cloud/src/analytics/analytics.controller.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant