Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@steven-tey
Copy link
Collaborator

@steven-tey steven-tey commented Oct 7, 2025

Summary by CodeRabbit

  • New Features

    • Identity-based deduplication now used for clicks, opens, and visits for more reliable tracking.
  • Bug Fixes

    • Reduced duplicate tracking events by switching cache keying from IP-derived to identity-derived keys.
  • Refactor

    • Unified tracking and caching flows to use an identity hash across recording and cache lookups.
  • Privacy

    • Less reliance on raw IPs while preserving geo-dependent behavior where applicable.

@vercel
Copy link
Contributor

vercel bot commented Oct 7, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
dub Ready Ready Preview Oct 8, 2025 0:58am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 7, 2025

Walkthrough

Replaces IP-based deduplication and cache keying with identityHash across tracking routes, middleware, record-click cache API, and Tinybird recording; updates function signatures and cache key construction, and includes identity_hash in event payloads.

Changes

Cohort / File(s) Summary
API routes: identityHash-based cache keys
apps/web/app/(ee)/api/track/click/route.ts, apps/web/app/(ee)/api/track/open/route.ts, apps/web/app/(ee)/api/track/visit/route.ts
Import and await getIdentityHash(req); replace cache key construction and Redis lookups to use identityHash instead of ip; preserve link lookup, workspace validation, waitUntil usage, and response shaping.
Record click cache API change
apps/web/lib/api/links/record-click-cache.ts
Rename KeyProps.ipidentityHash; update set, get, and _createKey signatures and key string to incorporate identityHash; export updated recordClickCache instance.
Middleware: identityHash lookup
apps/web/lib/middleware/link.ts
Remove ipAddress/LOCALHOST_IP reliance; import and await getIdentityHash(req) when caching/retrieving clickId; query recordClickCache with { domain, key, identityHash }; retain geolocation logic.
Tinybird click recording flow
apps/web/lib/tinybird/record-click.ts
Compute identityHash early for deduplication and cache lookups/sets; use identityHash in cache operations and include identity_hash in payload; compute ip later only for conditional EU handling; remove duplicate identityHash creation.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client
  participant Route as Edge/API Route
  participant ID as getIdentityHash
  participant Cache as recordClickCache (Redis)
  participant TB as Tinybird

  rect rgba(230,240,255,0.5)
    Client->>Route: POST /track (click/open/visit)
    Route->>ID: getIdentityHash(req)
    ID-->>Route: identityHash
    Route->>Cache: get({domain,key,identityHash})
    alt Cache hit
      Cache-->>Route: cached clickId/link
      Route-->>Client: 200 with cached result
    else Cache miss
      Route->>TB: recordClick(req, identityHash)
      TB->>Cache: set({domain,key,identityHash,clickId})
      TB-->>Route: recorded clickId/payload
      Route-->>Client: 200 with result
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Add click not record logs #2545 — Modifies apps/web/lib/tinybird/record-click.ts and click-recording logic; overlaps with identityHash-based dedup/cache changes.
  • Add /track/open #2683 — Updates /track/open route and cache key logic; directly overlaps with cache keying changes to identityHash.
  • Improve click caches #2470 — Refactors click caching layer and naming; intersects with record-click-cache API/signature edits.

Suggested reviewers

  • devkiran

Poem

A hop, a hash, a tiny cheer—
I trade the rain of IP for clear.
My burrow stores each tracked delight,
identity threads the quiet night.
Thump! metrics dance beneath moonlight. 🥕🐇

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly summarizes the PR’s intent to switch the recordClickCache implementation from IP-based keys to identityHash-based keys, which is the central change in this changeset. It is concise, specific, and free of extraneous terms, making it easy for a teammate scanning history to understand the primary update. Because it directly references the main change without noise, it meets the criteria for a clear and effective pull request title.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch identity-hash-click-cache

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 and usage tips.

@steven-tey
Copy link
Collaborator Author

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 8, 2025

✅ Actions performed

Full review triggered.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 26873a7 and 3741e7d.

📒 Files selected for processing (6)
  • apps/web/app/(ee)/api/track/click/route.ts (2 hunks)
  • apps/web/app/(ee)/api/track/open/route.ts (3 hunks)
  • apps/web/app/(ee)/api/track/visit/route.ts (2 hunks)
  • apps/web/lib/api/links/record-click-cache.ts (1 hunks)
  • apps/web/lib/middleware/link.ts (3 hunks)
  • apps/web/lib/tinybird/record-click.ts (3 hunks)
🔇 Additional comments (6)
apps/web/app/(ee)/api/track/open/route.ts (1)

6-6: LGTM! identityHash integration is correct.

The migration from IP-based to identityHash-based cache keys is properly implemented:

  • getIdentityHash is imported and called
  • The result is used in recordClickCache._createKey for cached click lookup

Note: The deepLinkClickCache (lines 32-56) still uses IP-based keys, which appears to be intentional as it's a separate caching mechanism for deep link data.

Also applies to: 29-29, 75-75

apps/web/app/(ee)/api/track/visit/route.ts (1)

7-7: LGTM! Clean migration to identityHash.

The changes correctly implement the identityHash-based cache keying:

  • Proper import of getIdentityHash
  • Removed unused LOCALHOST_IP and ipAddress imports
  • identityHash is computed and used in recordClickCache._createKey

The migration is clean and consistent with other track routes.

Also applies to: 12-13, 37-37, 40-40

apps/web/lib/middleware/link.ts (1)

5-5: LGTM! Middleware correctly migrated to identityHash.

The middleware properly implements identityHash-based cache lookups:

  • getIdentityHash imported and called conditionally when shouldCacheClickId is true
  • identityHash is used in recordClickCache.get for cached click retrieval
  • The geolocation import remains as it's still needed for geo-targeting logic (separate from cache keying)

The conditional computation of identityHash (only when needed) is efficient.

Also applies to: 253-256

apps/web/app/(ee)/api/track/click/route.ts (1)

11-11: LGTM! Track click route properly migrated.

The changes implement identityHash-based cache keying correctly:

  • getIdentityHash is imported from the correct path
  • Unused LOCALHOST_IP and ipAddress imports removed
  • identityHash is computed and used in recordClickCache._createKey

The migration is consistent with other track routes.

Also applies to: 19-20, 56-56, 61-61

apps/web/lib/tinybird/record-click.ts (1)

87-87: LGTM! Complete migration to identityHash-based deduplication.

The record-click function correctly implements identityHash-based deduplication:

  • identityHash is computed early (line 87)
  • Used for deduplication checks via recordClickCache.get (lines 93-97)
  • Used for caching via recordClickCache.set (line 186)
  • Added to the analytics payload as identity_hash (line 131)

Note: IP is still collected (line 122) and conditionally included in the analytics payload (lines 135-137) based on EU country logic. This is intentional and correct—IP is used for analytics but not for deduplication.

Also applies to: 93-97, 186-186

apps/web/lib/api/links/record-click-cache.ts (1)

13-26: identityHash always supplied
The sole call to recordClickCache.set uses getIdentityHash(req), which always returns a non-empty SHA256 string.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/web/lib/api/links/record-click-cache.ts (1)

34-36: Consider validating identityHash format.

While the current implementation is correct, consider adding validation to ensure identityHash is non-empty and doesn't contain problematic characters (e.g., colons that could interfere with the key structure). However, this validation may be better placed at the caller level where identityHash is generated.

Example validation in _createKey:

 _createKey({ domain, key, identityHash }: KeyProps) {
+  if (!identityHash || identityHash.includes(':')) {
+    throw new Error('Invalid identityHash for cache key');
+  }
   return `recordClick:${domain}:${key}:${identityHash}`;
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3741e7d and 8de472e.

📒 Files selected for processing (1)
  • apps/web/lib/api/links/record-click-cache.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
apps/web/lib/api/links/record-click-cache.ts (2)
apps/web/lib/upstash/redis.ts (1)
  • redis (4-7)
apps/web/lib/api/links/cache.ts (1)
  • CACHE_EXPIRATION (11-11)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (2)
apps/web/lib/api/links/record-click-cache.ts (2)

6-10: Previous concern addressed: identityHash is now required.

The identityHash property is now typed as string (non-optional), which resolves the cache key collision concern raised in the previous review. This ensures that every cache key will have a valid identityHash component.


13-36: LGTM! Clean refactor from IP to identityHash.

All method signatures (set, get, _createKey) have been consistently updated to use identityHash instead of ip. The cache key format recordClick:${domain}:${key}:${identityHash} is well-structured and appropriately scoped.

Note: During deployment, old IP-based cache entries will become inaccessible and new identityHash-based entries will be created. This is acceptable given the 1-hour TTL—existing entries will expire naturally without impacting functionality.

@steven-tey steven-tey merged commit dcc5196 into main Oct 8, 2025
8 checks passed
@steven-tey steven-tey deleted the identity-hash-click-cache branch October 8, 2025 03:10
@coderabbitai coderabbitai bot mentioned this pull request Nov 28, 2025
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.

2 participants