Skip to content

bug: uniqueViewers count in /api/analytics/overview is inflated — groupBy(['viewerId', 'viewerIp']) produces a Cartesian product, not a true distinct-viewer count #436

@Srejoye

Description

@Srejoye

Description:

The /api/analytics/overview endpoint computes unique viewer count via:

const uniqueViewersQuery = await app.prisma.cardView.groupBy({
  by: ['viewerId', 'viewerIp'],
  where: { ownerId: userId },
});
const uniqueViewers = uniqueViewersQuery.length;

Grouping by the composite key (viewerId, viewerIp) means a single authenticated viewer who visits from two different IP addresses generates two group rows, and an anonymous viewer (viewerId = null) with three different IPs generates three rows — all counted as separate unique viewers. The result can massively overcount uniqueness, especially for anonymous visitors where viewerId is null and viewerIp varies (mobile networks, VPNs, proxies).

The comment in the code even acknowledges that the correct query is COUNT(DISTINCT viewer_id), but the implemented workaround does not actually approximate that.

Affected file: apps/backend/src/routes/analytics.ts (lines 72–78)

Steps to reproduce:

  1. A logged-in viewer visits a profile from two different network connections (two IPs).
  2. uniqueViewers returns 2 for that single viewer.
  3. Ten anonymous web scrapers visiting from different IPs each increment the counter by 1, regardless of whether they are the same agent.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

Status
In progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions