Skip to content

Feature Request: Analytics Endpoint for Card Views (Privacy-Preserving)Β #440

@aryan24cse109-dev

Description

@aryan24cse109-dev

πŸ“Œ Problem Statement

Currently, DevCard has no way for users to know how many times their card was viewed or which links were tapped. This is a significant missing feature β€” developers sharing their DevCard at hackathons, conferences, or on resumes have zero visibility into engagement.

There is also no backend infrastructure for tracking these events in a privacy-respecting way. Without this, users can't measure the impact of their DevCard.


🎯 Proposed Solution

Build a server-side, privacy-preserving analytics backend with the following components:

1. Database Schema (new tables)

-- Tracks card view counts (aggregated, no personal data)
card_views (
  id           UUID PRIMARY KEY,
  card_id      VARCHAR NOT NULL,
  viewed_at    TIMESTAMP NOT NULL,
  country_code VARCHAR(2),        -- from CF-IPCountry header, NOT raw IP
  referrer     VARCHAR            -- domain only, e.g. "twitter.com"
)

-- Tracks individual link tap events
card_link_taps (
  id           UUID PRIMARY KEY,
  card_id      VARCHAR NOT NULL,
  platform     VARCHAR NOT NULL,  -- "github" | "linkedin" | "twitter" etc.
  tapped_at    TIMESTAMP NOT NULL
)

2. New API Endpoints

Method Endpoint Description
POST /api/analytics/view/:cardId Record a card view (server-side, no IP stored)
POST /api/analytics/tap/:cardId Record a link tap with platform name
GET /api/analytics/:cardId Fetch aggregated stats for the card owner

3. Response Shape for GET /api/analytics/:cardId

{
  "cardId": "abc123",
  "totalViews": 342,
  "last7Days": 87,
  "last30Days": 210,
  "topReferrers": ["twitter.com", "linkedin.com"],
  "linkTaps": {
    "github": 120,
    "linkedin": 95,
    "twitter": 60
  }
}

4. Privacy Rules (strict)

  • ❌ No raw IP addresses stored β€” ever
  • ❌ No User-Agent strings stored
  • βœ… Only country code extracted from CF-IPCountry header (Vercel/Cloudflare provides this)
  • βœ… Only domain extracted from Referer header (no full URL paths)
  • βœ… Only the card owner can access their own analytics via authenticated GET
  • βœ… POST endpoints are public (called client-side on card view/tap)

πŸ› οΈ Implementation Plan

  • Add card_views and card_link_taps tables to DB schema (migration file)
  • Create POST /api/analytics/view/:cardId β€” insert aggregated view record
  • Create POST /api/analytics/tap/:cardId β€” insert tap event with platform
  • Create GET /api/analytics/:cardId β€” auth-protected, returns aggregated stats
  • Add auth middleware to GET endpoint (only card owner can read)
  • Add rate limiting on POST endpoints to prevent fake inflation (e.g., 1 view per IP per card per hour using a hashed IP)
  • Write unit tests for all 3 endpoints
  • Document endpoints in README / API docs

πŸ”’ Security Considerations

  • The GET endpoint must validate that the requesting user owns the cardId
  • POST endpoints should be rate-limited per hashed-IP (hash + discard raw IP immediately)
  • Add bot detection heuristics (e.g., skip recording if User-Agent is a known bot β€” but don't store the UA)

πŸ“¦ Tech Stack Expected

  • Next.js API Routes (/app/api/ or /pages/api/)
  • Prisma / existing DB ORM used in the project
  • Redis (optional, for rate limiting β€” can use Upstash if not already present)

βœ… Acceptance Criteria

  • Card views are recorded on every public card visit without storing PII
  • Link taps are recorded per platform when a user clicks a social link
  • Authenticated GET endpoint returns correct aggregated stats
  • No raw IP, User-Agent, or personal data is written to the database at any point
  • All 3 endpoints have test coverage
  • Rate limiting prevents view count inflation

🏷️ Labels Suggested

enhancement backend privacy api intermediate gssoc26


πŸ‘€ Contributor Note

I am a GSSOC 2026 contributor and would like to be assigned this issue. I have experience with Next.js API routes, Prisma, and REST API design. Happy to discuss the implementation approach before starting.

Metadata

Metadata

Labels

criticalIncludes schema, architecture, or other critical core functionality changes.enhancementNew feature or requestfeature

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions